xref: /btstack/src/btstack_util.c (revision b45b7749fd0a3efec18073ae84f893078d0216d0)
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  *  General utility functions
42eb886013SMatthias Ringwald  */
43eb886013SMatthias Ringwald 
447907f069SMatthias Ringwald #include "btstack_config.h"
4502bdfbf8SMatthias Ringwald #include "btstack_debug.h"
46eb886013SMatthias Ringwald #include "btstack_util.h"
4702bdfbf8SMatthias Ringwald 
4846059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
49eb886013SMatthias Ringwald #include <stdio.h>
5046059ae4SMilanka Ringwald #endif
5146059ae4SMilanka Ringwald 
52eb886013SMatthias Ringwald #include <string.h>
53eb886013SMatthias Ringwald 
5473988a59SMatthias Ringwald /**
5573988a59SMatthias Ringwald  * @brief Compare two Bluetooth addresses
5673988a59SMatthias Ringwald  * @param a
5773988a59SMatthias Ringwald  * @param b
58969fc1c5SMilanka Ringwald  * @return 0 if equal
5973988a59SMatthias Ringwald  */
605222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){
6173988a59SMatthias Ringwald     return memcmp(a,b, BD_ADDR_LEN);
6273988a59SMatthias Ringwald }
6373988a59SMatthias Ringwald 
6473988a59SMatthias Ringwald /**
6573988a59SMatthias Ringwald  * @brief Copy Bluetooth address
6673988a59SMatthias Ringwald  * @param dest
6773988a59SMatthias Ringwald  * @param src
6873988a59SMatthias Ringwald  */
695222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){
706535961aSMatthias Ringwald     (void)memcpy(dest, src, BD_ADDR_LEN);
7173988a59SMatthias Ringwald }
7273988a59SMatthias Ringwald 
7341f9be70SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int position){
7441f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8));
7573988a59SMatthias Ringwald }
7641f9be70SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int position){
7741f9be70SMatthias Ringwald     return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16);
7873988a59SMatthias Ringwald }
7941f9be70SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int position){
8041f9be70SMatthias Ringwald     return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24);
8173988a59SMatthias Ringwald }
8273988a59SMatthias Ringwald 
8341f9be70SMatthias Ringwald void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
8441f9be70SMatthias Ringwald     uint16_t pos = position;
85b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)value;
86b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
87eb886013SMatthias Ringwald }
88eb886013SMatthias Ringwald 
8941f9be70SMatthias Ringwald void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
9041f9be70SMatthias Ringwald     uint16_t pos = position;
91adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
92adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
93adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
94adbdd27aSMilanka Ringwald }
95adbdd27aSMilanka Ringwald 
9641f9be70SMatthias Ringwald void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
9741f9be70SMatthias Ringwald     uint16_t pos = position;
98b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
99b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
100b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
101b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
102eb886013SMatthias Ringwald }
103eb886013SMatthias Ringwald 
10441f9be70SMatthias Ringwald uint32_t big_endian_read_16(const uint8_t * buffer, int position) {
10541f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8));
10673988a59SMatthias Ringwald }
10773988a59SMatthias Ringwald 
10841f9be70SMatthias Ringwald uint32_t big_endian_read_24(const uint8_t * buffer, int position) {
10941f9be70SMatthias Ringwald     return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16));
110e57a2545SMilanka Ringwald }
111e57a2545SMilanka Ringwald 
11241f9be70SMatthias Ringwald uint32_t big_endian_read_32(const uint8_t * buffer, int position) {
11341f9be70SMatthias Ringwald     return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24);
11473988a59SMatthias Ringwald }
11573988a59SMatthias Ringwald 
11641f9be70SMatthias Ringwald void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
11741f9be70SMatthias Ringwald     uint16_t pos = position;
118b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
119b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
120eb886013SMatthias Ringwald }
121eb886013SMatthias Ringwald 
12241f9be70SMatthias Ringwald void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
12341f9be70SMatthias Ringwald     uint16_t pos = position;
124b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
125b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
126b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1277f535380SMilanka Ringwald }
1287f535380SMilanka Ringwald 
12941f9be70SMatthias Ringwald void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
13041f9be70SMatthias Ringwald     uint16_t pos = position;
131b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
132b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
133b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
134b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
135eb886013SMatthias Ringwald }
136eb886013SMatthias Ringwald 
137eb886013SMatthias Ringwald // general swap/endianess utils
138*b45b7749SMilanka Ringwald void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){
139eb886013SMatthias Ringwald     int i;
140eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
141*b45b7749SMilanka Ringwald         dest[len - 1 - i] = src[i];
142eb886013SMatthias Ringwald }
143*b45b7749SMilanka Ringwald void reverse_24(const uint8_t * src, uint8_t * dest){
144*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 3);
145eb886013SMatthias Ringwald }
146*b45b7749SMilanka Ringwald void reverse_48(const uint8_t * src, uint8_t * dest){
147*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 6);
148bf1b35bfSMatthias Ringwald }
149*b45b7749SMilanka Ringwald void reverse_56(const uint8_t * src, uint8_t * dest){
150*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 7);
151eb886013SMatthias Ringwald }
152*b45b7749SMilanka Ringwald void reverse_64(const uint8_t * src, uint8_t * dest){
153*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 8);
154eb886013SMatthias Ringwald }
155*b45b7749SMilanka Ringwald void reverse_128(const uint8_t * src, uint8_t * dest){
156*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 16);
157eb886013SMatthias Ringwald }
158*b45b7749SMilanka Ringwald void reverse_256(const uint8_t * src, uint8_t * dest){
159*b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 32);
160cc7a2d78SMatthias Ringwald }
161eb886013SMatthias Ringwald 
162724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
163724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
164724d70a2SMatthias Ringwald }
165724d70a2SMatthias Ringwald 
166ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
167c1ab6cc1SMatthias Ringwald     return (a < b) ? a : b;
168ebaeb1beSMatthias Ringwald }
169ebaeb1beSMatthias Ringwald 
170ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
171c1ab6cc1SMatthias Ringwald     return (a > b) ? a : b;
172ebaeb1beSMatthias Ringwald }
173ebaeb1beSMatthias Ringwald 
17468af3967SMatthias Ringwald /**
17568af3967SMatthias Ringwald  * @brief Calculate delta between two points in time
17668af3967SMatthias Ringwald  * @returns time_a - time_b - result > 0 if time_a is newer than time_b
17768af3967SMatthias Ringwald  */
17868af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){
17968af3967SMatthias Ringwald     return (int32_t)(time_a - time_b);
18068af3967SMatthias Ringwald }
18168af3967SMatthias Ringwald 
182c1c58647SMatthias Ringwald 
183eb886013SMatthias Ringwald char char_for_nibble(int nibble){
1848334d3d8SMatthias Ringwald 
1858334d3d8SMatthias Ringwald     static const char * char_to_nibble = "0123456789ABCDEF";
1868334d3d8SMatthias Ringwald 
187c1c58647SMatthias Ringwald     if (nibble < 16){
188c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
189c1c58647SMatthias Ringwald     } else {
190eb886013SMatthias Ringwald         return '?';
191eb886013SMatthias Ringwald     }
192c1c58647SMatthias Ringwald }
193eb886013SMatthias Ringwald 
194405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
195405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
196405d63a9SMatthias Ringwald }
197405d63a9SMatthias Ringwald 
198405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
199405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
200405d63a9SMatthias Ringwald }
201405d63a9SMatthias Ringwald 
202c1c58647SMatthias Ringwald 
203a6efb919SMatthias Ringwald int nibble_for_char(char c){
204c1ab6cc1SMatthias Ringwald     if ((c >= '0') && (c <= '9')) return c - '0';
205c1ab6cc1SMatthias Ringwald     if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
206c1ab6cc1SMatthias Ringwald     if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
207a6efb919SMatthias Ringwald     return -1;
208a6efb919SMatthias Ringwald }
209a6efb919SMatthias Ringwald 
21046059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
211eb886013SMatthias Ringwald void printf_hexdump(const void * data, int size){
212c1c58647SMatthias Ringwald     char buffer[4];
213c1c58647SMatthias Ringwald     buffer[2] = ' ';
214c1c58647SMatthias Ringwald     buffer[3] =  0;
2159dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
216c1c58647SMatthias Ringwald     while (size > 0){
2179dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
218c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
219c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
220c1c58647SMatthias Ringwald         printf("%s", buffer);
221c1c58647SMatthias Ringwald         size--;
222eb886013SMatthias Ringwald     }
223eb886013SMatthias Ringwald     printf("\n");
224eb886013SMatthias Ringwald }
22546059ae4SMilanka Ringwald #endif
226eb886013SMatthias Ringwald 
227cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
228cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
229405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
230405d63a9SMatthias Ringwald // template '0x12, '
231405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
232405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2337224be7eSMatthias Ringwald     int i, j;
234eb886013SMatthias Ringwald     j = 0;
235eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2367224be7eSMatthias Ringwald 
2377224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
238c1ab6cc1SMatthias Ringwald         if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){
2397224be7eSMatthias Ringwald             j = 0;
2407224be7eSMatthias Ringwald         }
2417224be7eSMatthias Ringwald 
242eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
243eb886013SMatthias Ringwald         buffer[j++] = '0';
244eb886013SMatthias Ringwald         buffer[j++] = 'x';
245405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
246405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
247eb886013SMatthias Ringwald         buffer[j++] = ',';
248eb886013SMatthias Ringwald         buffer[j++] = ' ';
2497224be7eSMatthias Ringwald 
250c1ab6cc1SMatthias Ringwald         if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){
251eb886013SMatthias Ringwald             buffer[j] = 0;
252cb42147aSMatthias Ringwald             HCI_DUMP_LOG(level, "%s", buffer);
253eb886013SMatthias Ringwald             j = 0;
254eb886013SMatthias Ringwald         }
255eb886013SMatthias Ringwald     }
256eb886013SMatthias Ringwald     if (j != 0){
257eb886013SMatthias Ringwald         buffer[j] = 0;
258cb42147aSMatthias Ringwald         HCI_DUMP_LOG(level, "%s", buffer);
259eb886013SMatthias Ringwald     }
260cb42147aSMatthias Ringwald }
261cb42147aSMatthias Ringwald #endif
262cb42147aSMatthias Ringwald 
263cb42147aSMatthias Ringwald void log_debug_hexdump(const void * data, int size){
264e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
265fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
266cb42147aSMatthias Ringwald #else
2674bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2684bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
269cb42147aSMatthias Ringwald #endif
270cb42147aSMatthias Ringwald }
271cb42147aSMatthias Ringwald 
272cb42147aSMatthias Ringwald void log_info_hexdump(const void * data, int size){
273cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
274fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
275d0662982SMatthias Ringwald #else
2764bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2774bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
2788314c363SMatthias Ringwald #endif
2797299c0feSMatthias Ringwald }
280eb886013SMatthias Ringwald 
2818314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
28202bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
28302bdfbf8SMatthias Ringwald     char buffer[16*2+1];
28402bdfbf8SMatthias Ringwald     int i;
28502bdfbf8SMatthias Ringwald     int j = 0;
28602bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
28702bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
288405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
289405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
29002bdfbf8SMatthias Ringwald     }
29102bdfbf8SMatthias Ringwald     buffer[j] = 0;
29202bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
293d0662982SMatthias Ringwald #else
294d0662982SMatthias Ringwald     UNUSED(name);
295cb42147aSMatthias Ringwald     (void)key;
29602bdfbf8SMatthias Ringwald #endif
297eb886013SMatthias Ringwald }
298eb886013SMatthias Ringwald 
2992b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
3002b604902SMatthias Ringwald 
301eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
3022b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
303eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
304eb886013SMatthias Ringwald 
305*b45b7749SMilanka Ringwald void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t shortUUID){
306*b45b7749SMilanka Ringwald     (void)memcpy(uuid128, bluetooth_base_uuid, 16);
307*b45b7749SMilanka Ringwald     big_endian_store_32(uuid128, 0, shortUUID);
308eb886013SMatthias Ringwald }
309eb886013SMatthias Ringwald 
3105222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){
3112b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
312eb886013SMatthias Ringwald }
313eb886013SMatthias Ringwald 
314eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
3155222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
3167224be7eSMatthias Ringwald     int i;
3177224be7eSMatthias Ringwald     int j = 0;
3187224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
3197224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
3207224be7eSMatthias Ringwald     for (i=0;i<16;i++){
321405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
322405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
323405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3247224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3257224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3267224be7eSMatthias Ringwald         }
3277224be7eSMatthias Ringwald     }
328eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
329eb886013SMatthias Ringwald }
330eb886013SMatthias Ringwald 
331eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
3325222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
333eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
334eb886013SMatthias Ringwald     int i;
335eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
336405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
337405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
338405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
339eb886013SMatthias Ringwald         *p++ = ':';
340eb886013SMatthias Ringwald     }
341eb886013SMatthias Ringwald     *--p = 0;
342eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
343eb886013SMatthias Ringwald }
344eb886013SMatthias Ringwald 
3453c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){
3463c9da642SMatthias Ringwald     const int bd_addr_string_len = 17;
34730314625SMatthias Ringwald     uint16_t i = 0;
34830314625SMatthias Ringwald     while ((i + bd_addr_string_len) <= size){
3493c9da642SMatthias Ringwald         if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) {
3503c9da642SMatthias Ringwald             i++;
3513c9da642SMatthias Ringwald             continue;
3523c9da642SMatthias Ringwald         }
3533c9da642SMatthias Ringwald         // set address
3543c9da642SMatthias Ringwald         (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len);
3553c9da642SMatthias Ringwald         i += bd_addr_string_len;
3563c9da642SMatthias Ringwald     }
3573c9da642SMatthias Ringwald }
3583c9da642SMatthias Ringwald 
359a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
36041f9be70SMatthias Ringwald     int upper_nibble = nibble_for_char(byte_string[0]);
361a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
36241f9be70SMatthias Ringwald     int lower_nibble = nibble_for_char(byte_string[1]);
363a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
364a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
365a6efb919SMatthias Ringwald }
366eb886013SMatthias Ringwald 
367a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
36841f9be70SMatthias Ringwald     const char * the_string = addr_string;
369a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
370a6efb919SMatthias Ringwald     int result = 0;
371eb886013SMatthias Ringwald     int i;
372eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
37341f9be70SMatthias Ringwald         int single_byte = scan_hex_byte(the_string);
374a6efb919SMatthias Ringwald         if (single_byte < 0) break;
37541f9be70SMatthias Ringwald         the_string += 2;
376b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
37741f9be70SMatthias Ringwald         // don't check separator after last byte
378c1ab6cc1SMatthias Ringwald         if (i == (BD_ADDR_LEN - 1)) {
379a6efb919SMatthias Ringwald             result = 1;
380a6efb919SMatthias Ringwald             break;
381eb886013SMatthias Ringwald         }
382cd2e416cSMatthias Ringwald         // skip supported separators
38341f9be70SMatthias Ringwald         char next_char = *the_string;
3845df9dc78SMatthias Ringwald         if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) {
38541f9be70SMatthias Ringwald             the_string++;
386cd2e416cSMatthias Ringwald         }
387a6efb919SMatthias Ringwald     }
388a6efb919SMatthias Ringwald 
3899305033eSMatthias Ringwald     if (result != 0){
390a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
391a6efb919SMatthias Ringwald     }
392a6efb919SMatthias Ringwald 	return result;
393eb886013SMatthias Ringwald }
3945d067ab1SMatthias Ringwald 
3955d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char * str){
39641f9be70SMatthias Ringwald     const char * the_string = str;
3975d067ab1SMatthias Ringwald     uint32_t val = 0;
398ff3cc4a5SMatthias Ringwald     while (true){
39941f9be70SMatthias Ringwald         char chr = *the_string++;
400c1ab6cc1SMatthias Ringwald         if (!chr || (chr < '0') || (chr > '9'))
4015d067ab1SMatthias Ringwald             return val;
4024ea43905SMatthias Ringwald         val = (val * 10u) + (uint8_t)(chr - '0');
4035d067ab1SMatthias Ringwald     }
4045d067ab1SMatthias Ringwald }
4051f41c2c9SMatthias Ringwald 
406d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
407d1207cd8SMilanka Ringwald     if (i <         10) return 1;
408d1207cd8SMilanka Ringwald     if (i <        100) return 2;
409d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
410d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
411d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
412d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
413d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
414d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
415d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
416d1207cd8SMilanka Ringwald     return 10;
417d1207cd8SMilanka Ringwald }
418d1207cd8SMilanka Ringwald 
419d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
42041f9be70SMatthias Ringwald     uint32_t v = x;
42141f9be70SMatthias Ringwald     v = (v & 0x55555555) + ((v >> 1)  & 0x55555555U);
42241f9be70SMatthias Ringwald     v = (v & 0x33333333) + ((v >> 2)  & 0x33333333U);
42341f9be70SMatthias Ringwald     v = (v & 0x0F0F0F0F) + ((v >> 4)  & 0x0F0F0F0FU);
42441f9be70SMatthias Ringwald     v = (v & 0x00FF00FF) + ((v >> 8)  & 0x00FF00FFU);
42541f9be70SMatthias Ringwald     v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU);
42641f9be70SMatthias Ringwald     return v;
427d1207cd8SMilanka Ringwald }
4281f41c2c9SMatthias Ringwald 
4291f41c2c9SMatthias Ringwald /*
4301f41c2c9SMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
4311f41c2c9SMatthias Ringwald  */
4321f41c2c9SMatthias Ringwald 
4331f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
4341f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
4351f41c2c9SMatthias Ringwald 
4361f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
4371f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
4381f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
4391f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
4401f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
4411f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
4421f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
4431f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
4441f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
4451f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
4461f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
4471f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
4481f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
4491f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
4501f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
4511f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
4521f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
4531f41c2c9SMatthias Ringwald };
4541f41c2c9SMatthias Ringwald 
4551f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
4561f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
4571f41c2c9SMatthias Ringwald     uint16_t count;
4581f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
4591f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
4601f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
4611f41c2c9SMatthias Ringwald     }
4621f41c2c9SMatthias Ringwald     return crc;
4631f41c2c9SMatthias Ringwald }
4641f41c2c9SMatthias Ringwald 
4651f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
46663dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
4671f41c2c9SMatthias Ringwald     uint8_t crc;
4681f41c2c9SMatthias Ringwald     crc = crc8(data, len);
4691f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
4701f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
4711f41c2c9SMatthias Ringwald         return 0;               /* Valid */
4721f41c2c9SMatthias Ringwald     } else {
4731f41c2c9SMatthias Ringwald         return 1;               /* Failed */
4741f41c2c9SMatthias Ringwald     }
4751f41c2c9SMatthias Ringwald }
4761f41c2c9SMatthias Ringwald 
4771f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
47863dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
4791f41c2c9SMatthias Ringwald     /* Ones complement */
4804ea43905SMatthias Ringwald     return 0xFFu - crc8(data, len);
4811f41c2c9SMatthias Ringwald }
482