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