xref: /btstack/src/btstack_util.c (revision 9305033e0290a73b79a29900c5b9f35f77d880b1)
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 
5246059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
53eb886013SMatthias Ringwald #include <stdio.h>
5446059ae4SMilanka Ringwald #endif
5546059ae4SMilanka Ringwald 
56eb886013SMatthias Ringwald #include <string.h>
57eb886013SMatthias Ringwald 
5873988a59SMatthias Ringwald /**
5973988a59SMatthias Ringwald  * @brief Compare two Bluetooth addresses
6073988a59SMatthias Ringwald  * @param a
6173988a59SMatthias Ringwald  * @param b
62969fc1c5SMilanka Ringwald  * @return 0 if equal
6373988a59SMatthias Ringwald  */
645222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){
6573988a59SMatthias Ringwald     return memcmp(a,b, BD_ADDR_LEN);
6673988a59SMatthias Ringwald }
6773988a59SMatthias Ringwald 
6873988a59SMatthias Ringwald /**
6973988a59SMatthias Ringwald  * @brief Copy Bluetooth address
7073988a59SMatthias Ringwald  * @param dest
7173988a59SMatthias Ringwald  * @param src
7273988a59SMatthias Ringwald  */
735222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){
746535961aSMatthias Ringwald     (void)memcpy(dest, src, BD_ADDR_LEN);
7573988a59SMatthias Ringwald }
7673988a59SMatthias Ringwald 
7773988a59SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int pos){
78b0920f25SMilanka Ringwald     return (uint16_t)(((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8));
7973988a59SMatthias Ringwald }
8073988a59SMatthias Ringwald uint32_t little_endian_read_24(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);
8273988a59SMatthias Ringwald }
8373988a59SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int pos){
8473988a59SMatthias Ringwald     return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16) | (((uint32_t) buffer[(pos)+3]) << 24);
8573988a59SMatthias Ringwald }
8673988a59SMatthias Ringwald 
87f8fbdce0SMatthias Ringwald void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
88b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)value;
89b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
90eb886013SMatthias Ringwald }
91eb886013SMatthias Ringwald 
92adbdd27aSMilanka Ringwald void little_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){
93adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
94adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
95adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
96adbdd27aSMilanka Ringwald }
97adbdd27aSMilanka Ringwald 
98f8fbdce0SMatthias Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
99b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
100b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
101b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
102b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
103eb886013SMatthias Ringwald }
104eb886013SMatthias Ringwald 
10573988a59SMatthias Ringwald uint32_t big_endian_read_16( const uint8_t * buffer, int pos) {
106b0920f25SMilanka Ringwald     return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos   ]) << 8));
10773988a59SMatthias Ringwald }
10873988a59SMatthias Ringwald 
109e57a2545SMilanka Ringwald uint32_t big_endian_read_24( const uint8_t * buffer, int pos) {
110e57a2545SMilanka Ringwald     return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16));
111e57a2545SMilanka Ringwald }
112e57a2545SMilanka Ringwald 
11373988a59SMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
11473988a59SMatthias Ringwald     return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
11573988a59SMatthias Ringwald }
11673988a59SMatthias Ringwald 
117f8fbdce0SMatthias Ringwald void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
118b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
119b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
120eb886013SMatthias Ringwald }
121eb886013SMatthias Ringwald 
1227f535380SMilanka Ringwald void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){
123b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
124b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
125b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1267f535380SMilanka Ringwald }
1277f535380SMilanka Ringwald 
128f8fbdce0SMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
129b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
130b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
131b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
132b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
133eb886013SMatthias Ringwald }
134eb886013SMatthias Ringwald 
135eb886013SMatthias Ringwald // general swap/endianess utils
1369c80e4ccSMatthias Ringwald void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){
137eb886013SMatthias Ringwald     int i;
138eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
139eb886013SMatthias Ringwald         dst[len - 1 - i] = src[i];
140eb886013SMatthias Ringwald }
1419c80e4ccSMatthias Ringwald void reverse_24(const uint8_t * src, uint8_t * dst){
1429c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 3);
143eb886013SMatthias Ringwald }
1449c80e4ccSMatthias Ringwald void reverse_48(const uint8_t * src, uint8_t * dst){
1459c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 6);
146bf1b35bfSMatthias Ringwald }
1479c80e4ccSMatthias Ringwald void reverse_56(const uint8_t * src, uint8_t * dst){
1489c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 7);
149eb886013SMatthias Ringwald }
1509c80e4ccSMatthias Ringwald void reverse_64(const uint8_t * src, uint8_t * dst){
1519c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 8);
152eb886013SMatthias Ringwald }
1539c80e4ccSMatthias Ringwald void reverse_128(const uint8_t * src, uint8_t * dst){
1549c80e4ccSMatthias Ringwald     reverse_bytes(src, dst, 16);
155eb886013SMatthias Ringwald }
156cc7a2d78SMatthias Ringwald void reverse_256(const uint8_t * src, uint8_t * dst){
157cc7a2d78SMatthias Ringwald     reverse_bytes(src, dst, 32);
158cc7a2d78SMatthias Ringwald }
159eb886013SMatthias Ringwald 
160724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
161724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
162724d70a2SMatthias Ringwald }
163724d70a2SMatthias Ringwald 
164ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
165c1ab6cc1SMatthias Ringwald     return (a < b) ? a : b;
166ebaeb1beSMatthias Ringwald }
167ebaeb1beSMatthias Ringwald 
168ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
169c1ab6cc1SMatthias Ringwald     return (a > b) ? a : b;
170ebaeb1beSMatthias Ringwald }
171ebaeb1beSMatthias Ringwald 
17268af3967SMatthias Ringwald /**
17368af3967SMatthias Ringwald  * @brief Calculate delta between two points in time
17468af3967SMatthias Ringwald  * @returns time_a - time_b - result > 0 if time_a is newer than time_b
17568af3967SMatthias Ringwald  */
17668af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){
17768af3967SMatthias Ringwald     return (int32_t)(time_a - time_b);
17868af3967SMatthias Ringwald }
17968af3967SMatthias Ringwald 
180c1c58647SMatthias Ringwald 
181eb886013SMatthias Ringwald char char_for_nibble(int nibble){
1828334d3d8SMatthias Ringwald 
1838334d3d8SMatthias Ringwald     static const char * char_to_nibble = "0123456789ABCDEF";
1848334d3d8SMatthias Ringwald 
185c1c58647SMatthias Ringwald     if (nibble < 16){
186c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
187c1c58647SMatthias Ringwald     } else {
188eb886013SMatthias Ringwald         return '?';
189eb886013SMatthias Ringwald     }
190c1c58647SMatthias Ringwald }
191eb886013SMatthias Ringwald 
192405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
193405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
194405d63a9SMatthias Ringwald }
195405d63a9SMatthias Ringwald 
196405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
197405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
198405d63a9SMatthias Ringwald }
199405d63a9SMatthias Ringwald 
200c1c58647SMatthias Ringwald 
201a6efb919SMatthias Ringwald int nibble_for_char(char c){
202c1ab6cc1SMatthias Ringwald     if ((c >= '0') && (c <= '9')) return c - '0';
203c1ab6cc1SMatthias Ringwald     if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
204c1ab6cc1SMatthias Ringwald     if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
205a6efb919SMatthias Ringwald     return -1;
206a6efb919SMatthias Ringwald }
207a6efb919SMatthias Ringwald 
20846059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
209eb886013SMatthias Ringwald void printf_hexdump(const void *data, int size){
210c1c58647SMatthias Ringwald     char buffer[4];
211c1c58647SMatthias Ringwald     buffer[2] = ' ';
212c1c58647SMatthias Ringwald     buffer[3] =  0;
2139dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
214c1c58647SMatthias Ringwald     while (size > 0){
2159dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
216c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
217c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
218c1c58647SMatthias Ringwald         printf("%s", buffer);
219c1c58647SMatthias Ringwald         size--;
220eb886013SMatthias Ringwald     }
221eb886013SMatthias Ringwald     printf("\n");
222eb886013SMatthias Ringwald }
22346059ae4SMilanka Ringwald #endif
224eb886013SMatthias Ringwald 
225cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
226cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
227405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
228405d63a9SMatthias Ringwald // template '0x12, '
229405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
230405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2317224be7eSMatthias Ringwald     int i, j;
232eb886013SMatthias Ringwald     j = 0;
233eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2347224be7eSMatthias Ringwald 
2357224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
236c1ab6cc1SMatthias Ringwald         if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){
2377224be7eSMatthias Ringwald             j = 0;
2387224be7eSMatthias Ringwald         }
2397224be7eSMatthias Ringwald 
240eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
241eb886013SMatthias Ringwald         buffer[j++] = '0';
242eb886013SMatthias Ringwald         buffer[j++] = 'x';
243405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
244405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
245eb886013SMatthias Ringwald         buffer[j++] = ',';
246eb886013SMatthias Ringwald         buffer[j++] = ' ';
2477224be7eSMatthias Ringwald 
248c1ab6cc1SMatthias Ringwald         if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){
249eb886013SMatthias Ringwald             buffer[j] = 0;
250cb42147aSMatthias Ringwald             HCI_DUMP_LOG(level, "%s", buffer);
251eb886013SMatthias Ringwald             j = 0;
252eb886013SMatthias Ringwald         }
253eb886013SMatthias Ringwald     }
254eb886013SMatthias Ringwald     if (j != 0){
255eb886013SMatthias Ringwald         buffer[j] = 0;
256cb42147aSMatthias Ringwald         HCI_DUMP_LOG(level, "%s", buffer);
257eb886013SMatthias Ringwald     }
258cb42147aSMatthias Ringwald }
259cb42147aSMatthias Ringwald #endif
260cb42147aSMatthias Ringwald 
261cb42147aSMatthias Ringwald void log_debug_hexdump(const void *data, int size){
262e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
263fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
264cb42147aSMatthias Ringwald #else
2654bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2664bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
267cb42147aSMatthias Ringwald #endif
268cb42147aSMatthias Ringwald }
269cb42147aSMatthias Ringwald 
270cb42147aSMatthias Ringwald void log_info_hexdump(const void *data, int size){
271cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
272fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
273d0662982SMatthias Ringwald #else
2744bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2754bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
2768314c363SMatthias Ringwald #endif
2777299c0feSMatthias Ringwald }
278eb886013SMatthias Ringwald 
2798314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
28002bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
28102bdfbf8SMatthias Ringwald     char buffer[16*2+1];
28202bdfbf8SMatthias Ringwald     int i;
28302bdfbf8SMatthias Ringwald     int j = 0;
28402bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
28502bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
286405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
287405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
28802bdfbf8SMatthias Ringwald     }
28902bdfbf8SMatthias Ringwald     buffer[j] = 0;
29002bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
291d0662982SMatthias Ringwald #else
292d0662982SMatthias Ringwald     UNUSED(name);
293cb42147aSMatthias Ringwald     (void)key;
29402bdfbf8SMatthias Ringwald #endif
295eb886013SMatthias Ringwald }
296eb886013SMatthias Ringwald 
2972b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
2982b604902SMatthias Ringwald 
299eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
3002b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
301eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
302eb886013SMatthias Ringwald 
303e1a125dfSMatthias Ringwald void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){
3046535961aSMatthias Ringwald     (void)memcpy(uuid, bluetooth_base_uuid, 16);
305f8fbdce0SMatthias Ringwald     big_endian_store_32(uuid, 0, shortUUID);
306eb886013SMatthias Ringwald }
307eb886013SMatthias Ringwald 
3085222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){
3092b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
310eb886013SMatthias Ringwald }
311eb886013SMatthias Ringwald 
312eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
3135222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
3147224be7eSMatthias Ringwald     int i;
3157224be7eSMatthias Ringwald     int j = 0;
3167224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
3177224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
3187224be7eSMatthias Ringwald     for (i=0;i<16;i++){
319405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
320405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
321405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3227224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3237224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3247224be7eSMatthias Ringwald         }
3257224be7eSMatthias Ringwald     }
326eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
327eb886013SMatthias Ringwald }
328eb886013SMatthias Ringwald 
329eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
3305222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
331eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
332eb886013SMatthias Ringwald     int i;
333eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
334405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
335405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
336405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
337eb886013SMatthias Ringwald         *p++ = ':';
338eb886013SMatthias Ringwald     }
339eb886013SMatthias Ringwald     *--p = 0;
340eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
341eb886013SMatthias Ringwald }
342eb886013SMatthias Ringwald 
3433c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){
3443c9da642SMatthias Ringwald     const int bd_addr_string_len = 17;
34530314625SMatthias Ringwald     uint16_t i = 0;
34630314625SMatthias Ringwald     while ((i + bd_addr_string_len) <= size){
3473c9da642SMatthias Ringwald         if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) {
3483c9da642SMatthias Ringwald             i++;
3493c9da642SMatthias Ringwald             continue;
3503c9da642SMatthias Ringwald         }
3513c9da642SMatthias Ringwald         // set address
3523c9da642SMatthias Ringwald         (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len);
3533c9da642SMatthias Ringwald         i += bd_addr_string_len;
3543c9da642SMatthias Ringwald     }
3553c9da642SMatthias Ringwald }
3563c9da642SMatthias Ringwald 
357a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
358a6efb919SMatthias Ringwald     int upper_nibble = nibble_for_char(*byte_string++);
359a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
360a6efb919SMatthias Ringwald     int lower_nibble = nibble_for_char(*byte_string);
361a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
362a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
363a6efb919SMatthias Ringwald }
364eb886013SMatthias Ringwald 
365a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
366a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
367a6efb919SMatthias Ringwald     int result = 0;
368eb886013SMatthias Ringwald     int i;
369eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
370a6efb919SMatthias Ringwald         int single_byte = scan_hex_byte(addr_string);
371a6efb919SMatthias Ringwald         if (single_byte < 0) break;
372a6efb919SMatthias Ringwald         addr_string += 2;
373b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
374a6efb919SMatthias Ringwald         // don't check seperator after last byte
375c1ab6cc1SMatthias Ringwald         if (i == (BD_ADDR_LEN - 1)) {
376a6efb919SMatthias Ringwald             result = 1;
377a6efb919SMatthias Ringwald             break;
378eb886013SMatthias Ringwald         }
379cd2e416cSMatthias Ringwald         // skip supported separators
380cd2e416cSMatthias Ringwald         char next_char = *addr_string;
3815df9dc78SMatthias Ringwald         if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) {
382cd2e416cSMatthias Ringwald             addr_string++;
383cd2e416cSMatthias Ringwald         }
384a6efb919SMatthias Ringwald     }
385a6efb919SMatthias Ringwald 
386*9305033eSMatthias Ringwald     if (result != 0){
387a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
388a6efb919SMatthias Ringwald     }
389a6efb919SMatthias Ringwald 	return result;
390eb886013SMatthias Ringwald }
3915d067ab1SMatthias Ringwald 
3925d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){
3935d067ab1SMatthias Ringwald     uint32_t val = 0;
394ff3cc4a5SMatthias Ringwald     while (true){
3955d067ab1SMatthias Ringwald         char chr = *str;
396c1ab6cc1SMatthias Ringwald         if (!chr || (chr < '0') || (chr > '9'))
3975d067ab1SMatthias Ringwald             return val;
3984ea43905SMatthias Ringwald         val = (val * 10u) + (uint8_t)(chr - '0');
3995d067ab1SMatthias Ringwald         str++;
4005d067ab1SMatthias Ringwald     }
4015d067ab1SMatthias Ringwald }
4021f41c2c9SMatthias Ringwald 
403d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
404d1207cd8SMilanka Ringwald     if (i <         10) return 1;
405d1207cd8SMilanka Ringwald     if (i <        100) return 2;
406d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
407d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
408d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
409d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
410d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
411d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
412d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
413d1207cd8SMilanka Ringwald     return 10;
414d1207cd8SMilanka Ringwald }
415d1207cd8SMilanka Ringwald 
416d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
417d1207cd8SMilanka Ringwald     x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
418d1207cd8SMilanka Ringwald     x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
419d1207cd8SMilanka Ringwald     x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
420d1207cd8SMilanka Ringwald     x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
421d1207cd8SMilanka Ringwald     x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
422d1207cd8SMilanka Ringwald     return x;
423d1207cd8SMilanka Ringwald }
4241f41c2c9SMatthias Ringwald 
4251f41c2c9SMatthias Ringwald /*
4261f41c2c9SMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
4271f41c2c9SMatthias Ringwald  */
4281f41c2c9SMatthias Ringwald 
4291f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
4301f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
4311f41c2c9SMatthias Ringwald 
4321f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
4331f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
4341f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
4351f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
4361f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
4371f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
4381f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
4391f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
4401f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
4411f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
4421f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
4431f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
4441f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
4451f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
4461f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
4471f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
4481f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
4491f41c2c9SMatthias Ringwald };
4501f41c2c9SMatthias Ringwald 
4511f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
4521f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
4531f41c2c9SMatthias Ringwald     uint16_t count;
4541f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
4551f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
4561f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
4571f41c2c9SMatthias Ringwald     }
4581f41c2c9SMatthias Ringwald     return crc;
4591f41c2c9SMatthias Ringwald }
4601f41c2c9SMatthias Ringwald 
4611f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
46263dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
4631f41c2c9SMatthias Ringwald     uint8_t crc;
4641f41c2c9SMatthias Ringwald     crc = crc8(data, len);
4651f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
4661f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
4671f41c2c9SMatthias Ringwald         return 0;               /* Valid */
4681f41c2c9SMatthias Ringwald     } else {
4691f41c2c9SMatthias Ringwald         return 1;               /* Failed */
4701f41c2c9SMatthias Ringwald     }
4711f41c2c9SMatthias Ringwald }
4721f41c2c9SMatthias Ringwald 
4731f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
47463dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
4751f41c2c9SMatthias Ringwald     /* Ones complement */
4764ea43905SMatthias Ringwald     return 0xFFu - crc8(data, len);
4771f41c2c9SMatthias Ringwald }
478