xref: /btstack/src/btstack_util.c (revision 9dbfa9305b8c373858468c32c2782eb26f8f878c)
1eb886013SMatthias Ringwald /*
2eb886013SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3eb886013SMatthias Ringwald  *
4eb886013SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5eb886013SMatthias Ringwald  * modification, are permitted provided that the following conditions
6eb886013SMatthias Ringwald  * are met:
7eb886013SMatthias Ringwald  *
8eb886013SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9eb886013SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10eb886013SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11eb886013SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12eb886013SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13eb886013SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14eb886013SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15eb886013SMatthias Ringwald  *    from this software without specific prior written permission.
16eb886013SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17eb886013SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18eb886013SMatthias Ringwald  *    monetary gain.
19eb886013SMatthias Ringwald  *
20eb886013SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21eb886013SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22eb886013SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23eb886013SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24eb886013SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25eb886013SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26eb886013SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27eb886013SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28eb886013SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29eb886013SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30eb886013SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31eb886013SMatthias Ringwald  * SUCH DAMAGE.
32eb886013SMatthias Ringwald  *
33eb886013SMatthias Ringwald  * Please inquire about commercial licensing options at
34eb886013SMatthias Ringwald  * [email protected]
35eb886013SMatthias Ringwald  *
36eb886013SMatthias Ringwald  */
37eb886013SMatthias Ringwald 
38ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "btstack_util.c"
39ab2c6ae4SMatthias Ringwald 
40eb886013SMatthias Ringwald /*
41eb886013SMatthias Ringwald  *  btstack_util.c
42eb886013SMatthias Ringwald  *
43eb886013SMatthias Ringwald  *  General utility functions
44eb886013SMatthias Ringwald  *
45eb886013SMatthias Ringwald  *  Created by Matthias Ringwald on 7/23/09.
46eb886013SMatthias Ringwald  */
47eb886013SMatthias Ringwald 
487907f069SMatthias Ringwald #include "btstack_config.h"
4902bdfbf8SMatthias Ringwald #include "btstack_debug.h"
50eb886013SMatthias Ringwald #include "btstack_util.h"
5102bdfbf8SMatthias Ringwald 
52eb886013SMatthias Ringwald #include <stdio.h>
53eb886013SMatthias Ringwald #include <string.h>
54eb886013SMatthias Ringwald 
5573988a59SMatthias Ringwald /**
5673988a59SMatthias Ringwald  * @brief Compare two Bluetooth addresses
5773988a59SMatthias Ringwald  * @param a
5873988a59SMatthias Ringwald  * @param b
59969fc1c5SMilanka Ringwald  * @return 0 if equal
6073988a59SMatthias Ringwald  */
615222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){
6273988a59SMatthias Ringwald     return memcmp(a,b, BD_ADDR_LEN);
6373988a59SMatthias Ringwald }
6473988a59SMatthias Ringwald 
6573988a59SMatthias Ringwald /**
6673988a59SMatthias Ringwald  * @brief Copy Bluetooth address
6773988a59SMatthias Ringwald  * @param dest
6873988a59SMatthias Ringwald  * @param src
6973988a59SMatthias Ringwald  */
705222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){
7173988a59SMatthias Ringwald     memcpy(dest,src,BD_ADDR_LEN);
7273988a59SMatthias Ringwald }
7373988a59SMatthias Ringwald 
7473988a59SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int pos){
75b0920f25SMilanka Ringwald     return (uint16_t)(((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8));
7673988a59SMatthias Ringwald }
7773988a59SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int pos){
7873988a59SMatthias Ringwald     return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16);
7973988a59SMatthias Ringwald }
8073988a59SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int pos){
8173988a59SMatthias Ringwald     return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16) | (((uint32_t) buffer[(pos)+3]) << 24);
8273988a59SMatthias Ringwald }
8373988a59SMatthias Ringwald 
84f8fbdce0SMatthias Ringwald void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
85b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)value;
86b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
87eb886013SMatthias Ringwald }
88eb886013SMatthias Ringwald 
89f8fbdce0SMatthias Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
90b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
91b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
92b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
93b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
94eb886013SMatthias Ringwald }
95eb886013SMatthias Ringwald 
9673988a59SMatthias Ringwald uint32_t big_endian_read_16( const uint8_t * buffer, int pos) {
97b0920f25SMilanka Ringwald     return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos   ]) << 8));
9873988a59SMatthias Ringwald }
9973988a59SMatthias Ringwald 
100e57a2545SMilanka Ringwald uint32_t big_endian_read_24( const uint8_t * buffer, int pos) {
101e57a2545SMilanka Ringwald     return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16));
102e57a2545SMilanka Ringwald }
103e57a2545SMilanka Ringwald 
10473988a59SMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
10573988a59SMatthias Ringwald     return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
10673988a59SMatthias Ringwald }
10773988a59SMatthias Ringwald 
108f8fbdce0SMatthias Ringwald void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
109b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
110b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
111eb886013SMatthias Ringwald }
112eb886013SMatthias Ringwald 
1137f535380SMilanka Ringwald void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){
114b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
115b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
116b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1177f535380SMilanka Ringwald }
1187f535380SMilanka Ringwald 
119f8fbdce0SMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
120b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
121b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
122b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
123b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
124eb886013SMatthias Ringwald }
125eb886013SMatthias Ringwald 
126eb886013SMatthias Ringwald // general swap/endianess utils
1279c80e4ccSMatthias Ringwald void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){
128eb886013SMatthias Ringwald     int i;
129eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
130eb886013SMatthias Ringwald         dst[len - 1 - i] = src[i];
131eb886013SMatthias Ringwald }
1329c80e4ccSMatthias Ringwald void reverse_24(const uint8_t * src, uint8_t * dst){
1339c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 3);
134eb886013SMatthias Ringwald }
1359c80e4ccSMatthias Ringwald void reverse_48(const uint8_t * src, uint8_t * dst){
1369c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 6);
137bf1b35bfSMatthias Ringwald }
1389c80e4ccSMatthias Ringwald void reverse_56(const uint8_t * src, uint8_t * dst){
1399c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 7);
140eb886013SMatthias Ringwald }
1419c80e4ccSMatthias Ringwald void reverse_64(const uint8_t * src, uint8_t * dst){
1429c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 8);
143eb886013SMatthias Ringwald }
1449c80e4ccSMatthias Ringwald void reverse_128(const uint8_t * src, uint8_t * dst){
1459c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 16);
146eb886013SMatthias Ringwald }
147cc7a2d78SMatthias Ringwald void reverse_256(const uint8_t * src, uint8_t * dst){
148cc7a2d78SMatthias Ringwald     reverse_bytes(src, dst, 32);
149cc7a2d78SMatthias Ringwald }
150eb886013SMatthias Ringwald 
151724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
152724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
153724d70a2SMatthias Ringwald }
154724d70a2SMatthias Ringwald 
155ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
156ebaeb1beSMatthias Ringwald     return a < b ? a : b;
157ebaeb1beSMatthias Ringwald }
158ebaeb1beSMatthias Ringwald 
159ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
160ebaeb1beSMatthias Ringwald     return a > b ? a : b;
161ebaeb1beSMatthias Ringwald }
162ebaeb1beSMatthias Ringwald 
163c1c58647SMatthias Ringwald static const char * char_to_nibble = "0123456789ABCDEF";
164c1c58647SMatthias Ringwald 
165eb886013SMatthias Ringwald char char_for_nibble(int nibble){
166c1c58647SMatthias Ringwald     if (nibble < 16){
167c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
168c1c58647SMatthias Ringwald     } else {
169eb886013SMatthias Ringwald         return '?';
170eb886013SMatthias Ringwald     }
171c1c58647SMatthias Ringwald }
172eb886013SMatthias Ringwald 
173405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
174405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
175405d63a9SMatthias Ringwald }
176405d63a9SMatthias Ringwald 
177405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
178405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
179405d63a9SMatthias Ringwald }
180405d63a9SMatthias Ringwald 
181c1c58647SMatthias Ringwald 
182a6efb919SMatthias Ringwald int nibble_for_char(char c){
183a6efb919SMatthias Ringwald     if (c >= '0' && c <= '9') return c - '0';
1849f507070SMatthias Ringwald     if (c >= 'a' && c <= 'f') return c - 'a' + 10;
1859f507070SMatthias Ringwald     if (c >= 'A' && c <= 'F') return c - 'A' + 10;
186a6efb919SMatthias Ringwald     return -1;
187a6efb919SMatthias Ringwald }
188a6efb919SMatthias Ringwald 
189eb886013SMatthias Ringwald void printf_hexdump(const void *data, int size){
190c1c58647SMatthias Ringwald     char buffer[4];
191c1c58647SMatthias Ringwald     buffer[2] = ' ';
192c1c58647SMatthias Ringwald     buffer[3] =  0;
193*9dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
194c1c58647SMatthias Ringwald     while (size > 0){
195*9dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
196c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
197c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
198c1c58647SMatthias Ringwald         printf("%s", buffer);
199c1c58647SMatthias Ringwald         size--;
200eb886013SMatthias Ringwald     }
201eb886013SMatthias Ringwald     printf("\n");
202eb886013SMatthias Ringwald }
203eb886013SMatthias Ringwald 
204cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
205cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
206405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
207405d63a9SMatthias Ringwald // template '0x12, '
208405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
209405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2107224be7eSMatthias Ringwald     int i, j;
211eb886013SMatthias Ringwald     j = 0;
212eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2137224be7eSMatthias Ringwald 
2147224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
215405d63a9SMatthias Ringwald         if (j > BYTES_PER_BYTE * (ITEMS_PER_LINE-1)){
2167224be7eSMatthias Ringwald             j = 0;
2177224be7eSMatthias Ringwald         }
2187224be7eSMatthias Ringwald 
219eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
220eb886013SMatthias Ringwald         buffer[j++] = '0';
221eb886013SMatthias Ringwald         buffer[j++] = 'x';
222405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
223405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
224eb886013SMatthias Ringwald         buffer[j++] = ',';
225eb886013SMatthias Ringwald         buffer[j++] = ' ';
2267224be7eSMatthias Ringwald 
227405d63a9SMatthias Ringwald         if (j >= BYTES_PER_BYTE * ITEMS_PER_LINE ){
228eb886013SMatthias Ringwald             buffer[j] = 0;
229cb42147aSMatthias Ringwald             HCI_DUMP_LOG(level, "%s", buffer);
230eb886013SMatthias Ringwald             j = 0;
231eb886013SMatthias Ringwald         }
232eb886013SMatthias Ringwald     }
233eb886013SMatthias Ringwald     if (j != 0){
234eb886013SMatthias Ringwald         buffer[j] = 0;
235cb42147aSMatthias Ringwald         HCI_DUMP_LOG(level, "%s", buffer);
236eb886013SMatthias Ringwald     }
237cb42147aSMatthias Ringwald }
238cb42147aSMatthias Ringwald #endif
239cb42147aSMatthias Ringwald 
240cb42147aSMatthias Ringwald void log_debug_hexdump(const void *data, int size){
241e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
242fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
243cb42147aSMatthias Ringwald #else
2444bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2454bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
246cb42147aSMatthias Ringwald #endif
247cb42147aSMatthias Ringwald }
248cb42147aSMatthias Ringwald 
249cb42147aSMatthias Ringwald void log_info_hexdump(const void *data, int size){
250cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
251fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
252d0662982SMatthias Ringwald #else
2534bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2544bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
2558314c363SMatthias Ringwald #endif
2567299c0feSMatthias Ringwald }
257eb886013SMatthias Ringwald 
2588314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
25902bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
26002bdfbf8SMatthias Ringwald     char buffer[16*2+1];
26102bdfbf8SMatthias Ringwald     int i;
26202bdfbf8SMatthias Ringwald     int j = 0;
26302bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
26402bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
265405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
266405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
26702bdfbf8SMatthias Ringwald     }
26802bdfbf8SMatthias Ringwald     buffer[j] = 0;
26902bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
270d0662982SMatthias Ringwald #else
271d0662982SMatthias Ringwald     UNUSED(name);
272cb42147aSMatthias Ringwald     (void)key;
27302bdfbf8SMatthias Ringwald #endif
274eb886013SMatthias Ringwald }
275eb886013SMatthias Ringwald 
2762b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
2772b604902SMatthias Ringwald 
278eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
2792b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
280eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
281eb886013SMatthias Ringwald 
282e1a125dfSMatthias Ringwald void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){
2832b604902SMatthias Ringwald     memcpy(uuid, bluetooth_base_uuid, 16);
284f8fbdce0SMatthias Ringwald     big_endian_store_32(uuid, 0, shortUUID);
285eb886013SMatthias Ringwald }
286eb886013SMatthias Ringwald 
2875222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){
2882b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
289eb886013SMatthias Ringwald }
290eb886013SMatthias Ringwald 
291eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
2925222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
2937224be7eSMatthias Ringwald     int i;
2947224be7eSMatthias Ringwald     int j = 0;
2957224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
2967224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
2977224be7eSMatthias Ringwald     for (i=0;i<16;i++){
298405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
299405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
300405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3017224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3027224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3037224be7eSMatthias Ringwald         }
3047224be7eSMatthias Ringwald     }
305eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
306eb886013SMatthias Ringwald }
307eb886013SMatthias Ringwald 
308eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
3095222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
310eb886013SMatthias Ringwald     // orig code
311eb886013SMatthias Ringwald     // sprintf(bd_addr_to_str_buffer, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
312eb886013SMatthias Ringwald     // sprintf-free code
313eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
314eb886013SMatthias Ringwald     int i;
315eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
316405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
317405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
318405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
319eb886013SMatthias Ringwald         *p++ = ':';
320eb886013SMatthias Ringwald     }
321eb886013SMatthias Ringwald     *--p = 0;
322eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
323eb886013SMatthias Ringwald }
324eb886013SMatthias Ringwald 
325a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
326a6efb919SMatthias Ringwald     int upper_nibble = nibble_for_char(*byte_string++);
327a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
328a6efb919SMatthias Ringwald     int lower_nibble = nibble_for_char(*byte_string);
329a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
330a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
331a6efb919SMatthias Ringwald }
332eb886013SMatthias Ringwald 
333a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
334a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
335a6efb919SMatthias Ringwald     int result = 0;
336eb886013SMatthias Ringwald     int i;
337eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
338a6efb919SMatthias Ringwald         int single_byte = scan_hex_byte(addr_string);
339a6efb919SMatthias Ringwald         if (single_byte < 0) break;
340a6efb919SMatthias Ringwald         addr_string += 2;
341b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
342a6efb919SMatthias Ringwald         // don't check seperator after last byte
343a6efb919SMatthias Ringwald         if (i == BD_ADDR_LEN - 1) {
344a6efb919SMatthias Ringwald             result = 1;
345a6efb919SMatthias Ringwald             break;
346eb886013SMatthias Ringwald         }
347cd2e416cSMatthias Ringwald         // skip supported separators
348cd2e416cSMatthias Ringwald         char next_char = *addr_string;
349cd2e416cSMatthias Ringwald         if (next_char == ':' || next_char == '-' || next_char == ' ') {
350cd2e416cSMatthias Ringwald             addr_string++;
351cd2e416cSMatthias Ringwald         }
352a6efb919SMatthias Ringwald     }
353a6efb919SMatthias Ringwald 
354a6efb919SMatthias Ringwald     if (result){
355a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
356a6efb919SMatthias Ringwald     }
357a6efb919SMatthias Ringwald 	return result;
358eb886013SMatthias Ringwald }
3595d067ab1SMatthias Ringwald 
3605d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){
3615d067ab1SMatthias Ringwald     uint32_t val = 0;
3625d067ab1SMatthias Ringwald     while (1){
3635d067ab1SMatthias Ringwald         char chr = *str;
3645d067ab1SMatthias Ringwald         if (!chr || chr < '0' || chr > '9')
3655d067ab1SMatthias Ringwald             return val;
366b0920f25SMilanka Ringwald         val = (val * 10) + (uint8_t)(chr - '0');
3675d067ab1SMatthias Ringwald         str++;
3685d067ab1SMatthias Ringwald     }
3695d067ab1SMatthias Ringwald }
3701f41c2c9SMatthias Ringwald 
371d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
372d1207cd8SMilanka Ringwald     if (i <         10) return 1;
373d1207cd8SMilanka Ringwald     if (i <        100) return 2;
374d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
375d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
376d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
377d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
378d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
379d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
380d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
381d1207cd8SMilanka Ringwald     return 10;
382d1207cd8SMilanka Ringwald }
383d1207cd8SMilanka Ringwald 
384d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
385d1207cd8SMilanka Ringwald     x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
386d1207cd8SMilanka Ringwald     x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
387d1207cd8SMilanka Ringwald     x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
388d1207cd8SMilanka Ringwald     x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
389d1207cd8SMilanka Ringwald     x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
390d1207cd8SMilanka Ringwald     return x;
391d1207cd8SMilanka Ringwald }
3921f41c2c9SMatthias Ringwald 
3931f41c2c9SMatthias Ringwald /*
3941f41c2c9SMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
3951f41c2c9SMatthias Ringwald  */
3961f41c2c9SMatthias Ringwald 
3971f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
3981f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
3991f41c2c9SMatthias Ringwald 
4001f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
4011f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
4021f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
4031f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
4041f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
4051f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
4061f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
4071f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
4081f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
4091f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
4101f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
4111f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
4121f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
4131f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
4141f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
4151f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
4161f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
4171f41c2c9SMatthias Ringwald };
4181f41c2c9SMatthias Ringwald 
4191f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
4201f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
4211f41c2c9SMatthias Ringwald     uint16_t count;
4221f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
4231f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
4241f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
4251f41c2c9SMatthias Ringwald     }
4261f41c2c9SMatthias Ringwald     return crc;
4271f41c2c9SMatthias Ringwald }
4281f41c2c9SMatthias Ringwald 
4291f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
43063dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
4311f41c2c9SMatthias Ringwald     uint8_t crc;
4321f41c2c9SMatthias Ringwald     crc = crc8(data, len);
4331f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
4341f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
4351f41c2c9SMatthias Ringwald         return 0;               /* Valid */
4361f41c2c9SMatthias Ringwald     } else {
4371f41c2c9SMatthias Ringwald         return 1;               /* Failed */
4381f41c2c9SMatthias Ringwald     }
4391f41c2c9SMatthias Ringwald }
4401f41c2c9SMatthias Ringwald 
4411f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
44263dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
4431f41c2c9SMatthias Ringwald     /* Ones complement */
4441f41c2c9SMatthias Ringwald     return 0xFF - crc8(data, len);
4451f41c2c9SMatthias Ringwald }
446