xref: /btstack/src/btstack_util.c (revision b795dcd07cafa39590ef7b7e12c7051fdb8ae36a)
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
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH 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 
44*b795dcd0SMarcel Wappler #ifdef _MSC_VER
45*b795dcd0SMarcel Wappler #include <Windows.h>
46*b795dcd0SMarcel Wappler #include <intrin.h>
47*b795dcd0SMarcel Wappler #endif
48*b795dcd0SMarcel Wappler 
497907f069SMatthias Ringwald #include "btstack_config.h"
5002bdfbf8SMatthias Ringwald #include "btstack_debug.h"
51eb886013SMatthias Ringwald #include "btstack_util.h"
5202bdfbf8SMatthias Ringwald 
53ad144fa1SMatthias Ringwald #include <stdio.h>  // vsnprintf
54ad144fa1SMatthias Ringwald #include <string.h> // memcpy
55ad144fa1SMatthias Ringwald 
56ec08441fSMatthias Ringwald 
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 
7741f9be70SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int position){
7841f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8));
7973988a59SMatthias Ringwald }
8041f9be70SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int position){
8141f9be70SMatthias Ringwald     return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16);
8273988a59SMatthias Ringwald }
8341f9be70SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int position){
8441f9be70SMatthias Ringwald     return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24);
8573988a59SMatthias Ringwald }
8673988a59SMatthias Ringwald 
8741f9be70SMatthias Ringwald void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
8841f9be70SMatthias Ringwald     uint16_t pos = position;
89b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)value;
90b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
91eb886013SMatthias Ringwald }
92eb886013SMatthias Ringwald 
9341f9be70SMatthias Ringwald void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
9441f9be70SMatthias Ringwald     uint16_t pos = position;
95adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
96adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
97adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
98adbdd27aSMilanka Ringwald }
99adbdd27aSMilanka Ringwald 
10041f9be70SMatthias Ringwald void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
10141f9be70SMatthias Ringwald     uint16_t pos = position;
102b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
103b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
104b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
105b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
106eb886013SMatthias Ringwald }
107eb886013SMatthias Ringwald 
10841f9be70SMatthias Ringwald uint32_t big_endian_read_16(const uint8_t * buffer, int position) {
10941f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8));
11073988a59SMatthias Ringwald }
11173988a59SMatthias Ringwald 
11241f9be70SMatthias Ringwald uint32_t big_endian_read_24(const uint8_t * buffer, int position) {
11341f9be70SMatthias Ringwald     return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16));
114e57a2545SMilanka Ringwald }
115e57a2545SMilanka Ringwald 
11641f9be70SMatthias Ringwald uint32_t big_endian_read_32(const uint8_t * buffer, int position) {
11741f9be70SMatthias Ringwald     return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24);
11873988a59SMatthias Ringwald }
11973988a59SMatthias Ringwald 
12041f9be70SMatthias Ringwald void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
12141f9be70SMatthias Ringwald     uint16_t pos = position;
122b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
123b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
124eb886013SMatthias Ringwald }
125eb886013SMatthias Ringwald 
12641f9be70SMatthias Ringwald void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
12741f9be70SMatthias Ringwald     uint16_t pos = position;
128b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
129b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
130b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1317f535380SMilanka Ringwald }
1327f535380SMilanka Ringwald 
13341f9be70SMatthias Ringwald void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
13441f9be70SMatthias Ringwald     uint16_t pos = position;
135b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
136b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
137b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
138b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
139eb886013SMatthias Ringwald }
140eb886013SMatthias Ringwald 
141eb886013SMatthias Ringwald // general swap/endianess utils
142b45b7749SMilanka Ringwald void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){
143eb886013SMatthias Ringwald     int i;
144eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
145b45b7749SMilanka Ringwald         dest[len - 1 - i] = src[i];
146eb886013SMatthias Ringwald }
147b45b7749SMilanka Ringwald void reverse_24(const uint8_t * src, uint8_t * dest){
148b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 3);
149eb886013SMatthias Ringwald }
150b45b7749SMilanka Ringwald void reverse_48(const uint8_t * src, uint8_t * dest){
151b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 6);
152bf1b35bfSMatthias Ringwald }
153b45b7749SMilanka Ringwald void reverse_56(const uint8_t * src, uint8_t * dest){
154b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 7);
155eb886013SMatthias Ringwald }
156b45b7749SMilanka Ringwald void reverse_64(const uint8_t * src, uint8_t * dest){
157b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 8);
158eb886013SMatthias Ringwald }
159b45b7749SMilanka Ringwald void reverse_128(const uint8_t * src, uint8_t * dest){
160b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 16);
161eb886013SMatthias Ringwald }
162b45b7749SMilanka Ringwald void reverse_256(const uint8_t * src, uint8_t * dest){
163b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 32);
164cc7a2d78SMatthias Ringwald }
165eb886013SMatthias Ringwald 
166724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
167724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
168724d70a2SMatthias Ringwald }
169724d70a2SMatthias Ringwald 
17077955af6SMatthias Ringwald bool btstack_is_null(const uint8_t * buffer, uint16_t size){
17177955af6SMatthias Ringwald     uint16_t i;
17277955af6SMatthias Ringwald     for (i=0; i < size ; i++){
17377955af6SMatthias Ringwald         if (buffer[i] != 0) {
17477955af6SMatthias Ringwald             return false;
17577955af6SMatthias Ringwald         }
17677955af6SMatthias Ringwald     }
17777955af6SMatthias Ringwald     return true;
17877955af6SMatthias Ringwald }
17977955af6SMatthias Ringwald 
1806d708481SDirk Helbig bool btstack_is_null_bd_addr( const bd_addr_t addr ){
1816d708481SDirk Helbig     return btstack_is_null( addr, sizeof(bd_addr_t) );
1826d708481SDirk Helbig }
1836d708481SDirk Helbig 
184ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
185c1ab6cc1SMatthias Ringwald     return (a < b) ? a : b;
186ebaeb1beSMatthias Ringwald }
187ebaeb1beSMatthias Ringwald 
188ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
189c1ab6cc1SMatthias Ringwald     return (a > b) ? a : b;
190ebaeb1beSMatthias Ringwald }
191ebaeb1beSMatthias Ringwald 
19268af3967SMatthias Ringwald /**
193a9d566f7SMatthias Ringwald  * @brief Calculate delta between two uint32_t points in time
1946b65794dSMilanka Ringwald  * @return time_a - time_b - result > 0 if time_a is newer than time_b
19568af3967SMatthias Ringwald  */
19668af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){
19768af3967SMatthias Ringwald     return (int32_t)(time_a - time_b);
19868af3967SMatthias Ringwald }
19968af3967SMatthias Ringwald 
200a9d566f7SMatthias Ringwald /**
201a9d566f7SMatthias Ringwald  * @brief Calculate delta between two uint16_t points in time
202a9d566f7SMatthias Ringwald  * @return time_a - time_b - result > 0 if time_a is newer than time_b
203a9d566f7SMatthias Ringwald  */
204a9d566f7SMatthias Ringwald int16_t btstack_time16_delta(uint16_t time_a, uint16_t time_b){
205a9d566f7SMatthias Ringwald     return (int16_t)(time_a - time_b);
206a9d566f7SMatthias Ringwald }
207c1c58647SMatthias Ringwald 
208d7d45b32SMatthias Ringwald char char_for_nibble(uint8_t nibble){
2098334d3d8SMatthias Ringwald 
2108334d3d8SMatthias Ringwald     static const char * char_to_nibble = "0123456789ABCDEF";
2118334d3d8SMatthias Ringwald 
212c1c58647SMatthias Ringwald     if (nibble < 16){
213c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
214c1c58647SMatthias Ringwald     } else {
215eb886013SMatthias Ringwald         return '?';
216eb886013SMatthias Ringwald     }
217c1c58647SMatthias Ringwald }
218eb886013SMatthias Ringwald 
219405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
220405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
221405d63a9SMatthias Ringwald }
222405d63a9SMatthias Ringwald 
223405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
224405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
225405d63a9SMatthias Ringwald }
226405d63a9SMatthias Ringwald 
227c1c58647SMatthias Ringwald 
228a6efb919SMatthias Ringwald int nibble_for_char(char c){
229c1ab6cc1SMatthias Ringwald     if ((c >= '0') && (c <= '9')) return c - '0';
230c1ab6cc1SMatthias Ringwald     if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
231c1ab6cc1SMatthias Ringwald     if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
232a6efb919SMatthias Ringwald     return -1;
233a6efb919SMatthias Ringwald }
234a6efb919SMatthias Ringwald 
23546059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
236eb886013SMatthias Ringwald void printf_hexdump(const void * data, int size){
237c1c58647SMatthias Ringwald     char buffer[4];
238c1c58647SMatthias Ringwald     buffer[2] = ' ';
239c1c58647SMatthias Ringwald     buffer[3] =  0;
2409dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
241c1c58647SMatthias Ringwald     while (size > 0){
2429dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
243c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
244c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
245c1c58647SMatthias Ringwald         printf("%s", buffer);
246c1c58647SMatthias Ringwald         size--;
247eb886013SMatthias Ringwald     }
248eb886013SMatthias Ringwald     printf("\n");
249eb886013SMatthias Ringwald }
25046059ae4SMilanka Ringwald #endif
251eb886013SMatthias Ringwald 
252cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
253cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
254405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
255405d63a9SMatthias Ringwald // template '0x12, '
256405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
257405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2587224be7eSMatthias Ringwald     int i, j;
259eb886013SMatthias Ringwald     j = 0;
260eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2617224be7eSMatthias Ringwald 
2627224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
263c1ab6cc1SMatthias Ringwald         if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){
2647224be7eSMatthias Ringwald             j = 0;
2657224be7eSMatthias Ringwald         }
2667224be7eSMatthias Ringwald 
267eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
268eb886013SMatthias Ringwald         buffer[j++] = '0';
269eb886013SMatthias Ringwald         buffer[j++] = 'x';
270405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
271405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
272eb886013SMatthias Ringwald         buffer[j++] = ',';
273eb886013SMatthias Ringwald         buffer[j++] = ' ';
2747224be7eSMatthias Ringwald 
275c1ab6cc1SMatthias Ringwald         if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){
276eb886013SMatthias Ringwald             buffer[j] = 0;
277cb42147aSMatthias Ringwald             HCI_DUMP_LOG(level, "%s", buffer);
278eb886013SMatthias Ringwald             j = 0;
279eb886013SMatthias Ringwald         }
280eb886013SMatthias Ringwald     }
281eb886013SMatthias Ringwald     if (j != 0){
282eb886013SMatthias Ringwald         buffer[j] = 0;
283cb42147aSMatthias Ringwald         HCI_DUMP_LOG(level, "%s", buffer);
284eb886013SMatthias Ringwald     }
285cb42147aSMatthias Ringwald }
286cb42147aSMatthias Ringwald #endif
287cb42147aSMatthias Ringwald 
288cb42147aSMatthias Ringwald void log_debug_hexdump(const void * data, int size){
289e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
290fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
291cb42147aSMatthias Ringwald #else
2924bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
2934bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
294cb42147aSMatthias Ringwald #endif
295cb42147aSMatthias Ringwald }
296cb42147aSMatthias Ringwald 
297cb42147aSMatthias Ringwald void log_info_hexdump(const void * data, int size){
298cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
299fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
300d0662982SMatthias Ringwald #else
3014bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
3024bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
3038314c363SMatthias Ringwald #endif
3047299c0feSMatthias Ringwald }
305eb886013SMatthias Ringwald 
3068314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
30702bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
30802bdfbf8SMatthias Ringwald     char buffer[16*2+1];
30902bdfbf8SMatthias Ringwald     int i;
31002bdfbf8SMatthias Ringwald     int j = 0;
31102bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
31202bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
313405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
314405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
31502bdfbf8SMatthias Ringwald     }
31602bdfbf8SMatthias Ringwald     buffer[j] = 0;
31702bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
318d0662982SMatthias Ringwald #else
319d0662982SMatthias Ringwald     UNUSED(name);
320cb42147aSMatthias Ringwald     (void)key;
32102bdfbf8SMatthias Ringwald #endif
322eb886013SMatthias Ringwald }
323eb886013SMatthias Ringwald 
3242b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
3252b604902SMatthias Ringwald 
326eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
3272b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
328eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
329eb886013SMatthias Ringwald 
33048cdff9cSMilanka Ringwald void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid){
331b45b7749SMilanka Ringwald     (void)memcpy(uuid128, bluetooth_base_uuid, 16);
33248cdff9cSMilanka Ringwald     big_endian_store_32(uuid128, 0, short_uuid);
333eb886013SMatthias Ringwald }
334eb886013SMatthias Ringwald 
3358933879eSMatthias Ringwald bool uuid_has_bluetooth_prefix(const uint8_t * uuid128){
3362b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
337eb886013SMatthias Ringwald }
338eb886013SMatthias Ringwald 
339eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
3405222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
3417224be7eSMatthias Ringwald     int i;
3427224be7eSMatthias Ringwald     int j = 0;
3437224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
3447224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
3457224be7eSMatthias Ringwald     for (i=0;i<16;i++){
346405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
347405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
348405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3497224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3507224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3517224be7eSMatthias Ringwald         }
3527224be7eSMatthias Ringwald     }
353eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
354eb886013SMatthias Ringwald }
355eb886013SMatthias Ringwald 
356eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
35761c3ec28SMatthias Ringwald char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter){
358eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
359eb886013SMatthias Ringwald     int i;
360eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
361405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
362405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
363405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
36461c3ec28SMatthias Ringwald         *p++ = delimiter;
365eb886013SMatthias Ringwald     }
366eb886013SMatthias Ringwald     *--p = 0;
367eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
368eb886013SMatthias Ringwald }
369eb886013SMatthias Ringwald 
37061c3ec28SMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
37161c3ec28SMatthias Ringwald     return bd_addr_to_str_with_delimiter(addr, ':');
37261c3ec28SMatthias Ringwald }
37361c3ec28SMatthias Ringwald 
3743c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){
3753c9da642SMatthias Ringwald     const int bd_addr_string_len = 17;
37630314625SMatthias Ringwald     uint16_t i = 0;
37730314625SMatthias Ringwald     while ((i + bd_addr_string_len) <= size){
3783c9da642SMatthias Ringwald         if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) {
3793c9da642SMatthias Ringwald             i++;
3803c9da642SMatthias Ringwald             continue;
3813c9da642SMatthias Ringwald         }
3823c9da642SMatthias Ringwald         // set address
3833c9da642SMatthias Ringwald         (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len);
3843c9da642SMatthias Ringwald         i += bd_addr_string_len;
3853c9da642SMatthias Ringwald     }
3863c9da642SMatthias Ringwald }
3873c9da642SMatthias Ringwald 
388a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
38941f9be70SMatthias Ringwald     int upper_nibble = nibble_for_char(byte_string[0]);
390a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
39141f9be70SMatthias Ringwald     int lower_nibble = nibble_for_char(byte_string[1]);
392a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
393a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
394a6efb919SMatthias Ringwald }
395eb886013SMatthias Ringwald 
396a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
39741f9be70SMatthias Ringwald     const char * the_string = addr_string;
398a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
399a6efb919SMatthias Ringwald     int result = 0;
400eb886013SMatthias Ringwald     int i;
401eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
40241f9be70SMatthias Ringwald         int single_byte = scan_hex_byte(the_string);
403a6efb919SMatthias Ringwald         if (single_byte < 0) break;
40441f9be70SMatthias Ringwald         the_string += 2;
405b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
40641f9be70SMatthias Ringwald         // don't check separator after last byte
407c1ab6cc1SMatthias Ringwald         if (i == (BD_ADDR_LEN - 1)) {
408a6efb919SMatthias Ringwald             result = 1;
409a6efb919SMatthias Ringwald             break;
410eb886013SMatthias Ringwald         }
411cd2e416cSMatthias Ringwald         // skip supported separators
41241f9be70SMatthias Ringwald         char next_char = *the_string;
4135df9dc78SMatthias Ringwald         if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) {
41441f9be70SMatthias Ringwald             the_string++;
415cd2e416cSMatthias Ringwald         }
416a6efb919SMatthias Ringwald     }
417a6efb919SMatthias Ringwald 
4189305033eSMatthias Ringwald     if (result != 0){
419a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
420a6efb919SMatthias Ringwald     }
421a6efb919SMatthias Ringwald 	return result;
422eb886013SMatthias Ringwald }
4235d067ab1SMatthias Ringwald 
4245d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char * str){
42541f9be70SMatthias Ringwald     const char * the_string = str;
4265d067ab1SMatthias Ringwald     uint32_t val = 0;
427ff3cc4a5SMatthias Ringwald     while (true){
42841f9be70SMatthias Ringwald         char chr = *the_string++;
429c1ab6cc1SMatthias Ringwald         if (!chr || (chr < '0') || (chr > '9'))
4305d067ab1SMatthias Ringwald             return val;
4314ea43905SMatthias Ringwald         val = (val * 10u) + (uint8_t)(chr - '0');
4325d067ab1SMatthias Ringwald     }
4335d067ab1SMatthias Ringwald }
4341f41c2c9SMatthias Ringwald 
435d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
436d1207cd8SMilanka Ringwald     if (i <         10) return 1;
437d1207cd8SMilanka Ringwald     if (i <        100) return 2;
438d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
439d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
440d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
441d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
442d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
443d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
444d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
445d1207cd8SMilanka Ringwald     return 10;
446d1207cd8SMilanka Ringwald }
447d1207cd8SMilanka Ringwald 
448d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
44941f9be70SMatthias Ringwald     uint32_t v = x;
45041f9be70SMatthias Ringwald     v = (v & 0x55555555) + ((v >> 1)  & 0x55555555U);
45141f9be70SMatthias Ringwald     v = (v & 0x33333333) + ((v >> 2)  & 0x33333333U);
45241f9be70SMatthias Ringwald     v = (v & 0x0F0F0F0F) + ((v >> 4)  & 0x0F0F0F0FU);
45341f9be70SMatthias Ringwald     v = (v & 0x00FF00FF) + ((v >> 8)  & 0x00FF00FFU);
45441f9be70SMatthias Ringwald     v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU);
45541f9be70SMatthias Ringwald     return v;
456d1207cd8SMilanka Ringwald }
4571f41c2c9SMatthias Ringwald 
458ec08441fSMatthias Ringwald uint8_t btstack_clz(uint32_t value) {
4591a8c5172SDirk Helbig     btstack_assert( value != 0 );
460ec08441fSMatthias Ringwald #if defined(__GNUC__) || defined (__clang__)
461ec08441fSMatthias Ringwald     // use gcc/clang intrinsic
462ec08441fSMatthias Ringwald     return (uint8_t) __builtin_clz(value);
463ec08441fSMatthias Ringwald #elif defined(_MSC_VER)
464ec08441fSMatthias Ringwald     // use MSVC intrinsic
465ec08441fSMatthias Ringwald     DWORD leading_zero = 0;
4666f5aa202SMatthias Ringwald     _BitScanReverse( &leading_zero, value );
467ec08441fSMatthias Ringwald 	return (uint8_t)(31 - leading_zero);
468ec08441fSMatthias Ringwald #else
469ec08441fSMatthias Ringwald     // divide-and-conquer implementation for 32-bit integers
470af0ac871SAlec Cantor     uint32_t x = value;
471ec08441fSMatthias Ringwald     uint8_t r = 0;
472ec08441fSMatthias Ringwald     if ((x & 0xffff0000u) == 0) {
473ec08441fSMatthias Ringwald         x <<= 16;
474ec08441fSMatthias Ringwald         r += 16;
475ec08441fSMatthias Ringwald     }
476ec08441fSMatthias Ringwald     if ((x & 0xff000000u) == 0) {
477ec08441fSMatthias Ringwald         x <<= 8;
478ec08441fSMatthias Ringwald         r += 8;
479ec08441fSMatthias Ringwald     }
480ec08441fSMatthias Ringwald     if ((x & 0xf0000000u) == 0) {
481ec08441fSMatthias Ringwald         x <<= 4;
482ec08441fSMatthias Ringwald         r += 4;
483ec08441fSMatthias Ringwald     }
484ec08441fSMatthias Ringwald     if ((x & 0xc0000000u) == 0) {
485ec08441fSMatthias Ringwald         x <<= 2;
486ec08441fSMatthias Ringwald         r += 2;
487ec08441fSMatthias Ringwald     }
488ec08441fSMatthias Ringwald     if ((x & 0x80000000u) == 0) {
489ec08441fSMatthias Ringwald         x <<= 1;
490ec08441fSMatthias Ringwald         r += 1;
491ec08441fSMatthias Ringwald     }
492ec08441fSMatthias Ringwald     return r;
493ec08441fSMatthias Ringwald #endif
494ec08441fSMatthias Ringwald }
495ec08441fSMatthias Ringwald 
4961f41c2c9SMatthias Ringwald /*
49742fea667SMilanka Ringwald  * CRC-8 (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
4981f41c2c9SMatthias Ringwald  */
4991f41c2c9SMatthias Ringwald 
5001f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
5011f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
5021f41c2c9SMatthias Ringwald 
5031f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
5041f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
5051f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
5061f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
5071f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
5081f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
5091f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
5101f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
5111f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
5121f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
5131f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
5141f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
5151f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
5161f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
5171f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
5181f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
5191f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
5201f41c2c9SMatthias Ringwald };
5211f41c2c9SMatthias Ringwald 
5221f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
5231f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
5241f41c2c9SMatthias Ringwald     uint16_t count;
5251f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
5261f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
5271f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
5281f41c2c9SMatthias Ringwald     }
5291f41c2c9SMatthias Ringwald     return crc;
5301f41c2c9SMatthias Ringwald }
5311f41c2c9SMatthias Ringwald 
5321f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
53363dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
5341f41c2c9SMatthias Ringwald     uint8_t crc;
5351f41c2c9SMatthias Ringwald     crc = crc8(data, len);
5361f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
5371f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
5381f41c2c9SMatthias Ringwald         return 0;               /* Valid */
5391f41c2c9SMatthias Ringwald     } else {
5401f41c2c9SMatthias Ringwald         return 1;               /* Failed */
5411f41c2c9SMatthias Ringwald     }
5421f41c2c9SMatthias Ringwald }
5431f41c2c9SMatthias Ringwald 
5441f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
54563dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
5461f41c2c9SMatthias Ringwald     /* Ones complement */
5474ea43905SMatthias Ringwald     return 0xFFu - crc8(data, len);
5481f41c2c9SMatthias Ringwald }
549a73d0b9dSMilanka Ringwald 
55042fea667SMilanka Ringwald /*
55142fea667SMilanka Ringwald  * CRC-32 lookup table as calculated by the table generator. Polynomial (normal) 0x04c11db7, ISO 3309 (HDLC)
55242fea667SMilanka Ringwald  *
55342fea667SMilanka Ringwald  * Created using pycrc tool (https://pycrc.org) with "crc-32" as model, and "table-driven" algorithm
55442fea667SMilanka Ringwald  *  python3 pycrc.py --model crc-32 --algorithm table-driven --generate h -o crc32.h
55542fea667SMilanka Ringwald  *  python3 pycrc.py --model crc-32 --algorithm table-driven --generate c -o crc32.c
55642fea667SMilanka Ringwald  */
55742fea667SMilanka Ringwald 
55842fea667SMilanka Ringwald /**
55942fea667SMilanka Ringwald  * Static table used for the table_driven implementation.
56042fea667SMilanka Ringwald  */
56142fea667SMilanka Ringwald static const uint32_t crc_table[256] = {
56242fea667SMilanka Ringwald     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
56342fea667SMilanka Ringwald     0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
56442fea667SMilanka Ringwald     0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
56542fea667SMilanka Ringwald     0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
56642fea667SMilanka Ringwald     0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
56742fea667SMilanka Ringwald     0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
56842fea667SMilanka Ringwald     0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
56942fea667SMilanka Ringwald     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
57042fea667SMilanka Ringwald     0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
57142fea667SMilanka Ringwald     0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
57242fea667SMilanka Ringwald     0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
57342fea667SMilanka Ringwald     0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
57442fea667SMilanka Ringwald     0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
57542fea667SMilanka Ringwald     0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
57642fea667SMilanka Ringwald     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
57742fea667SMilanka Ringwald     0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
57842fea667SMilanka Ringwald     0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
57942fea667SMilanka Ringwald     0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
58042fea667SMilanka Ringwald     0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
58142fea667SMilanka Ringwald     0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
58242fea667SMilanka Ringwald     0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
58342fea667SMilanka Ringwald     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
58442fea667SMilanka Ringwald     0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
58542fea667SMilanka Ringwald     0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
58642fea667SMilanka Ringwald     0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
58742fea667SMilanka Ringwald     0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
58842fea667SMilanka Ringwald     0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
58942fea667SMilanka Ringwald     0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
59042fea667SMilanka Ringwald     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
59142fea667SMilanka Ringwald     0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
59242fea667SMilanka Ringwald     0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
59342fea667SMilanka Ringwald     0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
59442fea667SMilanka Ringwald };
59542fea667SMilanka Ringwald 
59642fea667SMilanka Ringwald uint32_t btstack_crc32_init(void){
59742fea667SMilanka Ringwald     return 0xffffffff;
59842fea667SMilanka Ringwald }
59942fea667SMilanka Ringwald 
60042fea667SMilanka Ringwald uint32_t btstack_crc32_update(uint32_t crc, const uint8_t * data, uint32_t data_len){
60176468bbdSMilanka Ringwald     const uint8_t *d = data;
60242fea667SMilanka Ringwald     uint32_t tbl_idx;
60342fea667SMilanka Ringwald 
60442fea667SMilanka Ringwald     while (data_len--) {
60542fea667SMilanka Ringwald         tbl_idx = (crc ^ *d) & 0xff;
60642fea667SMilanka Ringwald         crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
60742fea667SMilanka Ringwald         d++;
60842fea667SMilanka Ringwald     }
60942fea667SMilanka Ringwald     return crc & 0xffffffff;
61042fea667SMilanka Ringwald }
61142fea667SMilanka Ringwald 
61242fea667SMilanka Ringwald uint32_t btstack_crc32_finalize(uint32_t crc){
61342fea667SMilanka Ringwald     return crc ^ 0xffffffff;
61442fea667SMilanka Ringwald }
61542fea667SMilanka Ringwald 
61642fea667SMilanka Ringwald /*-----------------------------------------------------------------------------------*/
61742fea667SMilanka Ringwald 
618a73d0b9dSMilanka Ringwald uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid){
619a73d0b9dSMilanka Ringwald     uint16_t next_cid;
620a73d0b9dSMilanka Ringwald     if (current_cid == 0xffff) {
621a73d0b9dSMilanka Ringwald         next_cid = 1;
622a73d0b9dSMilanka Ringwald     } else {
623a73d0b9dSMilanka Ringwald         next_cid = current_cid + 1;
624a73d0b9dSMilanka Ringwald     }
625a73d0b9dSMilanka Ringwald     return next_cid;
626a73d0b9dSMilanka Ringwald }
627de22414aSMatthias Ringwald 
628ed7a067cSMilanka Ringwald uint16_t btstack_strcpy(char * dst, uint16_t dst_size, const char * src){
6291a3bc516SMatthias Ringwald     uint16_t bytes_to_copy = (uint16_t) btstack_min( dst_size - 1, (uint16_t) strlen(src));
630de22414aSMatthias Ringwald     (void) memcpy(dst, src, bytes_to_copy);
631981f700bSMatthias Ringwald     dst[bytes_to_copy] = 0;
632ed7a067cSMilanka Ringwald     return bytes_to_copy + 1;
633de22414aSMatthias Ringwald }
6343ece4788SMatthias Ringwald 
6353ece4788SMatthias Ringwald void btstack_strcat(char * dst, uint16_t dst_size, const char * src){
6363ece4788SMatthias Ringwald     uint16_t src_len = (uint16_t) strlen(src);
6373ece4788SMatthias Ringwald     uint16_t dst_len = (uint16_t) strlen(dst);
6383ece4788SMatthias Ringwald     uint16_t bytes_to_copy = btstack_min( src_len, dst_size - dst_len - 1);
6393ece4788SMatthias Ringwald     (void) memcpy( &dst[dst_len], src, bytes_to_copy);
6403ece4788SMatthias Ringwald     dst[dst_len + bytes_to_copy] = 0;
6413ece4788SMatthias Ringwald }
642f819d1d9SMilanka Ringwald 
643ad144fa1SMatthias Ringwald int btstack_printf_strlen(const char * format, ...){
644ad144fa1SMatthias Ringwald     va_list argptr;
645ad144fa1SMatthias Ringwald     va_start(argptr, format);
646ad144fa1SMatthias Ringwald     char dummy_buffer[1];
647ad144fa1SMatthias Ringwald     int len = vsnprintf(dummy_buffer, sizeof(dummy_buffer), format, argptr);
648ad144fa1SMatthias Ringwald     va_end(argptr);
649ad144fa1SMatthias Ringwald     return len;
650ad144fa1SMatthias Ringwald }
651ad144fa1SMatthias Ringwald 
652ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_assert_complete(char * buffer, size_t size, const char * format, ...){
653ad144fa1SMatthias Ringwald     va_list argptr;
654ad144fa1SMatthias Ringwald     va_start(argptr, format);
655ad144fa1SMatthias Ringwald     int len = vsnprintf(buffer, size, format, argptr);
656ad144fa1SMatthias Ringwald     va_end(argptr);
657ad144fa1SMatthias Ringwald 
658ad144fa1SMatthias Ringwald     // check for no error and no truncation
659ad144fa1SMatthias Ringwald     btstack_assert(len >= 0);
660ad144fa1SMatthias Ringwald     btstack_assert(len < size);
661ad144fa1SMatthias Ringwald     return (uint16_t) len;
662ad144fa1SMatthias Ringwald }
663ad144fa1SMatthias Ringwald 
664ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_best_effort(char * buffer, size_t size, const char * format, ...){
665ad144fa1SMatthias Ringwald     btstack_assert(size > 0);
666ad144fa1SMatthias Ringwald     va_list argptr;
667ad144fa1SMatthias Ringwald     va_start(argptr, format);
668ad144fa1SMatthias Ringwald     int len = vsnprintf(buffer, size, format, argptr);
669ad144fa1SMatthias Ringwald     va_end(argptr);
670ad144fa1SMatthias Ringwald     if (len < 0) {
671ad144fa1SMatthias Ringwald         // error -> len = 0
672ad144fa1SMatthias Ringwald         return 0;
673ad144fa1SMatthias Ringwald     } else {
674ad144fa1SMatthias Ringwald         // min of total string len and buffer size
675ad144fa1SMatthias Ringwald         return (uint16_t) btstack_min((uint32_t) len, (uint32_t) size - 1);
676ad144fa1SMatthias Ringwald     }
677ad144fa1SMatthias Ringwald }
678ad144fa1SMatthias Ringwald 
679f819d1d9SMilanka Ringwald uint16_t btstack_virtual_memcpy(
680f819d1d9SMilanka Ringwald     const uint8_t * field_data, uint16_t field_len, uint16_t field_offset, // position of field in complete data block
681f819d1d9SMilanka Ringwald     uint8_t * buffer, uint16_t buffer_size, uint16_t buffer_offset){
682f819d1d9SMilanka Ringwald 
683f819d1d9SMilanka Ringwald     uint16_t after_buffer = buffer_offset + buffer_size ;
684f819d1d9SMilanka Ringwald     // bail before buffer
685f819d1d9SMilanka Ringwald     if ((field_offset + field_len) < buffer_offset){
686f819d1d9SMilanka Ringwald         return 0;
687f819d1d9SMilanka Ringwald     }
688f819d1d9SMilanka Ringwald     // bail after buffer
689f819d1d9SMilanka Ringwald     if (field_offset >= after_buffer){
690f819d1d9SMilanka Ringwald         return 0;
691f819d1d9SMilanka Ringwald     }
692f819d1d9SMilanka Ringwald     // calc overlap
693f819d1d9SMilanka Ringwald     uint16_t bytes_to_copy = field_len;
694f819d1d9SMilanka Ringwald 
695f819d1d9SMilanka Ringwald     uint16_t skip_at_start = 0;
696f819d1d9SMilanka Ringwald     if (field_offset < buffer_offset){
697f819d1d9SMilanka Ringwald         skip_at_start = buffer_offset - field_offset;
698f819d1d9SMilanka Ringwald         bytes_to_copy -= skip_at_start;
699f819d1d9SMilanka Ringwald     }
700f819d1d9SMilanka Ringwald 
701f819d1d9SMilanka Ringwald     uint16_t skip_at_end = 0;
702f819d1d9SMilanka Ringwald     if ((field_offset + field_len) > after_buffer){
703f819d1d9SMilanka Ringwald         skip_at_end = (field_offset + field_len) - after_buffer;
704f819d1d9SMilanka Ringwald         bytes_to_copy -= skip_at_end;
705f819d1d9SMilanka Ringwald     }
706f819d1d9SMilanka Ringwald 
707f819d1d9SMilanka Ringwald     btstack_assert((skip_at_end + skip_at_start) <= field_len);
708f819d1d9SMilanka Ringwald     btstack_assert(bytes_to_copy <= field_len);
709f819d1d9SMilanka Ringwald 
710f819d1d9SMilanka Ringwald     memcpy(&buffer[(field_offset + skip_at_start) - buffer_offset], &field_data[skip_at_start], bytes_to_copy);
711f819d1d9SMilanka Ringwald     return bytes_to_copy;
712f819d1d9SMilanka Ringwald }
713