slip.c (3551B)
1#include "slip.h" 2 3#include <errno.h> 4 5enum { 6 SLIPDEC_START_STATE, 7 SLIPDEC_IN_FRAME_STATE, 8 SLIPDEC_ESC_STATE 9}; 10 11static int slip_decode_start(struct slip *slip, uint8_t rx_byte); 12static int slip_decode_inframe(struct slip *slip, uint8_t rx_byte); 13static int slip_decode_escseq(struct slip *slip, uint8_t rx_byte); 14 15static inline void 16store(uint8_t **cur, uint8_t *end, uint8_t byte) 17{ 18 if (*cur < end) *(*cur)++ = byte; 19} 20 21int 22slip_decode_start(struct slip *slip, uint8_t rx_byte) 23{ 24 /* wait for packet start */ 25 if (rx_byte == slip->start) { 26 slip->rx_index = 0; 27 slip->rx_state = SLIPDEC_IN_FRAME_STATE; 28 } 29 30 return 0; 31} 32 33int 34slip_decode_inframe(struct slip *slip, uint8_t rx_byte) 35{ 36 int rc; 37 38 if (rx_byte == slip->end) { 39 /* end of packet */ 40 slip->rx_packet(slip, slip->rx_buf, slip->rx_index, 41 slip->rx_packet_userdata); 42 slip->rx_state = SLIPDEC_START_STATE; 43 } else if (rx_byte == slip->start) { 44 /* malformed packet */ 45 if (slip->rx_restart) 46 slip->rx_restart(slip, rx_byte); 47 slip->rx_index = 0; 48 slip->rx_state = SLIPDEC_START_STATE; 49 } else if (rx_byte == slip->esc) { 50 /* escape sequence */ 51 slip->rx_state = SLIPDEC_ESC_STATE; 52 } else { 53 /* data byte */ 54 rc = slip_decode_store(slip, rx_byte); 55 if (rc) return rc; 56 } 57 58 return 0; 59} 60 61int 62slip_decode_escseq(struct slip *slip, uint8_t rx_byte) 63{ 64 uint8_t dec; 65 int rc; 66 67 dec = slip->esc_dec[rx_byte]; 68 if (slip->esc_active[dec]) { 69 rc = slip_decode_store(slip, dec); 70 if (rc) return rc; 71 slip->rx_state = SLIPDEC_IN_FRAME_STATE; 72 } else { 73 /* invalid contents */ 74 if (slip->rx_restart) 75 slip->rx_restart(slip, rx_byte); 76 slip->rx_state = SLIPDEC_START_STATE; 77 slip->rx_index = 0; 78 } 79 80 return 0; 81} 82 83int 84slip_init(struct slip *slip) 85{ 86 int i; 87 88 slip->rx_state = SLIPDEC_START_STATE; 89 90 slip->rx_index = 0; 91 slip->rx_buflen = 0; 92 slip->rx_buf = NULL; 93 94 if (!slip->rx_packet) return -EINVAL; 95 if (!slip->realloc) return -EINVAL; 96 if (slip->esc == slip->start) return -EINVAL; 97 if (slip->esc == slip->end) return -EINVAL; 98 99 /* build decode table */ 100 for (i = 0; i < 256; i++) 101 slip->esc_dec[slip->esc_enc[i]] = (uint8_t) i; 102 103 return 0; 104} 105 106void 107slip_deinit(struct slip *slip) 108{ 109 free(slip->rx_buf); 110} 111 112int 113slip_decode_store(struct slip *slip, uint8_t byte) 114{ 115 int rc; 116 117 if (slip->rx_index >= slip->rx_buflen) { 118 if (!slip->rx_buflen) 119 slip->rx_buflen = 256; 120 else 121 slip->rx_buflen *= 2; 122 rc = slip->realloc((void **)&slip->rx_buf, slip->rx_buflen); 123 if (rc) return rc; 124 } 125 slip->rx_buf[slip->rx_index++] = byte; 126 127 return 0; 128} 129 130int 131slip_decode(struct slip *slip, uint8_t* data, size_t size) 132{ 133 uint8_t rx_byte; 134 size_t i; 135 int rc; 136 137 for (i = 0; i < size; i++) { 138 rx_byte = data[i]; 139 switch (slip->rx_state) { 140 case SLIPDEC_START_STATE: 141 rc = slip_decode_start(slip, rx_byte); 142 break; 143 case SLIPDEC_IN_FRAME_STATE: 144 rc = slip_decode_inframe(slip, rx_byte); 145 break; 146 case SLIPDEC_ESC_STATE: 147 rc = slip_decode_escseq(slip, rx_byte); 148 break; 149 default: 150 rc = -EINVAL; 151 break; 152 } 153 if (rc) return rc; 154 } 155 156 return 0; 157} 158 159int 160slip_encode(struct slip *slip, uint8_t* out, size_t *outlen, size_t outcap, 161 uint8_t* in, size_t inlen) 162{ 163 uint8_t *pos, *end; 164 size_t i; 165 166 pos = out; 167 end = out + outcap; 168 169 store(&pos, end, slip->start); 170 171 for (i = 0; i < inlen && pos < end; i++) { 172 if (slip->esc_active[in[i]]) { 173 store(&pos, end, slip->esc); 174 store(&pos, end, slip->esc_enc[in[i]]); 175 } else { 176 store(&pos, end, in[i]); 177 } 178 } 179 180 store(&pos, end, slip->end); 181 182 if (pos >= end) return -ENOBUFS; 183 184 *outlen = (size_t) (pos - out); 185 186 return 0; 187}