xref: /btstack/src/btstack_slip.c (revision b5550b84bf441beddbefc9ecbe329167e7fb192c)
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"
444d6feae0SMatthias Ringwald #include "btstack_debug.h"
45ab67bfbbSMatthias Ringwald 
46ab67bfbbSMatthias Ringwald typedef enum {
47ab67bfbbSMatthias Ringwald 	SLIP_ENCODER_DEFAULT,
484d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DC,
494d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DD
50ab67bfbbSMatthias Ringwald } btstack_slip_encoder_state_t;
51ab67bfbbSMatthias Ringwald 
524d6feae0SMatthias Ringwald // h5 slip state machine
534d6feae0SMatthias Ringwald typedef enum {
544d6feae0SMatthias Ringwald     SLIP_DECODER_UNKNOWN = 1,
554d6feae0SMatthias Ringwald     SLIP_DECODER_ACTIVE,
564d6feae0SMatthias Ringwald     SLIP_DECODER_X_C0,
574d6feae0SMatthias Ringwald     SLIP_DECODER_X_DB,
584d6feae0SMatthias Ringwald     SLIP_DECODER_COMPLETE
594d6feae0SMatthias Ringwald } btstack_slip_decoder_state_t;
604d6feae0SMatthias Ringwald 
614d6feae0SMatthias Ringwald 
624d6feae0SMatthias 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 
674d6feae0SMatthias Ringwald // decoder
684d6feae0SMatthias Ringwald static btstack_slip_decoder_state_t decoder_state;
694d6feae0SMatthias Ringwald static uint8_t * decoder_buffer;
704d6feae0SMatthias Ringwald static uint16_t  decoder_max_size;
714d6feae0SMatthias Ringwald static uint16_t  decoder_pos;
724d6feae0SMatthias Ringwald 
734d6feae0SMatthias 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++;
105*b5550b84SMatthias Ringwald 			encoder_len--;
106ab67bfbbSMatthias Ringwald 			switch (next_byte){
107ab67bfbbSMatthias Ringwald 				case BTSTACK_SLIP_SOF:
1084d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DC;
109ab67bfbbSMatthias Ringwald 					return 0xdb;
110ab67bfbbSMatthias Ringwald 				case 0xdb:
1114d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DD;
112ab67bfbbSMatthias Ringwald 					return 0xdb;
113ab67bfbbSMatthias Ringwald 				default:
114ab67bfbbSMatthias Ringwald 					return next_byte;
115ab67bfbbSMatthias Ringwald 			}
116ab67bfbbSMatthias Ringwald 			break;
1174d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DC:
118*b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
119ab67bfbbSMatthias Ringwald 			return 0x0dc;
1204d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DD:
121*b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
122ab67bfbbSMatthias Ringwald 			return 0x0dd;
123ab67bfbbSMatthias Ringwald 	}
124ab67bfbbSMatthias Ringwald }
125ab67bfbbSMatthias Ringwald 
1264d6feae0SMatthias Ringwald // Decoder
127ab67bfbbSMatthias Ringwald 
1284d6feae0SMatthias Ringwald static void btstack_slip_decoder_reset(void){
1294d6feae0SMatthias Ringwald 	decoder_state = SLIP_DECODER_UNKNOWN;
1304d6feae0SMatthias Ringwald 	decoder_pos = 0;
131ab67bfbbSMatthias Ringwald }
1324d6feae0SMatthias Ringwald 
1334d6feae0SMatthias Ringwald static void btstack_slip_decoder_store_byte(uint8_t input){
1344d6feae0SMatthias Ringwald 	if (decoder_pos >= decoder_max_size){
1354d6feae0SMatthias Ringwald 	    log_error("btstack_slip_decoder_store_byte: packet to long");
1364d6feae0SMatthias Ringwald 	    btstack_slip_decoder_reset();
1374d6feae0SMatthias Ringwald 	}
1384d6feae0SMatthias Ringwald 	decoder_buffer[decoder_pos++] = input;
1394d6feae0SMatthias Ringwald }
1404d6feae0SMatthias Ringwald 
1414d6feae0SMatthias Ringwald /**
1424d6feae0SMatthias Ringwald  * @brief Initialise SLIP decoder with buffer
1434d6feae0SMatthias Ringwald  * @param buffer to store received data
1444d6feae0SMatthias Ringwald  * @param max_size of buffer
1454d6feae0SMatthias Ringwald  */
1464d6feae0SMatthias Ringwald void btstack_slip_decoder_init(uint8_t * buffer, uint16_t max_size){
1474d6feae0SMatthias Ringwald 	decoder_buffer = buffer;
1484d6feae0SMatthias Ringwald 	decoder_max_size = max_size;
1494d6feae0SMatthias Ringwald 	btstack_slip_decoder_reset();
1504d6feae0SMatthias Ringwald }
1514d6feae0SMatthias Ringwald 
1524d6feae0SMatthias Ringwald /**
1534d6feae0SMatthias Ringwald  * @brief Process received byte
1544d6feae0SMatthias Ringwald  * @param data
1554d6feae0SMatthias Ringwald  */
1564d6feae0SMatthias Ringwald 
1574d6feae0SMatthias Ringwald void btstack_slip_decoder_process(uint8_t input){
1584d6feae0SMatthias Ringwald 	switch(decoder_state){
1594d6feae0SMatthias Ringwald         case SLIP_DECODER_UNKNOWN:
1604d6feae0SMatthias Ringwald             if (input != BTSTACK_SLIP_SOF) break;
1614d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1624d6feae0SMatthias Ringwald             decoder_state = SLIP_DECODER_X_C0;
1634d6feae0SMatthias Ringwald             break;
1644d6feae0SMatthias Ringwald         case SLIP_DECODER_COMPLETE:
1654d6feae0SMatthias Ringwald         	log_error("btstack_slip_decoder_process called in state COMPLETE");
1664d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1674d6feae0SMatthias Ringwald         	break;
1684d6feae0SMatthias Ringwald         case SLIP_DECODER_X_C0:
1694d6feae0SMatthias Ringwald             switch(input){
1704d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
1714d6feae0SMatthias Ringwald                     break;
1724d6feae0SMatthias Ringwald                 case 0xdb:
1734d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
1744d6feae0SMatthias Ringwald                     break;
1754d6feae0SMatthias Ringwald                 default:
1764d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
1774d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1784d6feae0SMatthias Ringwald                     break;
1794d6feae0SMatthias Ringwald             }
1804d6feae0SMatthias Ringwald             break;
1814d6feae0SMatthias Ringwald         case SLIP_DECODER_X_DB:
1824d6feae0SMatthias Ringwald             switch(input){
1834d6feae0SMatthias Ringwald                 case 0xdc:
1844d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(BTSTACK_SLIP_SOF);
1854d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1864d6feae0SMatthias Ringwald                     break;
1874d6feae0SMatthias Ringwald                 case 0xdd:
1884d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(0xdb);
1894d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1904d6feae0SMatthias Ringwald                     break;
1914d6feae0SMatthias Ringwald                 default:
1924d6feae0SMatthias Ringwald                     btstack_slip_decoder_reset();
1934d6feae0SMatthias Ringwald                     break;
1944d6feae0SMatthias Ringwald             }
1954d6feae0SMatthias Ringwald             break;
1964d6feae0SMatthias Ringwald         case SLIP_DECODER_ACTIVE:
1974d6feae0SMatthias Ringwald             switch(input){
1984d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
1994d6feae0SMatthias Ringwald                     if (decoder_pos){
2004d6feae0SMatthias Ringwald                     	decoder_state = SLIP_DECODER_COMPLETE;
2014d6feae0SMatthias Ringwald                     } else {
2024d6feae0SMatthias Ringwald 	                    btstack_slip_decoder_reset();
2034d6feae0SMatthias Ringwald                     }
2044d6feae0SMatthias Ringwald                     break;
2054d6feae0SMatthias Ringwald                 case 0xdb:
2064d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
2074d6feae0SMatthias Ringwald                     break;
2084d6feae0SMatthias Ringwald                 default:
2094d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
2104d6feae0SMatthias Ringwald                     break;
2114d6feae0SMatthias Ringwald             }
2124d6feae0SMatthias Ringwald             break;
2134d6feae0SMatthias Ringwald     }
2144d6feae0SMatthias Ringwald }
2154d6feae0SMatthias Ringwald 
2164d6feae0SMatthias Ringwald /**
2174d6feae0SMatthias Ringwald  * @brief Get size of decoded frame
2184d6feae0SMatthias Ringwald  * @return size of frame. Size = 0 => frame not complete
2194d6feae0SMatthias Ringwald  */
2204d6feae0SMatthias Ringwald 
2214d6feae0SMatthias Ringwald uint16_t btstack_slip_decoder_frame_size(void){
2224d6feae0SMatthias Ringwald 	switch (decoder_state){
2234d6feae0SMatthias Ringwald 		case SLIP_DECODER_COMPLETE:
2244d6feae0SMatthias Ringwald 			return decoder_pos;
2254d6feae0SMatthias Ringwald 		default:
2264d6feae0SMatthias Ringwald 			return 0;
2274d6feae0SMatthias Ringwald 	}
2284d6feae0SMatthias Ringwald }
229