xref: /btstack/src/btstack_util.c (revision 5df9dc7819db26ff2f834e23204a29e4dd68d594)
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 
38e501bae0SMatthias 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 
89adbdd27aSMilanka Ringwald void little_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){
90adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
91adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
92adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
93adbdd27aSMilanka Ringwald }
94adbdd27aSMilanka Ringwald 
95f8fbdce0SMatthias Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
96b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
97b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
98b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
99b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
100eb886013SMatthias Ringwald }
101eb886013SMatthias Ringwald 
10273988a59SMatthias Ringwald uint32_t big_endian_read_16( const uint8_t * buffer, int pos) {
103b0920f25SMilanka Ringwald     return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos   ]) << 8));
10473988a59SMatthias Ringwald }
10573988a59SMatthias Ringwald 
106e57a2545SMilanka Ringwald uint32_t big_endian_read_24( const uint8_t * buffer, int pos) {
107e57a2545SMilanka Ringwald     return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16));
108e57a2545SMilanka Ringwald }
109e57a2545SMilanka Ringwald 
11073988a59SMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
11173988a59SMatthias Ringwald     return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
11273988a59SMatthias Ringwald }
11373988a59SMatthias Ringwald 
114f8fbdce0SMatthias Ringwald void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
115b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
116b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
117eb886013SMatthias Ringwald }
118eb886013SMatthias Ringwald 
1197f535380SMilanka Ringwald void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){
120b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
121b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
122b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1237f535380SMilanka Ringwald }
1247f535380SMilanka Ringwald 
125f8fbdce0SMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
126b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
127b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
128b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
129b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
130eb886013SMatthias Ringwald }
131eb886013SMatthias Ringwald 
132eb886013SMatthias Ringwald // general swap/endianess utils
1339c80e4ccSMatthias Ringwald void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){
134eb886013SMatthias Ringwald     int i;
135eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
136eb886013SMatthias Ringwald         dst[len - 1 - i] = src[i];
137eb886013SMatthias Ringwald }
1389c80e4ccSMatthias Ringwald void reverse_24(const uint8_t * src, uint8_t * dst){
1399c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 3);
140eb886013SMatthias Ringwald }
1419c80e4ccSMatthias Ringwald void reverse_48(const uint8_t * src, uint8_t * dst){
1429c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 6);
143bf1b35bfSMatthias Ringwald }
1449c80e4ccSMatthias Ringwald void reverse_56(const uint8_t * src, uint8_t * dst){
1459c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 7);
146eb886013SMatthias Ringwald }
1479c80e4ccSMatthias Ringwald void reverse_64(const uint8_t * src, uint8_t * dst){
1489c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 8);
149eb886013SMatthias Ringwald }
1509c80e4ccSMatthias Ringwald void reverse_128(const uint8_t * src, uint8_t * dst){
1519c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 16);
152eb886013SMatthias Ringwald }
153cc7a2d78SMatthias Ringwald void reverse_256(const uint8_t * src, uint8_t * dst){
154cc7a2d78SMatthias Ringwald     reverse_bytes(src, dst, 32);
155cc7a2d78SMatthias Ringwald }
156eb886013SMatthias Ringwald 
157724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
158724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
159724d70a2SMatthias Ringwald }
160724d70a2SMatthias Ringwald 
161ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
162c1ab6cc1SMatthias Ringwald     return (a < b) ? a : b;
163ebaeb1beSMatthias Ringwald }
164ebaeb1beSMatthias Ringwald 
165ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
166c1ab6cc1SMatthias Ringwald     return (a > b) ? a : b;
167ebaeb1beSMatthias Ringwald }
168ebaeb1beSMatthias Ringwald 
16968af3967SMatthias Ringwald /**
17068af3967SMatthias Ringwald  * @brief Calculate delta between two points in time
17168af3967SMatthias Ringwald  * @returns time_a - time_b - result > 0 if time_a is newer than time_b
17268af3967SMatthias Ringwald  */
17368af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){
17468af3967SMatthias Ringwald     return (int32_t)(time_a - time_b);
17568af3967SMatthias Ringwald }
17668af3967SMatthias Ringwald 
177c1c58647SMatthias Ringwald static const char * char_to_nibble = "0123456789ABCDEF";
178c1c58647SMatthias Ringwald 
179eb886013SMatthias Ringwald char char_for_nibble(int nibble){
180c1c58647SMatthias Ringwald     if (nibble < 16){
181c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
182c1c58647SMatthias Ringwald     } else {
183eb886013SMatthias Ringwald         return '?';
184eb886013SMatthias Ringwald     }
185c1c58647SMatthias Ringwald }
186eb886013SMatthias Ringwald 
187405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
188405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
189405d63a9SMatthias Ringwald }
190405d63a9SMatthias Ringwald 
191405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
192405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
193405d63a9SMatthias Ringwald }
194405d63a9SMatthias Ringwald 
195c1c58647SMatthias Ringwald 
196a6efb919SMatthias Ringwald int nibble_for_char(char c){
197c1ab6cc1SMatthias Ringwald     if ((c >= '0') && (c <= '9')) return c - '0';
198c1ab6cc1SMatthias Ringwald     if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
199c1ab6cc1SMatthias Ringwald     if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
200a6efb919SMatthias Ringwald     return -1;
201a6efb919SMatthias Ringwald }
202a6efb919SMatthias Ringwald 
203eb886013SMatthias Ringwald void printf_hexdump(const void *data, int size){
204c1c58647SMatthias Ringwald     char buffer[4];
205c1c58647SMatthias Ringwald     buffer[2] = ' ';
206c1c58647SMatthias Ringwald     buffer[3] =  0;
2079dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
208c1c58647SMatthias Ringwald     while (size > 0){
2099dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
210c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
211c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
212c1c58647SMatthias Ringwald         printf("%s", buffer);
213c1c58647SMatthias Ringwald         size--;
214eb886013SMatthias Ringwald     }
215eb886013SMatthias Ringwald     printf("\n");
216eb886013SMatthias Ringwald }
217eb886013SMatthias Ringwald 
218cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
219cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
220405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
221405d63a9SMatthias Ringwald // template '0x12, '
222405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
223405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2247224be7eSMatthias Ringwald     int i, j;
225eb886013SMatthias Ringwald     j = 0;
226eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2277224be7eSMatthias Ringwald 
2287224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
229c1ab6cc1SMatthias Ringwald         if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){
2307224be7eSMatthias Ringwald             j = 0;
2317224be7eSMatthias Ringwald         }
2327224be7eSMatthias Ringwald 
233eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
234eb886013SMatthias Ringwald         buffer[j++] = '0';
235eb886013SMatthias Ringwald         buffer[j++] = 'x';
236405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
237405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
238eb886013SMatthias Ringwald         buffer[j++] = ',';
239eb886013SMatthias Ringwald         buffer[j++] = ' ';
2407224be7eSMatthias Ringwald 
241c1ab6cc1SMatthias Ringwald         if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){
242eb886013SMatthias Ringwald             buffer[j] = 0;
243cb42147aSMatthias Ringwald             HCI_DUMP_LOG(level, "%s", buffer);
244eb886013SMatthias Ringwald             j = 0;
245eb886013SMatthias Ringwald         }
246eb886013SMatthias Ringwald     }
247eb886013SMatthias Ringwald     if (j != 0){
248eb886013SMatthias Ringwald         buffer[j] = 0;
249cb42147aSMatthias Ringwald         HCI_DUMP_LOG(level, "%s", buffer);
250eb886013SMatthias Ringwald     }
251cb42147aSMatthias Ringwald }
252cb42147aSMatthias Ringwald #endif
253cb42147aSMatthias Ringwald 
254cb42147aSMatthias Ringwald void log_debug_hexdump(const void *data, int size){
255e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
256fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
257cb42147aSMatthias Ringwald #else
2584bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2594bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
260cb42147aSMatthias Ringwald #endif
261cb42147aSMatthias Ringwald }
262cb42147aSMatthias Ringwald 
263cb42147aSMatthias Ringwald void log_info_hexdump(const void *data, int size){
264cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
265fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
266d0662982SMatthias Ringwald #else
2674bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2684bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
2698314c363SMatthias Ringwald #endif
2707299c0feSMatthias Ringwald }
271eb886013SMatthias Ringwald 
2728314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
27302bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
27402bdfbf8SMatthias Ringwald     char buffer[16*2+1];
27502bdfbf8SMatthias Ringwald     int i;
27602bdfbf8SMatthias Ringwald     int j = 0;
27702bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
27802bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
279405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
280405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
28102bdfbf8SMatthias Ringwald     }
28202bdfbf8SMatthias Ringwald     buffer[j] = 0;
28302bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
284d0662982SMatthias Ringwald #else
285d0662982SMatthias Ringwald     UNUSED(name);
286cb42147aSMatthias Ringwald     (void)key;
28702bdfbf8SMatthias Ringwald #endif
288eb886013SMatthias Ringwald }
289eb886013SMatthias Ringwald 
2902b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
2912b604902SMatthias Ringwald 
292eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
2932b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
294eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
295eb886013SMatthias Ringwald 
296e1a125dfSMatthias Ringwald void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){
2972b604902SMatthias Ringwald     memcpy(uuid, bluetooth_base_uuid, 16);
298f8fbdce0SMatthias Ringwald     big_endian_store_32(uuid, 0, shortUUID);
299eb886013SMatthias Ringwald }
300eb886013SMatthias Ringwald 
3015222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){
3022b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
303eb886013SMatthias Ringwald }
304eb886013SMatthias Ringwald 
305eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
3065222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
3077224be7eSMatthias Ringwald     int i;
3087224be7eSMatthias Ringwald     int j = 0;
3097224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
3107224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
3117224be7eSMatthias Ringwald     for (i=0;i<16;i++){
312405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
313405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
314405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3157224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3167224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3177224be7eSMatthias Ringwald         }
3187224be7eSMatthias Ringwald     }
319eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
320eb886013SMatthias Ringwald }
321eb886013SMatthias Ringwald 
322eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
3235222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
324eb886013SMatthias Ringwald     // orig code
325eb886013SMatthias 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]);
326eb886013SMatthias Ringwald     // sprintf-free code
327eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
328eb886013SMatthias Ringwald     int i;
329eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
330405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
331405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
332405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
333eb886013SMatthias Ringwald         *p++ = ':';
334eb886013SMatthias Ringwald     }
335eb886013SMatthias Ringwald     *--p = 0;
336eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
337eb886013SMatthias Ringwald }
338eb886013SMatthias Ringwald 
339a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
340a6efb919SMatthias Ringwald     int upper_nibble = nibble_for_char(*byte_string++);
341a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
342a6efb919SMatthias Ringwald     int lower_nibble = nibble_for_char(*byte_string);
343a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
344a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
345a6efb919SMatthias Ringwald }
346eb886013SMatthias Ringwald 
347a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
348a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
349a6efb919SMatthias Ringwald     int result = 0;
350eb886013SMatthias Ringwald     int i;
351eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
352a6efb919SMatthias Ringwald         int single_byte = scan_hex_byte(addr_string);
353a6efb919SMatthias Ringwald         if (single_byte < 0) break;
354a6efb919SMatthias Ringwald         addr_string += 2;
355b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
356a6efb919SMatthias Ringwald         // don't check seperator after last byte
357c1ab6cc1SMatthias Ringwald         if (i == (BD_ADDR_LEN - 1)) {
358a6efb919SMatthias Ringwald             result = 1;
359a6efb919SMatthias Ringwald             break;
360eb886013SMatthias Ringwald         }
361cd2e416cSMatthias Ringwald         // skip supported separators
362cd2e416cSMatthias Ringwald         char next_char = *addr_string;
363*5df9dc78SMatthias Ringwald         if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) {
364cd2e416cSMatthias Ringwald             addr_string++;
365cd2e416cSMatthias Ringwald         }
366a6efb919SMatthias Ringwald     }
367a6efb919SMatthias Ringwald 
368a6efb919SMatthias Ringwald     if (result){
369a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
370a6efb919SMatthias Ringwald     }
371a6efb919SMatthias Ringwald 	return result;
372eb886013SMatthias Ringwald }
3735d067ab1SMatthias Ringwald 
3745d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){
3755d067ab1SMatthias Ringwald     uint32_t val = 0;
3765d067ab1SMatthias Ringwald     while (1){
3775d067ab1SMatthias Ringwald         char chr = *str;
378c1ab6cc1SMatthias Ringwald         if (!chr || (chr < '0') || (chr > '9'))
3795d067ab1SMatthias Ringwald             return val;
380b0920f25SMilanka Ringwald         val = (val * 10) + (uint8_t)(chr - '0');
3815d067ab1SMatthias Ringwald         str++;
3825d067ab1SMatthias Ringwald     }
3835d067ab1SMatthias Ringwald }
3841f41c2c9SMatthias Ringwald 
385d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
386d1207cd8SMilanka Ringwald     if (i <         10) return 1;
387d1207cd8SMilanka Ringwald     if (i <        100) return 2;
388d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
389d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
390d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
391d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
392d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
393d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
394d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
395d1207cd8SMilanka Ringwald     return 10;
396d1207cd8SMilanka Ringwald }
397d1207cd8SMilanka Ringwald 
398d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
399d1207cd8SMilanka Ringwald     x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
400d1207cd8SMilanka Ringwald     x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
401d1207cd8SMilanka Ringwald     x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
402d1207cd8SMilanka Ringwald     x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
403d1207cd8SMilanka Ringwald     x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
404d1207cd8SMilanka Ringwald     return x;
405d1207cd8SMilanka Ringwald }
4061f41c2c9SMatthias Ringwald 
4071f41c2c9SMatthias Ringwald /*
4081f41c2c9SMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
4091f41c2c9SMatthias Ringwald  */
4101f41c2c9SMatthias Ringwald 
4111f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
4121f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
4131f41c2c9SMatthias Ringwald 
4141f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
4151f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
4161f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
4171f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
4181f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
4191f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
4201f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
4211f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
4221f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
4231f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
4241f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
4251f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
4261f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
4271f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
4281f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
4291f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
4301f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
4311f41c2c9SMatthias Ringwald };
4321f41c2c9SMatthias Ringwald 
4331f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
4341f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
4351f41c2c9SMatthias Ringwald     uint16_t count;
4361f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
4371f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
4381f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
4391f41c2c9SMatthias Ringwald     }
4401f41c2c9SMatthias Ringwald     return crc;
4411f41c2c9SMatthias Ringwald }
4421f41c2c9SMatthias Ringwald 
4431f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
44463dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
4451f41c2c9SMatthias Ringwald     uint8_t crc;
4461f41c2c9SMatthias Ringwald     crc = crc8(data, len);
4471f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
4481f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
4491f41c2c9SMatthias Ringwald         return 0;               /* Valid */
4501f41c2c9SMatthias Ringwald     } else {
4511f41c2c9SMatthias Ringwald         return 1;               /* Failed */
4521f41c2c9SMatthias Ringwald     }
4531f41c2c9SMatthias Ringwald }
4541f41c2c9SMatthias Ringwald 
4551f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
45663dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
4571f41c2c9SMatthias Ringwald     /* Ones complement */
4581f41c2c9SMatthias Ringwald     return 0xFF - crc8(data, len);
4591f41c2c9SMatthias Ringwald }
460