xref: /btstack/src/btstack_util.c (revision c95caec03e329c8b3429e249cc7edf04313327b4)
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 
44b795dcd0SMarcel Wappler #ifdef _MSC_VER
45b795dcd0SMarcel Wappler #include <Windows.h>
46b795dcd0SMarcel Wappler #include <intrin.h>
47b795dcd0SMarcel Wappler #endif
48b795dcd0SMarcel 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  */
bd_addr_cmp(const bd_addr_t a,const bd_addr_t b)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  */
bd_addr_copy(bd_addr_t dest,const bd_addr_t src)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 
little_endian_read_08(const uint8_t * buffer,int position)779fce1f71SMatthias Ringwald uint8_t little_endian_read_08(const uint8_t* buffer, int position) {
789fce1f71SMatthias Ringwald     return (uint8_t)buffer[position];
799fce1f71SMatthias Ringwald }
little_endian_read_16(const uint8_t * buffer,int position)8041f9be70SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int position){
8141f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8));
8273988a59SMatthias Ringwald }
little_endian_read_24(const uint8_t * buffer,int position)8341f9be70SMatthias Ringwald uint32_t little_endian_read_24(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);
8573988a59SMatthias Ringwald }
little_endian_read_32(const uint8_t * buffer,int position)8641f9be70SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int position){
8741f9be70SMatthias Ringwald     return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24);
8873988a59SMatthias Ringwald }
8973988a59SMatthias Ringwald 
little_endian_store_08(uint8_t * buffer,uint16_t position,uint8_t value)909fce1f71SMatthias Ringwald void little_endian_store_08(uint8_t* buffer, uint16_t position, uint8_t value) {
919fce1f71SMatthias Ringwald     uint16_t pos = position;
929fce1f71SMatthias Ringwald     buffer[pos] = value;
939fce1f71SMatthias Ringwald }
949fce1f71SMatthias Ringwald 
little_endian_store_16(uint8_t * buffer,uint16_t position,uint16_t value)9541f9be70SMatthias Ringwald void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
9641f9be70SMatthias Ringwald     uint16_t pos = position;
97b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)value;
98b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
99eb886013SMatthias Ringwald }
100eb886013SMatthias Ringwald 
little_endian_store_24(uint8_t * buffer,uint16_t position,uint32_t value)10141f9be70SMatthias Ringwald void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
10241f9be70SMatthias Ringwald     uint16_t pos = position;
103adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
104adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
105adbdd27aSMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
106adbdd27aSMilanka Ringwald }
107adbdd27aSMilanka Ringwald 
little_endian_store_32(uint8_t * buffer,uint16_t position,uint32_t value)10841f9be70SMatthias Ringwald void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
10941f9be70SMatthias Ringwald     uint16_t pos = position;
110b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
111b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
112b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
113b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
114eb886013SMatthias Ringwald }
115eb886013SMatthias Ringwald 
big_endian_read_08(const uint8_t * buffer,int position)1169fce1f71SMatthias Ringwald uint32_t big_endian_read_08(const uint8_t* buffer, int position) {
1179fce1f71SMatthias Ringwald     return buffer[position];
1189fce1f71SMatthias Ringwald }
1199fce1f71SMatthias Ringwald 
big_endian_read_16(const uint8_t * buffer,int position)12041f9be70SMatthias Ringwald uint32_t big_endian_read_16(const uint8_t * buffer, int position) {
12141f9be70SMatthias Ringwald     return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8));
12273988a59SMatthias Ringwald }
12373988a59SMatthias Ringwald 
big_endian_read_24(const uint8_t * buffer,int position)12441f9be70SMatthias Ringwald uint32_t big_endian_read_24(const uint8_t * buffer, int position) {
12541f9be70SMatthias Ringwald     return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16));
126e57a2545SMilanka Ringwald }
127e57a2545SMilanka Ringwald 
big_endian_read_32(const uint8_t * buffer,int position)12841f9be70SMatthias Ringwald uint32_t big_endian_read_32(const uint8_t * buffer, int position) {
12941f9be70SMatthias Ringwald     return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24);
13073988a59SMatthias Ringwald }
13173988a59SMatthias Ringwald 
big_endian_store_08(uint8_t * buffer,uint16_t position,uint8_t value)1329fce1f71SMatthias Ringwald void big_endian_store_08(uint8_t* buffer, uint16_t position, uint8_t value) {
1339fce1f71SMatthias Ringwald     uint16_t pos = position;
1349fce1f71SMatthias Ringwald     buffer[pos++] = (uint8_t)(value);
1359fce1f71SMatthias Ringwald }
1369fce1f71SMatthias Ringwald 
big_endian_store_16(uint8_t * buffer,uint16_t position,uint16_t value)13741f9be70SMatthias Ringwald void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){
13841f9be70SMatthias Ringwald     uint16_t pos = position;
139b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
140b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
141eb886013SMatthias Ringwald }
142eb886013SMatthias Ringwald 
big_endian_store_24(uint8_t * buffer,uint16_t position,uint32_t value)14341f9be70SMatthias Ringwald void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){
14441f9be70SMatthias Ringwald     uint16_t pos = position;
145b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
146b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
147b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
1487f535380SMilanka Ringwald }
1497f535380SMilanka Ringwald 
big_endian_store_32(uint8_t * buffer,uint16_t position,uint32_t value)15041f9be70SMatthias Ringwald void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){
15141f9be70SMatthias Ringwald     uint16_t pos = position;
152b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 24);
153b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 16);
154b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value >> 8);
155b0920f25SMilanka Ringwald     buffer[pos++] = (uint8_t)(value);
156eb886013SMatthias Ringwald }
157eb886013SMatthias Ringwald 
158eb886013SMatthias Ringwald // general swap/endianess utils
reverse_bytes(const uint8_t * src,uint8_t * dest,int len)159b45b7749SMilanka Ringwald void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){
160eb886013SMatthias Ringwald     int i;
161eb886013SMatthias Ringwald     for (i = 0; i < len; i++)
162b45b7749SMilanka Ringwald         dest[len - 1 - i] = src[i];
163eb886013SMatthias Ringwald }
reverse_24(const uint8_t * src,uint8_t * dest)164b45b7749SMilanka Ringwald void reverse_24(const uint8_t * src, uint8_t * dest){
165b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 3);
166eb886013SMatthias Ringwald }
reverse_48(const uint8_t * src,uint8_t * dest)167b45b7749SMilanka Ringwald void reverse_48(const uint8_t * src, uint8_t * dest){
168b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 6);
169bf1b35bfSMatthias Ringwald }
reverse_56(const uint8_t * src,uint8_t * dest)170b45b7749SMilanka Ringwald void reverse_56(const uint8_t * src, uint8_t * dest){
171b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 7);
172eb886013SMatthias Ringwald }
reverse_64(const uint8_t * src,uint8_t * dest)173b45b7749SMilanka Ringwald void reverse_64(const uint8_t * src, uint8_t * dest){
174b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 8);
175eb886013SMatthias Ringwald }
reverse_128(const uint8_t * src,uint8_t * dest)176b45b7749SMilanka Ringwald void reverse_128(const uint8_t * src, uint8_t * dest){
177b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 16);
178eb886013SMatthias Ringwald }
reverse_256(const uint8_t * src,uint8_t * dest)179b45b7749SMilanka Ringwald void reverse_256(const uint8_t * src, uint8_t * dest){
180b45b7749SMilanka Ringwald     reverse_bytes(src, dest, 32);
181cc7a2d78SMatthias Ringwald }
182eb886013SMatthias Ringwald 
reverse_bd_addr(const bd_addr_t src,bd_addr_t dest)183724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
184724d70a2SMatthias Ringwald     reverse_bytes(src, dest, 6);
185724d70a2SMatthias Ringwald }
186724d70a2SMatthias Ringwald 
btstack_is_null(const uint8_t * buffer,uint16_t size)18777955af6SMatthias Ringwald bool btstack_is_null(const uint8_t * buffer, uint16_t size){
18877955af6SMatthias Ringwald     uint16_t i;
18977955af6SMatthias Ringwald     for (i=0; i < size ; i++){
19077955af6SMatthias Ringwald         if (buffer[i] != 0) {
19177955af6SMatthias Ringwald             return false;
19277955af6SMatthias Ringwald         }
19377955af6SMatthias Ringwald     }
19477955af6SMatthias Ringwald     return true;
19577955af6SMatthias Ringwald }
19677955af6SMatthias Ringwald 
btstack_is_null_bd_addr(const bd_addr_t addr)1976d708481SDirk Helbig bool btstack_is_null_bd_addr( const bd_addr_t addr ){
1986d708481SDirk Helbig     return btstack_is_null( addr, sizeof(bd_addr_t) );
1996d708481SDirk Helbig }
2006d708481SDirk Helbig 
btstack_min(uint32_t a,uint32_t b)201ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){
202c1ab6cc1SMatthias Ringwald     return (a < b) ? a : b;
203ebaeb1beSMatthias Ringwald }
204ebaeb1beSMatthias Ringwald 
btstack_max(uint32_t a,uint32_t b)205ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){
206c1ab6cc1SMatthias Ringwald     return (a > b) ? a : b;
207ebaeb1beSMatthias Ringwald }
208ebaeb1beSMatthias Ringwald 
20968af3967SMatthias Ringwald /**
210a9d566f7SMatthias Ringwald  * @brief Calculate delta between two uint32_t points in time
2116b65794dSMilanka Ringwald  * @return time_a - time_b - result > 0 if time_a is newer than time_b
21268af3967SMatthias Ringwald  */
btstack_time_delta(uint32_t time_a,uint32_t time_b)21368af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){
21468af3967SMatthias Ringwald     return (int32_t)(time_a - time_b);
21568af3967SMatthias Ringwald }
21668af3967SMatthias Ringwald 
217a9d566f7SMatthias Ringwald /**
218a9d566f7SMatthias Ringwald  * @brief Calculate delta between two uint16_t points in time
219a9d566f7SMatthias Ringwald  * @return time_a - time_b - result > 0 if time_a is newer than time_b
220a9d566f7SMatthias Ringwald  */
btstack_time16_delta(uint16_t time_a,uint16_t time_b)221a9d566f7SMatthias Ringwald int16_t btstack_time16_delta(uint16_t time_a, uint16_t time_b){
222a9d566f7SMatthias Ringwald     return (int16_t)(time_a - time_b);
223a9d566f7SMatthias Ringwald }
224c1c58647SMatthias Ringwald 
char_for_nibble(uint8_t nibble)225d7d45b32SMatthias Ringwald char char_for_nibble(uint8_t nibble){
2268334d3d8SMatthias Ringwald 
2278334d3d8SMatthias Ringwald     static const char * char_to_nibble = "0123456789ABCDEF";
2288334d3d8SMatthias Ringwald 
229c1c58647SMatthias Ringwald     if (nibble < 16){
230c1c58647SMatthias Ringwald         return char_to_nibble[nibble];
231c1c58647SMatthias Ringwald     } else {
232eb886013SMatthias Ringwald         return '?';
233eb886013SMatthias Ringwald     }
234c1c58647SMatthias Ringwald }
235eb886013SMatthias Ringwald 
char_for_high_nibble(int value)236405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){
237405d63a9SMatthias Ringwald     return char_for_nibble((value >> 4) & 0x0f);
238405d63a9SMatthias Ringwald }
239405d63a9SMatthias Ringwald 
char_for_low_nibble(int value)240405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){
241405d63a9SMatthias Ringwald     return char_for_nibble(value & 0x0f);
242405d63a9SMatthias Ringwald }
243405d63a9SMatthias Ringwald 
244c1c58647SMatthias Ringwald 
nibble_for_char(char c)245a6efb919SMatthias Ringwald int nibble_for_char(char c){
246c1ab6cc1SMatthias Ringwald     if ((c >= '0') && (c <= '9')) return c - '0';
247c1ab6cc1SMatthias Ringwald     if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
248c1ab6cc1SMatthias Ringwald     if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
249a6efb919SMatthias Ringwald     return -1;
250a6efb919SMatthias Ringwald }
251a6efb919SMatthias Ringwald 
25246059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP
printf_hexdump(const void * data,int size)253eb886013SMatthias Ringwald void printf_hexdump(const void * data, int size){
254c1c58647SMatthias Ringwald     char buffer[4];
255c1c58647SMatthias Ringwald     buffer[2] = ' ';
256c1c58647SMatthias Ringwald     buffer[3] =  0;
2579dbfa930SMatthias Ringwald     const uint8_t * ptr = (const uint8_t *) data;
258c1c58647SMatthias Ringwald     while (size > 0){
2599dbfa930SMatthias Ringwald         uint8_t byte = *ptr++;
260c1c58647SMatthias Ringwald         buffer[0] = char_for_high_nibble(byte);
261c1c58647SMatthias Ringwald         buffer[1] = char_for_low_nibble(byte);
262c1c58647SMatthias Ringwald         printf("%s", buffer);
263c1c58647SMatthias Ringwald         size--;
264eb886013SMatthias Ringwald     }
265eb886013SMatthias Ringwald     printf("\n");
266eb886013SMatthias Ringwald }
26746059ae4SMilanka Ringwald #endif
268eb886013SMatthias Ringwald 
269cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG)
log_hexdump(int level,const void * data,int size)270cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){
271405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16
272405d63a9SMatthias Ringwald // template '0x12, '
273405d63a9SMatthias Ringwald #define BYTES_PER_BYTE  6
274405d63a9SMatthias Ringwald     char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
2757224be7eSMatthias Ringwald     int i, j;
276eb886013SMatthias Ringwald     j = 0;
277eb886013SMatthias Ringwald     for (i=0; i<size;i++){
2787224be7eSMatthias Ringwald 
2797224be7eSMatthias Ringwald         // help static analyzer proof that j stays within bounds
280c1ab6cc1SMatthias Ringwald         if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){
2817224be7eSMatthias Ringwald             j = 0;
2827224be7eSMatthias Ringwald         }
2837224be7eSMatthias Ringwald 
284eb886013SMatthias Ringwald         uint8_t byte = ((uint8_t *)data)[i];
285eb886013SMatthias Ringwald         buffer[j++] = '0';
286eb886013SMatthias Ringwald         buffer[j++] = 'x';
287405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
288405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
289eb886013SMatthias Ringwald         buffer[j++] = ',';
290eb886013SMatthias Ringwald         buffer[j++] = ' ';
2917224be7eSMatthias Ringwald 
292c1ab6cc1SMatthias Ringwald         if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){
293eb886013SMatthias Ringwald             buffer[j] = 0;
29443bdd576SMatthias Ringwald             hci_dump_log(level, "%s", buffer);
295eb886013SMatthias Ringwald             j = 0;
296eb886013SMatthias Ringwald         }
297eb886013SMatthias Ringwald     }
298eb886013SMatthias Ringwald     if (j != 0){
299eb886013SMatthias Ringwald         buffer[j] = 0;
30043bdd576SMatthias Ringwald         hci_dump_log(level, "%s", buffer);
301eb886013SMatthias Ringwald     }
302cb42147aSMatthias Ringwald }
303cb42147aSMatthias Ringwald #endif
304cb42147aSMatthias Ringwald 
log_debug_hexdump(const void * data,int size)305cb42147aSMatthias Ringwald void log_debug_hexdump(const void * data, int size){
306e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG
307fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size);
308cb42147aSMatthias Ringwald #else
3094bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
3104bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
311cb42147aSMatthias Ringwald #endif
312cb42147aSMatthias Ringwald }
313cb42147aSMatthias Ringwald 
log_info_hexdump(const void * data,int size)314cb42147aSMatthias Ringwald void log_info_hexdump(const void * data, int size){
315cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO
316fa087deaSMatthias Ringwald     log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size);
317d0662982SMatthias Ringwald #else
3184bd79111SMatthias Ringwald     UNUSED(data);   // ok: no code
3194bd79111SMatthias Ringwald     UNUSED(size);   // ok: no code
3208314c363SMatthias Ringwald #endif
3217299c0feSMatthias Ringwald }
322eb886013SMatthias Ringwald 
log_info_key(const char * name,sm_key_t key)3238314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){
32402bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO
32502bdfbf8SMatthias Ringwald     char buffer[16*2+1];
32602bdfbf8SMatthias Ringwald     int i;
32702bdfbf8SMatthias Ringwald     int j = 0;
32802bdfbf8SMatthias Ringwald     for (i=0; i<16;i++){
32902bdfbf8SMatthias Ringwald         uint8_t byte = key[i];
330405d63a9SMatthias Ringwald         buffer[j++] = char_for_high_nibble(byte);
331405d63a9SMatthias Ringwald         buffer[j++] = char_for_low_nibble(byte);
33202bdfbf8SMatthias Ringwald     }
33302bdfbf8SMatthias Ringwald     buffer[j] = 0;
33402bdfbf8SMatthias Ringwald     log_info("%-6s %s", name, buffer);
335d0662982SMatthias Ringwald #else
336d0662982SMatthias Ringwald     UNUSED(name);
337cb42147aSMatthias Ringwald     (void)key;
33802bdfbf8SMatthias Ringwald #endif
339eb886013SMatthias Ringwald }
340eb886013SMatthias Ringwald 
3412b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t
3422b604902SMatthias Ringwald 
343eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
3442b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
345eb886013SMatthias Ringwald     0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
346eb886013SMatthias Ringwald 
uuid_add_bluetooth_prefix(uint8_t * uuid128,uint32_t short_uuid)34748cdff9cSMilanka Ringwald void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid){
348b45b7749SMilanka Ringwald     (void)memcpy(uuid128, bluetooth_base_uuid, 16);
34948cdff9cSMilanka Ringwald     big_endian_store_32(uuid128, 0, short_uuid);
350eb886013SMatthias Ringwald }
351eb886013SMatthias Ringwald 
uuid_has_bluetooth_prefix(const uint8_t * uuid128)3528933879eSMatthias Ringwald bool uuid_has_bluetooth_prefix(const uint8_t * uuid128){
3532b604902SMatthias Ringwald     return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0;
354eb886013SMatthias Ringwald }
355eb886013SMatthias Ringwald 
356eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1];
uuid128_to_str(const uint8_t * uuid)3575222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){
3587224be7eSMatthias Ringwald     int i;
3597224be7eSMatthias Ringwald     int j = 0;
3607224be7eSMatthias Ringwald     // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
3617224be7eSMatthias Ringwald     const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
3627224be7eSMatthias Ringwald     for (i=0;i<16;i++){
363405d63a9SMatthias Ringwald         uint8_t byte = uuid[i];
364405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
365405d63a9SMatthias Ringwald         uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
3667224be7eSMatthias Ringwald         if (dash_locations & (1<<i)){
3677224be7eSMatthias Ringwald             uuid128_to_str_buffer[j++] = '-';
3687224be7eSMatthias Ringwald         }
3697224be7eSMatthias Ringwald     }
370eb886013SMatthias Ringwald     return uuid128_to_str_buffer;
371eb886013SMatthias Ringwald }
372eb886013SMatthias Ringwald 
373eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3];  // 12:45:78:01:34:67\0
bd_addr_to_str_with_delimiter(const bd_addr_t addr,char delimiter)37461c3ec28SMatthias Ringwald char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter){
375eb886013SMatthias Ringwald     char * p = bd_addr_to_str_buffer;
376eb886013SMatthias Ringwald     int i;
377eb886013SMatthias Ringwald     for (i = 0; i < 6 ; i++) {
378405d63a9SMatthias Ringwald         uint8_t byte = addr[i];
379405d63a9SMatthias Ringwald         *p++ = char_for_high_nibble(byte);
380405d63a9SMatthias Ringwald         *p++ = char_for_low_nibble(byte);
38161c3ec28SMatthias Ringwald         *p++ = delimiter;
382eb886013SMatthias Ringwald     }
383eb886013SMatthias Ringwald     *--p = 0;
384eb886013SMatthias Ringwald     return (char *) bd_addr_to_str_buffer;
385eb886013SMatthias Ringwald }
386eb886013SMatthias Ringwald 
bd_addr_to_str(const bd_addr_t addr)38761c3ec28SMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){
38861c3ec28SMatthias Ringwald     return bd_addr_to_str_with_delimiter(addr, ':');
38961c3ec28SMatthias Ringwald }
39061c3ec28SMatthias Ringwald 
btstack_replace_bd_addr_placeholder(uint8_t * buffer,uint16_t size,const bd_addr_t address)3913c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){
3923c9da642SMatthias Ringwald     const int bd_addr_string_len = 17;
39330314625SMatthias Ringwald     uint16_t i = 0;
39430314625SMatthias Ringwald     while ((i + bd_addr_string_len) <= size){
3953c9da642SMatthias Ringwald         if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) {
3963c9da642SMatthias Ringwald             i++;
3973c9da642SMatthias Ringwald             continue;
3983c9da642SMatthias Ringwald         }
3993c9da642SMatthias Ringwald         // set address
4003c9da642SMatthias Ringwald         (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len);
4013c9da642SMatthias Ringwald         i += bd_addr_string_len;
4023c9da642SMatthias Ringwald     }
4033c9da642SMatthias Ringwald }
4043c9da642SMatthias Ringwald 
scan_hex_byte(const char * byte_string)405a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
40641f9be70SMatthias Ringwald     int upper_nibble = nibble_for_char(byte_string[0]);
407a6efb919SMatthias Ringwald     if (upper_nibble < 0) return -1;
40841f9be70SMatthias Ringwald     int lower_nibble = nibble_for_char(byte_string[1]);
409a6efb919SMatthias Ringwald     if (lower_nibble < 0) return -1;
410a6efb919SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
411a6efb919SMatthias Ringwald }
412eb886013SMatthias Ringwald 
sscanf_bd_addr(const char * addr_string,bd_addr_t addr)413a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
41441f9be70SMatthias Ringwald     const char * the_string = addr_string;
415a6efb919SMatthias Ringwald     uint8_t buffer[BD_ADDR_LEN];
416a6efb919SMatthias Ringwald     int result = 0;
417eb886013SMatthias Ringwald     int i;
418eb886013SMatthias Ringwald     for (i = 0; i < BD_ADDR_LEN; i++) {
41941f9be70SMatthias Ringwald         int single_byte = scan_hex_byte(the_string);
420a6efb919SMatthias Ringwald         if (single_byte < 0) break;
42141f9be70SMatthias Ringwald         the_string += 2;
422b0920f25SMilanka Ringwald         buffer[i] = (uint8_t)single_byte;
42341f9be70SMatthias Ringwald         // don't check separator after last byte
424c1ab6cc1SMatthias Ringwald         if (i == (BD_ADDR_LEN - 1)) {
425a6efb919SMatthias Ringwald             result = 1;
426a6efb919SMatthias Ringwald             break;
427eb886013SMatthias Ringwald         }
428cd2e416cSMatthias Ringwald         // skip supported separators
42941f9be70SMatthias Ringwald         char next_char = *the_string;
4305df9dc78SMatthias Ringwald         if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) {
43141f9be70SMatthias Ringwald             the_string++;
432cd2e416cSMatthias Ringwald         }
433a6efb919SMatthias Ringwald     }
434a6efb919SMatthias Ringwald 
4359305033eSMatthias Ringwald     if (result != 0){
436a6efb919SMatthias Ringwald         bd_addr_copy(addr, buffer);
437a6efb919SMatthias Ringwald     }
438a6efb919SMatthias Ringwald 	return result;
439eb886013SMatthias Ringwald }
4405d067ab1SMatthias Ringwald 
btstack_atoi(const char * str)4415d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char * str){
44241f9be70SMatthias Ringwald     const char * the_string = str;
4435d067ab1SMatthias Ringwald     uint32_t val = 0;
444ff3cc4a5SMatthias Ringwald     while (true){
44541f9be70SMatthias Ringwald         char chr = *the_string++;
446*c95caec0SMatthias Ringwald         // skip whitespace
447*c95caec0SMatthias Ringwald         if (((chr >= 0x09) && (chr <= 0x0d)) || (chr == ' ')) {
448*c95caec0SMatthias Ringwald             continue;
449*c95caec0SMatthias Ringwald         }
450*c95caec0SMatthias Ringwald         if (!chr || (chr < '0') || (chr > '9')){
4515d067ab1SMatthias Ringwald             return val;
452*c95caec0SMatthias Ringwald         }
4534ea43905SMatthias Ringwald         val = (val * 10u) + (uint8_t)(chr - '0');
4545d067ab1SMatthias Ringwald     }
4555d067ab1SMatthias Ringwald }
4561f41c2c9SMatthias Ringwald 
string_len_for_uint32(uint32_t i)457d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){
458d1207cd8SMilanka Ringwald     if (i <         10) return 1;
459d1207cd8SMilanka Ringwald     if (i <        100) return 2;
460d1207cd8SMilanka Ringwald     if (i <       1000) return 3;
461d1207cd8SMilanka Ringwald     if (i <      10000) return 4;
462d1207cd8SMilanka Ringwald     if (i <     100000) return 5;
463d1207cd8SMilanka Ringwald     if (i <    1000000) return 6;
464d1207cd8SMilanka Ringwald     if (i <   10000000) return 7;
465d1207cd8SMilanka Ringwald     if (i <  100000000) return 8;
466d1207cd8SMilanka Ringwald     if (i < 1000000000) return 9;
467d1207cd8SMilanka Ringwald     return 10;
468d1207cd8SMilanka Ringwald }
469d1207cd8SMilanka Ringwald 
count_set_bits_uint32(uint32_t x)470d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){
47141f9be70SMatthias Ringwald     uint32_t v = x;
47241f9be70SMatthias Ringwald     v = (v & 0x55555555) + ((v >> 1)  & 0x55555555U);
47341f9be70SMatthias Ringwald     v = (v & 0x33333333) + ((v >> 2)  & 0x33333333U);
47441f9be70SMatthias Ringwald     v = (v & 0x0F0F0F0F) + ((v >> 4)  & 0x0F0F0F0FU);
47541f9be70SMatthias Ringwald     v = (v & 0x00FF00FF) + ((v >> 8)  & 0x00FF00FFU);
47641f9be70SMatthias Ringwald     v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU);
47741f9be70SMatthias Ringwald     return v;
478d1207cd8SMilanka Ringwald }
4791f41c2c9SMatthias Ringwald 
btstack_clz(uint32_t value)480ec08441fSMatthias Ringwald uint8_t btstack_clz(uint32_t value) {
4811a8c5172SDirk Helbig     btstack_assert( value != 0 );
482ec08441fSMatthias Ringwald #if defined(__GNUC__) || defined (__clang__)
483ec08441fSMatthias Ringwald     // use gcc/clang intrinsic
484ec08441fSMatthias Ringwald     return (uint8_t) __builtin_clz(value);
485ec08441fSMatthias Ringwald #elif defined(_MSC_VER)
486ec08441fSMatthias Ringwald     // use MSVC intrinsic
487ec08441fSMatthias Ringwald     DWORD leading_zero = 0;
4886f5aa202SMatthias Ringwald     _BitScanReverse( &leading_zero, value );
489ec08441fSMatthias Ringwald 	return (uint8_t)(31 - leading_zero);
490ec08441fSMatthias Ringwald #else
491ec08441fSMatthias Ringwald     // divide-and-conquer implementation for 32-bit integers
492af0ac871SAlec Cantor     uint32_t x = value;
493ec08441fSMatthias Ringwald     uint8_t r = 0;
494ec08441fSMatthias Ringwald     if ((x & 0xffff0000u) == 0) {
495ec08441fSMatthias Ringwald         x <<= 16;
496ec08441fSMatthias Ringwald         r += 16;
497ec08441fSMatthias Ringwald     }
498ec08441fSMatthias Ringwald     if ((x & 0xff000000u) == 0) {
499ec08441fSMatthias Ringwald         x <<= 8;
500ec08441fSMatthias Ringwald         r += 8;
501ec08441fSMatthias Ringwald     }
502ec08441fSMatthias Ringwald     if ((x & 0xf0000000u) == 0) {
503ec08441fSMatthias Ringwald         x <<= 4;
504ec08441fSMatthias Ringwald         r += 4;
505ec08441fSMatthias Ringwald     }
506ec08441fSMatthias Ringwald     if ((x & 0xc0000000u) == 0) {
507ec08441fSMatthias Ringwald         x <<= 2;
508ec08441fSMatthias Ringwald         r += 2;
509ec08441fSMatthias Ringwald     }
510ec08441fSMatthias Ringwald     if ((x & 0x80000000u) == 0) {
511ec08441fSMatthias Ringwald         x <<= 1;
512ec08441fSMatthias Ringwald         r += 1;
513ec08441fSMatthias Ringwald     }
514ec08441fSMatthias Ringwald     return r;
515ec08441fSMatthias Ringwald #endif
516ec08441fSMatthias Ringwald }
517ec08441fSMatthias Ringwald 
5181f41c2c9SMatthias Ringwald /*
51942fea667SMilanka Ringwald  * CRC-8 (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
5201f41c2c9SMatthias Ringwald  */
5211f41c2c9SMatthias Ringwald 
5221f41c2c9SMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
5231f41c2c9SMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
5241f41c2c9SMatthias Ringwald 
5251f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
5261f41c2c9SMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
5271f41c2c9SMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
5281f41c2c9SMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
5291f41c2c9SMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
5301f41c2c9SMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
5311f41c2c9SMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
5321f41c2c9SMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
5331f41c2c9SMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
5341f41c2c9SMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
5351f41c2c9SMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
5361f41c2c9SMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
5371f41c2c9SMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
5381f41c2c9SMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
5391f41c2c9SMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
5401f41c2c9SMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
5411f41c2c9SMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
5421f41c2c9SMatthias Ringwald };
5431f41c2c9SMatthias Ringwald 
5441f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
crc8(uint8_t * data,uint16_t len)5451f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){
5461f41c2c9SMatthias Ringwald     uint16_t count;
5471f41c2c9SMatthias Ringwald     uint8_t crc = CRC8_INIT;
5481f41c2c9SMatthias Ringwald     for (count = 0; count < len; count++){
5491f41c2c9SMatthias Ringwald         crc = crc8table[crc ^ data[count]];
5501f41c2c9SMatthias Ringwald     }
5511f41c2c9SMatthias Ringwald     return crc;
5521f41c2c9SMatthias Ringwald }
5531f41c2c9SMatthias Ringwald 
5541f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
btstack_crc8_check(uint8_t * data,uint16_t len,uint8_t check_sum)55563dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){
5561f41c2c9SMatthias Ringwald     uint8_t crc;
5571f41c2c9SMatthias Ringwald     crc = crc8(data, len);
5581f41c2c9SMatthias Ringwald     crc = crc8table[crc ^ check_sum];
5591f41c2c9SMatthias Ringwald     if (crc == CRC8_OK){
5601f41c2c9SMatthias Ringwald         return 0;               /* Valid */
5611f41c2c9SMatthias Ringwald     } else {
5621f41c2c9SMatthias Ringwald         return 1;               /* Failed */
5631f41c2c9SMatthias Ringwald     }
5641f41c2c9SMatthias Ringwald }
5651f41c2c9SMatthias Ringwald 
5661f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/
btstack_crc8_calc(uint8_t * data,uint16_t len)56763dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){
5681f41c2c9SMatthias Ringwald     /* Ones complement */
5694ea43905SMatthias Ringwald     return 0xFFu - crc8(data, len);
5701f41c2c9SMatthias Ringwald }
571a73d0b9dSMilanka Ringwald 
57242fea667SMilanka Ringwald /*
57342fea667SMilanka Ringwald  * CRC-32 lookup table as calculated by the table generator. Polynomial (normal) 0x04c11db7, ISO 3309 (HDLC)
57442fea667SMilanka Ringwald  *
57542fea667SMilanka Ringwald  * Created using pycrc tool (https://pycrc.org) with "crc-32" as model, and "table-driven" algorithm
57642fea667SMilanka Ringwald  *  python3 pycrc.py --model crc-32 --algorithm table-driven --generate h -o crc32.h
57742fea667SMilanka Ringwald  *  python3 pycrc.py --model crc-32 --algorithm table-driven --generate c -o crc32.c
57842fea667SMilanka Ringwald  */
57942fea667SMilanka Ringwald 
58042fea667SMilanka Ringwald /**
58142fea667SMilanka Ringwald  * Static table used for the table_driven implementation.
58242fea667SMilanka Ringwald  */
58342fea667SMilanka Ringwald static const uint32_t crc_table[256] = {
58442fea667SMilanka Ringwald     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
58542fea667SMilanka Ringwald     0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
58642fea667SMilanka Ringwald     0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
58742fea667SMilanka Ringwald     0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
58842fea667SMilanka Ringwald     0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
58942fea667SMilanka Ringwald     0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
59042fea667SMilanka Ringwald     0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
59142fea667SMilanka Ringwald     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
59242fea667SMilanka Ringwald     0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
59342fea667SMilanka Ringwald     0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
59442fea667SMilanka Ringwald     0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
59542fea667SMilanka Ringwald     0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
59642fea667SMilanka Ringwald     0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
59742fea667SMilanka Ringwald     0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
59842fea667SMilanka Ringwald     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
59942fea667SMilanka Ringwald     0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
60042fea667SMilanka Ringwald     0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
60142fea667SMilanka Ringwald     0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
60242fea667SMilanka Ringwald     0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
60342fea667SMilanka Ringwald     0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
60442fea667SMilanka Ringwald     0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
60542fea667SMilanka Ringwald     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
60642fea667SMilanka Ringwald     0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
60742fea667SMilanka Ringwald     0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
60842fea667SMilanka Ringwald     0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
60942fea667SMilanka Ringwald     0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
61042fea667SMilanka Ringwald     0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
61142fea667SMilanka Ringwald     0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
61242fea667SMilanka Ringwald     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
61342fea667SMilanka Ringwald     0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
61442fea667SMilanka Ringwald     0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
61542fea667SMilanka Ringwald     0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
61642fea667SMilanka Ringwald };
61742fea667SMilanka Ringwald 
btstack_crc32_init(void)61842fea667SMilanka Ringwald uint32_t btstack_crc32_init(void){
61942fea667SMilanka Ringwald     return 0xffffffff;
62042fea667SMilanka Ringwald }
62142fea667SMilanka Ringwald 
btstack_crc32_update(uint32_t crc,const uint8_t * data,uint32_t data_len)62242fea667SMilanka Ringwald uint32_t btstack_crc32_update(uint32_t crc, const uint8_t * data, uint32_t data_len){
62376468bbdSMilanka Ringwald     const uint8_t *d = data;
62442fea667SMilanka Ringwald     uint32_t tbl_idx;
62542fea667SMilanka Ringwald 
62642fea667SMilanka Ringwald     while (data_len--) {
62742fea667SMilanka Ringwald         tbl_idx = (crc ^ *d) & 0xff;
62842fea667SMilanka Ringwald         crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
62942fea667SMilanka Ringwald         d++;
63042fea667SMilanka Ringwald     }
63142fea667SMilanka Ringwald     return crc & 0xffffffff;
63242fea667SMilanka Ringwald }
63342fea667SMilanka Ringwald 
btstack_crc32_finalize(uint32_t crc)63442fea667SMilanka Ringwald uint32_t btstack_crc32_finalize(uint32_t crc){
63542fea667SMilanka Ringwald     return crc ^ 0xffffffff;
63642fea667SMilanka Ringwald }
63742fea667SMilanka Ringwald 
63842fea667SMilanka Ringwald /*-----------------------------------------------------------------------------------*/
63942fea667SMilanka Ringwald 
btstack_next_cid_ignoring_zero(uint16_t current_cid)640a73d0b9dSMilanka Ringwald uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid){
641a73d0b9dSMilanka Ringwald     uint16_t next_cid;
642a73d0b9dSMilanka Ringwald     if (current_cid == 0xffff) {
643a73d0b9dSMilanka Ringwald         next_cid = 1;
644a73d0b9dSMilanka Ringwald     } else {
645a73d0b9dSMilanka Ringwald         next_cid = current_cid + 1;
646a73d0b9dSMilanka Ringwald     }
647a73d0b9dSMilanka Ringwald     return next_cid;
648a73d0b9dSMilanka Ringwald }
649de22414aSMatthias Ringwald 
btstack_strcpy(char * dst,uint16_t dst_size,const char * src)650ed7a067cSMilanka Ringwald uint16_t btstack_strcpy(char * dst, uint16_t dst_size, const char * src){
6511a3bc516SMatthias Ringwald     uint16_t bytes_to_copy = (uint16_t) btstack_min( dst_size - 1, (uint16_t) strlen(src));
652de22414aSMatthias Ringwald     (void) memcpy(dst, src, bytes_to_copy);
653981f700bSMatthias Ringwald     dst[bytes_to_copy] = 0;
654ed7a067cSMilanka Ringwald     return bytes_to_copy + 1;
655de22414aSMatthias Ringwald }
6563ece4788SMatthias Ringwald 
btstack_strcat(char * dst,uint16_t dst_size,const char * src)6573ece4788SMatthias Ringwald void btstack_strcat(char * dst, uint16_t dst_size, const char * src){
6583ece4788SMatthias Ringwald     uint16_t src_len = (uint16_t) strlen(src);
6593ece4788SMatthias Ringwald     uint16_t dst_len = (uint16_t) strlen(dst);
6603ece4788SMatthias Ringwald     uint16_t bytes_to_copy = btstack_min( src_len, dst_size - dst_len - 1);
6613ece4788SMatthias Ringwald     (void) memcpy( &dst[dst_len], src, bytes_to_copy);
6623ece4788SMatthias Ringwald     dst[dst_len + bytes_to_copy] = 0;
6633ece4788SMatthias Ringwald }
664f819d1d9SMilanka Ringwald 
btstack_printf_strlen(const char * format,...)665ad144fa1SMatthias Ringwald int btstack_printf_strlen(const char * format, ...){
666ad144fa1SMatthias Ringwald     va_list argptr;
667ad144fa1SMatthias Ringwald     va_start(argptr, format);
668ad144fa1SMatthias Ringwald     char dummy_buffer[1];
669ad144fa1SMatthias Ringwald     int len = vsnprintf(dummy_buffer, sizeof(dummy_buffer), format, argptr);
670ad144fa1SMatthias Ringwald     va_end(argptr);
671ad144fa1SMatthias Ringwald     return len;
672ad144fa1SMatthias Ringwald }
673ad144fa1SMatthias Ringwald 
btstack_snprintf_assert_complete(char * buffer,size_t size,const char * format,...)674ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_assert_complete(char * buffer, size_t size, const char * format, ...){
675ad144fa1SMatthias Ringwald     va_list argptr;
676ad144fa1SMatthias Ringwald     va_start(argptr, format);
677ad144fa1SMatthias Ringwald     int len = vsnprintf(buffer, size, format, argptr);
678ad144fa1SMatthias Ringwald     va_end(argptr);
679ad144fa1SMatthias Ringwald 
680ad144fa1SMatthias Ringwald     // check for no error and no truncation
681ad144fa1SMatthias Ringwald     btstack_assert(len >= 0);
682c46e8f55SMatthias Ringwald     btstack_assert((unsigned int) len < size);
683ad144fa1SMatthias Ringwald     return (uint16_t) len;
684ad144fa1SMatthias Ringwald }
685ad144fa1SMatthias Ringwald 
btstack_snprintf_best_effort(char * buffer,size_t size,const char * format,...)686ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_best_effort(char * buffer, size_t size, const char * format, ...){
687ad144fa1SMatthias Ringwald     btstack_assert(size > 0);
688ad144fa1SMatthias Ringwald     va_list argptr;
689ad144fa1SMatthias Ringwald     va_start(argptr, format);
690ad144fa1SMatthias Ringwald     int len = vsnprintf(buffer, size, format, argptr);
691ad144fa1SMatthias Ringwald     va_end(argptr);
692ad144fa1SMatthias Ringwald     if (len < 0) {
693ad144fa1SMatthias Ringwald         // error -> len = 0
694ad144fa1SMatthias Ringwald         return 0;
695ad144fa1SMatthias Ringwald     } else {
696ad144fa1SMatthias Ringwald         // min of total string len and buffer size
697ad144fa1SMatthias Ringwald         return (uint16_t) btstack_min((uint32_t) len, (uint32_t) size - 1);
698ad144fa1SMatthias Ringwald     }
699ad144fa1SMatthias Ringwald }
700ad144fa1SMatthias Ringwald 
btstack_virtual_memcpy(const uint8_t * field_data,uint16_t field_len,uint16_t field_offset,uint8_t * buffer,uint16_t buffer_size,uint16_t buffer_offset)701f819d1d9SMilanka Ringwald uint16_t btstack_virtual_memcpy(
702f819d1d9SMilanka Ringwald     const uint8_t * field_data, uint16_t field_len, uint16_t field_offset, // position of field in complete data block
703f819d1d9SMilanka Ringwald     uint8_t * buffer, uint16_t buffer_size, uint16_t buffer_offset){
704f819d1d9SMilanka Ringwald 
705f819d1d9SMilanka Ringwald     uint16_t after_buffer = buffer_offset + buffer_size ;
706f819d1d9SMilanka Ringwald     // bail before buffer
707f819d1d9SMilanka Ringwald     if ((field_offset + field_len) < buffer_offset){
708f819d1d9SMilanka Ringwald         return 0;
709f819d1d9SMilanka Ringwald     }
710f819d1d9SMilanka Ringwald     // bail after buffer
711f819d1d9SMilanka Ringwald     if (field_offset >= after_buffer){
712f819d1d9SMilanka Ringwald         return 0;
713f819d1d9SMilanka Ringwald     }
714f819d1d9SMilanka Ringwald     // calc overlap
715f819d1d9SMilanka Ringwald     uint16_t bytes_to_copy = field_len;
716f819d1d9SMilanka Ringwald 
717f819d1d9SMilanka Ringwald     uint16_t skip_at_start = 0;
718f819d1d9SMilanka Ringwald     if (field_offset < buffer_offset){
719f819d1d9SMilanka Ringwald         skip_at_start = buffer_offset - field_offset;
720f819d1d9SMilanka Ringwald         bytes_to_copy -= skip_at_start;
721f819d1d9SMilanka Ringwald     }
722f819d1d9SMilanka Ringwald 
723f819d1d9SMilanka Ringwald     uint16_t skip_at_end = 0;
724f819d1d9SMilanka Ringwald     if ((field_offset + field_len) > after_buffer){
725f819d1d9SMilanka Ringwald         skip_at_end = (field_offset + field_len) - after_buffer;
726f819d1d9SMilanka Ringwald         bytes_to_copy -= skip_at_end;
727f819d1d9SMilanka Ringwald     }
728f819d1d9SMilanka Ringwald 
729f819d1d9SMilanka Ringwald     btstack_assert((skip_at_end + skip_at_start) <= field_len);
730f819d1d9SMilanka Ringwald     btstack_assert(bytes_to_copy <= field_len);
731f819d1d9SMilanka Ringwald 
732f819d1d9SMilanka Ringwald     memcpy(&buffer[(field_offset + skip_at_start) - buffer_offset], &field_data[skip_at_start], bytes_to_copy);
733f819d1d9SMilanka Ringwald     return bytes_to_copy;
734f819d1d9SMilanka Ringwald }
735