xref: /btstack/src/btstack_slip.c (revision a8d51f092f1b660d0f6921369ad2bc3f9368296c)
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 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_slip.c"
39ab2c6ae4SMatthias Ringwald 
40ab67bfbbSMatthias Ringwald /*
41ab67bfbbSMatthias Ringwald  *  btstack_slip.c
42ab67bfbbSMatthias Ringwald  *  SLIP encoder/decoder
43ab67bfbbSMatthias Ringwald  */
44ab67bfbbSMatthias Ringwald 
45ab67bfbbSMatthias Ringwald #include "btstack_slip.h"
464d6feae0SMatthias Ringwald #include "btstack_debug.h"
47ab67bfbbSMatthias Ringwald 
48ab67bfbbSMatthias Ringwald typedef enum {
49ab67bfbbSMatthias Ringwald 	SLIP_ENCODER_DEFAULT,
504d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DC,
514d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DD
52ab67bfbbSMatthias Ringwald } btstack_slip_encoder_state_t;
53ab67bfbbSMatthias Ringwald 
544d6feae0SMatthias Ringwald // h5 slip state machine
554d6feae0SMatthias Ringwald typedef enum {
564d6feae0SMatthias Ringwald     SLIP_DECODER_UNKNOWN = 1,
574d6feae0SMatthias Ringwald     SLIP_DECODER_ACTIVE,
584d6feae0SMatthias Ringwald     SLIP_DECODER_X_C0,
594d6feae0SMatthias Ringwald     SLIP_DECODER_X_DB,
604d6feae0SMatthias Ringwald     SLIP_DECODER_COMPLETE
614d6feae0SMatthias Ringwald } btstack_slip_decoder_state_t;
624d6feae0SMatthias Ringwald 
634d6feae0SMatthias Ringwald 
644d6feae0SMatthias Ringwald // encoder
65ab67bfbbSMatthias Ringwald static btstack_slip_encoder_state_t encoder_state;
66ab67bfbbSMatthias Ringwald static const uint8_t * encoder_data;
67ab67bfbbSMatthias Ringwald static uint16_t  encoder_len;
68ab67bfbbSMatthias Ringwald 
694d6feae0SMatthias Ringwald // decoder
704d6feae0SMatthias Ringwald static btstack_slip_decoder_state_t decoder_state;
714d6feae0SMatthias Ringwald static uint8_t * decoder_buffer;
724d6feae0SMatthias Ringwald static uint16_t  decoder_max_size;
734d6feae0SMatthias Ringwald static uint16_t  decoder_pos;
744d6feae0SMatthias Ringwald 
754d6feae0SMatthias Ringwald 
76ab67bfbbSMatthias Ringwald // ENCODER
77ab67bfbbSMatthias Ringwald 
78ab67bfbbSMatthias Ringwald /**
79ab67bfbbSMatthias Ringwald  * @brief Initialise SLIP encoder with data
80ab67bfbbSMatthias Ringwald  * @param data
81ab67bfbbSMatthias Ringwald  * @param len
82ab67bfbbSMatthias Ringwald  */
83ab67bfbbSMatthias Ringwald void btstack_slip_encoder_start(const uint8_t * data, uint16_t len){
84ab67bfbbSMatthias Ringwald 	encoder_state = SLIP_ENCODER_DEFAULT;
85ab67bfbbSMatthias Ringwald 	encoder_data  = data;
86ab67bfbbSMatthias Ringwald 	encoder_len   = len;
87ab67bfbbSMatthias Ringwald }
88ab67bfbbSMatthias Ringwald 
89ab67bfbbSMatthias Ringwald /**
90ab67bfbbSMatthias Ringwald  * @brief Check if encoder has data ready
91ab67bfbbSMatthias Ringwald  * @return True if data ready
92ab67bfbbSMatthias Ringwald  */
93ab67bfbbSMatthias Ringwald int  btstack_slip_encoder_has_data(void){
94ab67bfbbSMatthias Ringwald 	if (encoder_state != SLIP_ENCODER_DEFAULT) return 1;
954ea43905SMatthias Ringwald 	return encoder_len > 0u;
96ab67bfbbSMatthias Ringwald }
97ab67bfbbSMatthias Ringwald 
98ab67bfbbSMatthias Ringwald /**
99ab67bfbbSMatthias Ringwald  * @brief Get next byte from encoder
100ab67bfbbSMatthias Ringwald  * @return Next bytes from encoder
101ab67bfbbSMatthias Ringwald  */
102ab67bfbbSMatthias Ringwald uint8_t btstack_slip_encoder_get_byte(void){
103ab67bfbbSMatthias Ringwald 	uint8_t next_byte;
104ab67bfbbSMatthias Ringwald 	switch (encoder_state){
105ab67bfbbSMatthias Ringwald 		case SLIP_ENCODER_DEFAULT:
106ab67bfbbSMatthias Ringwald 			next_byte = *encoder_data++;
107b5550b84SMatthias Ringwald 			encoder_len--;
108ab67bfbbSMatthias Ringwald 			switch (next_byte){
109ab67bfbbSMatthias Ringwald 				case BTSTACK_SLIP_SOF:
1104d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DC;
111ab67bfbbSMatthias Ringwald 					return 0xdb;
112ab67bfbbSMatthias Ringwald 				case 0xdb:
1134d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DD;
114ab67bfbbSMatthias Ringwald 					return 0xdb;
115ab67bfbbSMatthias Ringwald 				default:
116ab67bfbbSMatthias Ringwald                     break;
1174395a000SMatthias Ringwald 			}
1184395a000SMatthias Ringwald 			return next_byte;
1194d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DC:
120b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
121ab67bfbbSMatthias Ringwald 			return 0x0dc;
1224d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DD:
123b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
124ab67bfbbSMatthias Ringwald 			return 0x0dd;
125da0fc6ccSMatthias Ringwald         default:
126da0fc6ccSMatthias Ringwald             log_error("btstack_slip_encoder_get_byte invalid state %x", encoder_state);
127da0fc6ccSMatthias Ringwald             return 0x00;
128ab67bfbbSMatthias Ringwald 	}
129ab67bfbbSMatthias Ringwald }
130ab67bfbbSMatthias Ringwald 
1314d6feae0SMatthias Ringwald // Decoder
132ab67bfbbSMatthias Ringwald 
1334d6feae0SMatthias Ringwald static void btstack_slip_decoder_reset(void){
1344d6feae0SMatthias Ringwald 	decoder_state = SLIP_DECODER_UNKNOWN;
1354d6feae0SMatthias Ringwald 	decoder_pos = 0;
136ab67bfbbSMatthias Ringwald }
1374d6feae0SMatthias Ringwald 
1384d6feae0SMatthias Ringwald static void btstack_slip_decoder_store_byte(uint8_t input){
1394d6feae0SMatthias Ringwald 	if (decoder_pos >= decoder_max_size){
1404d6feae0SMatthias Ringwald 	    log_error("btstack_slip_decoder_store_byte: packet to long");
1414d6feae0SMatthias Ringwald 	    btstack_slip_decoder_reset();
1424d6feae0SMatthias Ringwald 	}
1434d6feae0SMatthias Ringwald 	decoder_buffer[decoder_pos++] = input;
1444d6feae0SMatthias Ringwald }
1454d6feae0SMatthias Ringwald 
1464d6feae0SMatthias Ringwald /**
1474d6feae0SMatthias Ringwald  * @brief Initialise SLIP decoder with buffer
1484d6feae0SMatthias Ringwald  * @param buffer to store received data
1494d6feae0SMatthias Ringwald  * @param max_size of buffer
1504d6feae0SMatthias Ringwald  */
1514d6feae0SMatthias Ringwald void btstack_slip_decoder_init(uint8_t * buffer, uint16_t max_size){
1524d6feae0SMatthias Ringwald 	decoder_buffer = buffer;
1534d6feae0SMatthias Ringwald 	decoder_max_size = max_size;
1544d6feae0SMatthias Ringwald 	btstack_slip_decoder_reset();
1554d6feae0SMatthias Ringwald }
1564d6feae0SMatthias Ringwald 
1574d6feae0SMatthias Ringwald /**
1584d6feae0SMatthias Ringwald  * @brief Process received byte
1594d6feae0SMatthias Ringwald  * @param data
1604d6feae0SMatthias Ringwald  */
1614d6feae0SMatthias Ringwald 
1624d6feae0SMatthias Ringwald void btstack_slip_decoder_process(uint8_t input){
1634d6feae0SMatthias Ringwald 	switch(decoder_state){
1644d6feae0SMatthias Ringwald         case SLIP_DECODER_UNKNOWN:
1654d6feae0SMatthias Ringwald             if (input != BTSTACK_SLIP_SOF) break;
1664d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1674d6feae0SMatthias Ringwald             decoder_state = SLIP_DECODER_X_C0;
1684d6feae0SMatthias Ringwald             break;
1694d6feae0SMatthias Ringwald         case SLIP_DECODER_COMPLETE:
1704d6feae0SMatthias Ringwald         	log_error("btstack_slip_decoder_process called in state COMPLETE");
1714d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1724d6feae0SMatthias Ringwald         	break;
1734d6feae0SMatthias Ringwald         case SLIP_DECODER_X_C0:
1744d6feae0SMatthias Ringwald             switch(input){
1754d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
1764d6feae0SMatthias Ringwald                     break;
1774d6feae0SMatthias Ringwald                 case 0xdb:
1784d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
1794d6feae0SMatthias Ringwald                     break;
1804d6feae0SMatthias Ringwald                 default:
1814d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
1824d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1834d6feae0SMatthias Ringwald                     break;
1844d6feae0SMatthias Ringwald             }
1854d6feae0SMatthias Ringwald             break;
1864d6feae0SMatthias Ringwald         case SLIP_DECODER_X_DB:
1874d6feae0SMatthias Ringwald             switch(input){
1884d6feae0SMatthias Ringwald                 case 0xdc:
1894d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(BTSTACK_SLIP_SOF);
1904d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1914d6feae0SMatthias Ringwald                     break;
1924d6feae0SMatthias Ringwald                 case 0xdd:
1934d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(0xdb);
1944d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1954d6feae0SMatthias Ringwald                     break;
1964d6feae0SMatthias Ringwald                 default:
1974d6feae0SMatthias Ringwald                     btstack_slip_decoder_reset();
1984d6feae0SMatthias Ringwald                     break;
1994d6feae0SMatthias Ringwald             }
2004d6feae0SMatthias Ringwald             break;
2014d6feae0SMatthias Ringwald         case SLIP_DECODER_ACTIVE:
2024d6feae0SMatthias Ringwald             switch(input){
2034d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
2044d6feae0SMatthias Ringwald                     if (decoder_pos){
2054d6feae0SMatthias Ringwald                     	decoder_state = SLIP_DECODER_COMPLETE;
2064d6feae0SMatthias Ringwald                     } else {
2074d6feae0SMatthias Ringwald 	                    btstack_slip_decoder_reset();
2084d6feae0SMatthias Ringwald                     }
2094d6feae0SMatthias Ringwald                     break;
2104d6feae0SMatthias Ringwald                 case 0xdb:
2114d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
2124d6feae0SMatthias Ringwald                     break;
2134d6feae0SMatthias Ringwald                 default:
2144d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
2154d6feae0SMatthias Ringwald                     break;
2164d6feae0SMatthias Ringwald             }
2174d6feae0SMatthias Ringwald             break;
218*a8d51f09SMatthias Ringwald 		default:
219*a8d51f09SMatthias Ringwald 			btstack_assert(false);
220*a8d51f09SMatthias Ringwald 			break;
2214d6feae0SMatthias Ringwald     }
2224d6feae0SMatthias Ringwald }
2234d6feae0SMatthias Ringwald 
2244d6feae0SMatthias Ringwald /**
2254d6feae0SMatthias Ringwald  * @brief Get size of decoded frame
2264d6feae0SMatthias Ringwald  * @return size of frame. Size = 0 => frame not complete
2274d6feae0SMatthias Ringwald  */
2284d6feae0SMatthias Ringwald 
2294d6feae0SMatthias Ringwald uint16_t btstack_slip_decoder_frame_size(void){
2304d6feae0SMatthias Ringwald 	switch (decoder_state){
2314d6feae0SMatthias Ringwald 		case SLIP_DECODER_COMPLETE:
2324d6feae0SMatthias Ringwald 			return decoder_pos;
2334d6feae0SMatthias Ringwald 		default:
2344d6feae0SMatthias Ringwald 			return 0;
2354d6feae0SMatthias Ringwald 	}
2364d6feae0SMatthias Ringwald }
237