xref: /btstack/src/btstack_slip.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
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
23*2fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald  * GMBH 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,
504a2b7feaSMatthias Ringwald 	SLIP_ENCODER_SEND_C0,
514d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DC,
524d6feae0SMatthias Ringwald 	SLIP_ENCODER_SEND_DD
53ab67bfbbSMatthias Ringwald } btstack_slip_encoder_state_t;
54ab67bfbbSMatthias Ringwald 
554d6feae0SMatthias Ringwald // h5 slip state machine
564d6feae0SMatthias Ringwald typedef enum {
574d6feae0SMatthias Ringwald     SLIP_DECODER_UNKNOWN = 1,
584d6feae0SMatthias Ringwald     SLIP_DECODER_ACTIVE,
594d6feae0SMatthias Ringwald     SLIP_DECODER_X_C0,
604d6feae0SMatthias Ringwald     SLIP_DECODER_X_DB,
614d6feae0SMatthias Ringwald     SLIP_DECODER_COMPLETE
624d6feae0SMatthias Ringwald } btstack_slip_decoder_state_t;
634d6feae0SMatthias Ringwald 
644d6feae0SMatthias Ringwald 
654d6feae0SMatthias Ringwald // encoder
66ab67bfbbSMatthias Ringwald static btstack_slip_encoder_state_t encoder_state;
67ab67bfbbSMatthias Ringwald static const uint8_t * encoder_data;
68ab67bfbbSMatthias Ringwald static uint16_t  encoder_len;
69ab67bfbbSMatthias Ringwald 
704d6feae0SMatthias Ringwald // decoder
714d6feae0SMatthias Ringwald static btstack_slip_decoder_state_t decoder_state;
724d6feae0SMatthias Ringwald static uint8_t * decoder_buffer;
734d6feae0SMatthias Ringwald static uint16_t  decoder_max_size;
744d6feae0SMatthias Ringwald static uint16_t  decoder_pos;
754d6feae0SMatthias Ringwald 
764d6feae0SMatthias Ringwald 
77ab67bfbbSMatthias Ringwald // ENCODER
78ab67bfbbSMatthias Ringwald 
79ab67bfbbSMatthias Ringwald /**
80ab67bfbbSMatthias Ringwald  * @brief Initialise SLIP encoder with data
81ab67bfbbSMatthias Ringwald  * @param data
82ab67bfbbSMatthias Ringwald  * @param len
83ab67bfbbSMatthias Ringwald  */
btstack_slip_encoder_start(const uint8_t * data,uint16_t len)84ab67bfbbSMatthias Ringwald void btstack_slip_encoder_start(const uint8_t * data, uint16_t len){
854a2b7feaSMatthias Ringwald 	// start with C0 SOF
864a2b7feaSMatthias Ringwald 	encoder_state = SLIP_ENCODER_SEND_C0;
87ab67bfbbSMatthias Ringwald 	encoder_data  = data;
88ab67bfbbSMatthias Ringwald 	encoder_len   = len;
89ab67bfbbSMatthias Ringwald }
90ab67bfbbSMatthias Ringwald 
91ab67bfbbSMatthias Ringwald /**
92ab67bfbbSMatthias Ringwald  * @brief Check if encoder has data ready
93ab67bfbbSMatthias Ringwald  * @return True if data ready
94ab67bfbbSMatthias Ringwald  */
btstack_slip_encoder_has_data(void)95ab67bfbbSMatthias Ringwald int  btstack_slip_encoder_has_data(void){
96ab67bfbbSMatthias Ringwald 	if (encoder_state != SLIP_ENCODER_DEFAULT) return 1;
974ea43905SMatthias Ringwald 	return encoder_len > 0u;
98ab67bfbbSMatthias Ringwald }
99ab67bfbbSMatthias Ringwald 
100ab67bfbbSMatthias Ringwald /**
101ab67bfbbSMatthias Ringwald  * @brief Get next byte from encoder
102ab67bfbbSMatthias Ringwald  * @return Next bytes from encoder
103ab67bfbbSMatthias Ringwald  */
btstack_slip_encoder_get_byte(void)104ab67bfbbSMatthias Ringwald uint8_t btstack_slip_encoder_get_byte(void){
105ab67bfbbSMatthias Ringwald 	uint8_t next_byte;
106ab67bfbbSMatthias Ringwald 	switch (encoder_state){
107ab67bfbbSMatthias Ringwald 		case SLIP_ENCODER_DEFAULT:
108ab67bfbbSMatthias Ringwald 			next_byte = *encoder_data++;
109b5550b84SMatthias Ringwald 			encoder_len--;
110ab67bfbbSMatthias Ringwald 			switch (next_byte){
111ab67bfbbSMatthias Ringwald 				case BTSTACK_SLIP_SOF:
1124d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DC;
1134a2b7feaSMatthias Ringwald 					next_byte = 0xdb;
1144a2b7feaSMatthias Ringwald 					break;
115ab67bfbbSMatthias Ringwald 				case 0xdb:
1164d6feae0SMatthias Ringwald 					encoder_state = SLIP_ENCODER_SEND_DD;
1174a2b7feaSMatthias Ringwald 					next_byte = 0xdb;
118ab67bfbbSMatthias Ringwald 				default:
119ab67bfbbSMatthias Ringwald                     break;
1204395a000SMatthias Ringwald 			}
1214a2b7feaSMatthias Ringwald 			break;
1224a2b7feaSMatthias Ringwald 		case SLIP_ENCODER_SEND_C0:
1234a2b7feaSMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
1244a2b7feaSMatthias Ringwald 			return 0xc0;
1254d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DC:
126b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
1274a2b7feaSMatthias Ringwald 			next_byte = 0xdc;
1284a2b7feaSMatthias Ringwald 			break;
1294d6feae0SMatthias Ringwald 		case SLIP_ENCODER_SEND_DD:
130b5550b84SMatthias Ringwald 			encoder_state = SLIP_ENCODER_DEFAULT;
1314a2b7feaSMatthias Ringwald 			next_byte = 0x0dd;
1324a2b7feaSMatthias Ringwald 			break;
133da0fc6ccSMatthias Ringwald         default:
134da0fc6ccSMatthias Ringwald             log_error("btstack_slip_encoder_get_byte invalid state %x", encoder_state);
135da0fc6ccSMatthias Ringwald             return 0x00;
136ab67bfbbSMatthias Ringwald 	}
1374a2b7feaSMatthias Ringwald 
1384a2b7feaSMatthias Ringwald 	// After last byte, send CO SOF again
1394a2b7feaSMatthias Ringwald 	if ((encoder_state == SLIP_ENCODER_DEFAULT) && (encoder_len == 0)){
1404a2b7feaSMatthias Ringwald 		encoder_state = SLIP_ENCODER_SEND_C0;
1414a2b7feaSMatthias Ringwald 	}
1424a2b7feaSMatthias Ringwald 	return next_byte;
143ab67bfbbSMatthias Ringwald }
144ab67bfbbSMatthias Ringwald 
1454d6feae0SMatthias Ringwald // Decoder
146ab67bfbbSMatthias Ringwald 
btstack_slip_decoder_reset(void)1474d6feae0SMatthias Ringwald static void btstack_slip_decoder_reset(void){
1484d6feae0SMatthias Ringwald 	decoder_state = SLIP_DECODER_UNKNOWN;
1494d6feae0SMatthias Ringwald 	decoder_pos = 0;
150ab67bfbbSMatthias Ringwald }
1514d6feae0SMatthias Ringwald 
btstack_slip_decoder_store_byte(uint8_t input)1524d6feae0SMatthias Ringwald static void btstack_slip_decoder_store_byte(uint8_t input){
1534d6feae0SMatthias Ringwald 	if (decoder_pos >= decoder_max_size){
1544d6feae0SMatthias Ringwald 	    log_error("btstack_slip_decoder_store_byte: packet to long");
1554d6feae0SMatthias Ringwald 	    btstack_slip_decoder_reset();
1564d6feae0SMatthias Ringwald 	}
1574d6feae0SMatthias Ringwald 	decoder_buffer[decoder_pos++] = input;
1584d6feae0SMatthias Ringwald }
1594d6feae0SMatthias Ringwald 
1604d6feae0SMatthias Ringwald /**
1614d6feae0SMatthias Ringwald  * @brief Initialise SLIP decoder with buffer
1624d6feae0SMatthias Ringwald  * @param buffer to store received data
1634d6feae0SMatthias Ringwald  * @param max_size of buffer
1644d6feae0SMatthias Ringwald  */
btstack_slip_decoder_init(uint8_t * buffer,uint16_t max_size)1654d6feae0SMatthias Ringwald void btstack_slip_decoder_init(uint8_t * buffer, uint16_t max_size){
1664d6feae0SMatthias Ringwald 	decoder_buffer = buffer;
1674d6feae0SMatthias Ringwald 	decoder_max_size = max_size;
1684d6feae0SMatthias Ringwald 	btstack_slip_decoder_reset();
1694d6feae0SMatthias Ringwald }
1704d6feae0SMatthias Ringwald 
1714d6feae0SMatthias Ringwald /**
1724d6feae0SMatthias Ringwald  * @brief Process received byte
1734d6feae0SMatthias Ringwald  * @param data
1744d6feae0SMatthias Ringwald  */
1754d6feae0SMatthias Ringwald 
btstack_slip_decoder_process(uint8_t input)1764d6feae0SMatthias Ringwald void btstack_slip_decoder_process(uint8_t input){
1774d6feae0SMatthias Ringwald 	switch(decoder_state){
1784d6feae0SMatthias Ringwald         case SLIP_DECODER_UNKNOWN:
1794d6feae0SMatthias Ringwald             if (input != BTSTACK_SLIP_SOF) break;
1804d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1814d6feae0SMatthias Ringwald             decoder_state = SLIP_DECODER_X_C0;
1824d6feae0SMatthias Ringwald             break;
1834d6feae0SMatthias Ringwald         case SLIP_DECODER_COMPLETE:
1844d6feae0SMatthias Ringwald         	log_error("btstack_slip_decoder_process called in state COMPLETE");
1854d6feae0SMatthias Ringwald             btstack_slip_decoder_reset();
1864d6feae0SMatthias Ringwald         	break;
1874d6feae0SMatthias Ringwald         case SLIP_DECODER_X_C0:
1884d6feae0SMatthias Ringwald             switch(input){
1894d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
1904d6feae0SMatthias Ringwald                     break;
1914d6feae0SMatthias Ringwald                 case 0xdb:
1924d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
1934d6feae0SMatthias Ringwald                     break;
1944d6feae0SMatthias Ringwald                 default:
1954d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
1964d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
1974d6feae0SMatthias Ringwald                     break;
1984d6feae0SMatthias Ringwald             }
1994d6feae0SMatthias Ringwald             break;
2004d6feae0SMatthias Ringwald         case SLIP_DECODER_X_DB:
2014d6feae0SMatthias Ringwald             switch(input){
2024d6feae0SMatthias Ringwald                 case 0xdc:
2034d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(BTSTACK_SLIP_SOF);
2044d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
2054d6feae0SMatthias Ringwald                     break;
2064d6feae0SMatthias Ringwald                 case 0xdd:
2074d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(0xdb);
2084d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_ACTIVE;
2094d6feae0SMatthias Ringwald                     break;
2104d6feae0SMatthias Ringwald                 default:
2114d6feae0SMatthias Ringwald                     btstack_slip_decoder_reset();
2124d6feae0SMatthias Ringwald                     break;
2134d6feae0SMatthias Ringwald             }
2144d6feae0SMatthias Ringwald             break;
2154d6feae0SMatthias Ringwald         case SLIP_DECODER_ACTIVE:
2164d6feae0SMatthias Ringwald             switch(input){
2174d6feae0SMatthias Ringwald                 case BTSTACK_SLIP_SOF:
2189305033eSMatthias Ringwald                     if (decoder_pos != 0){
2194d6feae0SMatthias Ringwald                     	decoder_state = SLIP_DECODER_COMPLETE;
2204d6feae0SMatthias Ringwald                     } else {
2214d6feae0SMatthias Ringwald 	                    btstack_slip_decoder_reset();
2224d6feae0SMatthias Ringwald                     }
2234d6feae0SMatthias Ringwald                     break;
2244d6feae0SMatthias Ringwald                 case 0xdb:
2254d6feae0SMatthias Ringwald                     decoder_state = SLIP_DECODER_X_DB;
2264d6feae0SMatthias Ringwald                     break;
2274d6feae0SMatthias Ringwald                 default:
2284d6feae0SMatthias Ringwald                     btstack_slip_decoder_store_byte(input);
2294d6feae0SMatthias Ringwald                     break;
2304d6feae0SMatthias Ringwald             }
2314d6feae0SMatthias Ringwald             break;
232a8d51f09SMatthias Ringwald 		default:
233a8d51f09SMatthias Ringwald 			btstack_assert(false);
234a8d51f09SMatthias Ringwald 			break;
2354d6feae0SMatthias Ringwald     }
2364d6feae0SMatthias Ringwald }
2374d6feae0SMatthias Ringwald 
2384d6feae0SMatthias Ringwald /**
2394d6feae0SMatthias Ringwald  * @brief Get size of decoded frame
2404d6feae0SMatthias Ringwald  * @return size of frame. Size = 0 => frame not complete
2414d6feae0SMatthias Ringwald  */
2424d6feae0SMatthias Ringwald 
btstack_slip_decoder_frame_size(void)2434d6feae0SMatthias Ringwald uint16_t btstack_slip_decoder_frame_size(void){
2444d6feae0SMatthias Ringwald 	switch (decoder_state){
2454d6feae0SMatthias Ringwald 		case SLIP_DECODER_COMPLETE:
2464d6feae0SMatthias Ringwald 			return decoder_pos;
2474d6feae0SMatthias Ringwald 		default:
2484d6feae0SMatthias Ringwald 			return 0;
2494d6feae0SMatthias Ringwald 	}
2504d6feae0SMatthias Ringwald }
251