1 /*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "btstack_slip.c"
39
40 /*
41 * btstack_slip.c
42 * SLIP encoder/decoder
43 */
44
45 #include "btstack_slip.h"
46 #include "btstack_debug.h"
47
48 typedef enum {
49 SLIP_ENCODER_DEFAULT,
50 SLIP_ENCODER_SEND_C0,
51 SLIP_ENCODER_SEND_DC,
52 SLIP_ENCODER_SEND_DD
53 } btstack_slip_encoder_state_t;
54
55 // h5 slip state machine
56 typedef enum {
57 SLIP_DECODER_UNKNOWN = 1,
58 SLIP_DECODER_ACTIVE,
59 SLIP_DECODER_X_C0,
60 SLIP_DECODER_X_DB,
61 SLIP_DECODER_COMPLETE
62 } btstack_slip_decoder_state_t;
63
64
65 // encoder
66 static btstack_slip_encoder_state_t encoder_state;
67 static const uint8_t * encoder_data;
68 static uint16_t encoder_len;
69
70 // decoder
71 static btstack_slip_decoder_state_t decoder_state;
72 static uint8_t * decoder_buffer;
73 static uint16_t decoder_max_size;
74 static uint16_t decoder_pos;
75
76
77 // ENCODER
78
79 /**
80 * @brief Initialise SLIP encoder with data
81 * @param data
82 * @param len
83 */
btstack_slip_encoder_start(const uint8_t * data,uint16_t len)84 void btstack_slip_encoder_start(const uint8_t * data, uint16_t len){
85 // start with C0 SOF
86 encoder_state = SLIP_ENCODER_SEND_C0;
87 encoder_data = data;
88 encoder_len = len;
89 }
90
91 /**
92 * @brief Check if encoder has data ready
93 * @return True if data ready
94 */
btstack_slip_encoder_has_data(void)95 int btstack_slip_encoder_has_data(void){
96 if (encoder_state != SLIP_ENCODER_DEFAULT) return 1;
97 return encoder_len > 0u;
98 }
99
100 /**
101 * @brief Get next byte from encoder
102 * @return Next bytes from encoder
103 */
btstack_slip_encoder_get_byte(void)104 uint8_t btstack_slip_encoder_get_byte(void){
105 uint8_t next_byte;
106 switch (encoder_state){
107 case SLIP_ENCODER_DEFAULT:
108 next_byte = *encoder_data++;
109 encoder_len--;
110 switch (next_byte){
111 case BTSTACK_SLIP_SOF:
112 encoder_state = SLIP_ENCODER_SEND_DC;
113 next_byte = 0xdb;
114 break;
115 case 0xdb:
116 encoder_state = SLIP_ENCODER_SEND_DD;
117 next_byte = 0xdb;
118 default:
119 break;
120 }
121 break;
122 case SLIP_ENCODER_SEND_C0:
123 encoder_state = SLIP_ENCODER_DEFAULT;
124 return 0xc0;
125 case SLIP_ENCODER_SEND_DC:
126 encoder_state = SLIP_ENCODER_DEFAULT;
127 next_byte = 0xdc;
128 break;
129 case SLIP_ENCODER_SEND_DD:
130 encoder_state = SLIP_ENCODER_DEFAULT;
131 next_byte = 0x0dd;
132 break;
133 default:
134 log_error("btstack_slip_encoder_get_byte invalid state %x", encoder_state);
135 return 0x00;
136 }
137
138 // After last byte, send CO SOF again
139 if ((encoder_state == SLIP_ENCODER_DEFAULT) && (encoder_len == 0)){
140 encoder_state = SLIP_ENCODER_SEND_C0;
141 }
142 return next_byte;
143 }
144
145 // Decoder
146
btstack_slip_decoder_reset(void)147 static void btstack_slip_decoder_reset(void){
148 decoder_state = SLIP_DECODER_UNKNOWN;
149 decoder_pos = 0;
150 }
151
btstack_slip_decoder_store_byte(uint8_t input)152 static void btstack_slip_decoder_store_byte(uint8_t input){
153 if (decoder_pos >= decoder_max_size){
154 log_error("btstack_slip_decoder_store_byte: packet to long");
155 btstack_slip_decoder_reset();
156 }
157 decoder_buffer[decoder_pos++] = input;
158 }
159
160 /**
161 * @brief Initialise SLIP decoder with buffer
162 * @param buffer to store received data
163 * @param max_size of buffer
164 */
btstack_slip_decoder_init(uint8_t * buffer,uint16_t max_size)165 void btstack_slip_decoder_init(uint8_t * buffer, uint16_t max_size){
166 decoder_buffer = buffer;
167 decoder_max_size = max_size;
168 btstack_slip_decoder_reset();
169 }
170
171 /**
172 * @brief Process received byte
173 * @param data
174 */
175
btstack_slip_decoder_process(uint8_t input)176 void btstack_slip_decoder_process(uint8_t input){
177 switch(decoder_state){
178 case SLIP_DECODER_UNKNOWN:
179 if (input != BTSTACK_SLIP_SOF) break;
180 btstack_slip_decoder_reset();
181 decoder_state = SLIP_DECODER_X_C0;
182 break;
183 case SLIP_DECODER_COMPLETE:
184 log_error("btstack_slip_decoder_process called in state COMPLETE");
185 btstack_slip_decoder_reset();
186 break;
187 case SLIP_DECODER_X_C0:
188 switch(input){
189 case BTSTACK_SLIP_SOF:
190 break;
191 case 0xdb:
192 decoder_state = SLIP_DECODER_X_DB;
193 break;
194 default:
195 btstack_slip_decoder_store_byte(input);
196 decoder_state = SLIP_DECODER_ACTIVE;
197 break;
198 }
199 break;
200 case SLIP_DECODER_X_DB:
201 switch(input){
202 case 0xdc:
203 btstack_slip_decoder_store_byte(BTSTACK_SLIP_SOF);
204 decoder_state = SLIP_DECODER_ACTIVE;
205 break;
206 case 0xdd:
207 btstack_slip_decoder_store_byte(0xdb);
208 decoder_state = SLIP_DECODER_ACTIVE;
209 break;
210 default:
211 btstack_slip_decoder_reset();
212 break;
213 }
214 break;
215 case SLIP_DECODER_ACTIVE:
216 switch(input){
217 case BTSTACK_SLIP_SOF:
218 if (decoder_pos != 0){
219 decoder_state = SLIP_DECODER_COMPLETE;
220 } else {
221 btstack_slip_decoder_reset();
222 }
223 break;
224 case 0xdb:
225 decoder_state = SLIP_DECODER_X_DB;
226 break;
227 default:
228 btstack_slip_decoder_store_byte(input);
229 break;
230 }
231 break;
232 default:
233 btstack_assert(false);
234 break;
235 }
236 }
237
238 /**
239 * @brief Get size of decoded frame
240 * @return size of frame. Size = 0 => frame not complete
241 */
242
btstack_slip_decoder_frame_size(void)243 uint16_t btstack_slip_decoder_frame_size(void){
244 switch (decoder_state){
245 case SLIP_DECODER_COMPLETE:
246 return decoder_pos;
247 default:
248 return 0;
249 }
250 }
251