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 447907f069SMatthias Ringwald #include "btstack_config.h" 4502bdfbf8SMatthias Ringwald #include "btstack_debug.h" 46eb886013SMatthias Ringwald #include "btstack_util.h" 4702bdfbf8SMatthias Ringwald 48*ec08441fSMatthias Ringwald #ifdef _MSC_VER 49*ec08441fSMatthias Ringwald #include <intrin.h> 50*ec08441fSMatthias Ringwald #include <windows.h> 51*ec08441fSMatthias Ringwald #endif 52*ec08441fSMatthias Ringwald 5346059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP 54eb886013SMatthias Ringwald #include <stdio.h> 5546059ae4SMilanka Ringwald #endif 5646059ae4SMilanka Ringwald 57eb886013SMatthias Ringwald #include <string.h> 58eb886013SMatthias Ringwald 5973988a59SMatthias Ringwald /** 6073988a59SMatthias Ringwald * @brief Compare two Bluetooth addresses 6173988a59SMatthias Ringwald * @param a 6273988a59SMatthias Ringwald * @param b 63969fc1c5SMilanka Ringwald * @return 0 if equal 6473988a59SMatthias Ringwald */ 655222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){ 6673988a59SMatthias Ringwald return memcmp(a,b, BD_ADDR_LEN); 6773988a59SMatthias Ringwald } 6873988a59SMatthias Ringwald 6973988a59SMatthias Ringwald /** 7073988a59SMatthias Ringwald * @brief Copy Bluetooth address 7173988a59SMatthias Ringwald * @param dest 7273988a59SMatthias Ringwald * @param src 7373988a59SMatthias Ringwald */ 745222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){ 756535961aSMatthias Ringwald (void)memcpy(dest, src, BD_ADDR_LEN); 7673988a59SMatthias Ringwald } 7773988a59SMatthias Ringwald 7841f9be70SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int position){ 7941f9be70SMatthias Ringwald return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8)); 8073988a59SMatthias Ringwald } 8141f9be70SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int position){ 8241f9be70SMatthias Ringwald return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16); 8373988a59SMatthias Ringwald } 8441f9be70SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int position){ 8541f9be70SMatthias Ringwald return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24); 8673988a59SMatthias Ringwald } 8773988a59SMatthias Ringwald 8841f9be70SMatthias Ringwald void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 8941f9be70SMatthias Ringwald uint16_t pos = position; 90b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)value; 91b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 92eb886013SMatthias Ringwald } 93eb886013SMatthias Ringwald 9441f9be70SMatthias Ringwald void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 9541f9be70SMatthias Ringwald uint16_t pos = position; 96adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value); 97adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 98adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 99adbdd27aSMilanka Ringwald } 100adbdd27aSMilanka Ringwald 10141f9be70SMatthias Ringwald void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 10241f9be70SMatthias Ringwald uint16_t pos = position; 103b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 104b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 105b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 106b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 107eb886013SMatthias Ringwald } 108eb886013SMatthias Ringwald 10941f9be70SMatthias Ringwald uint32_t big_endian_read_16(const uint8_t * buffer, int position) { 11041f9be70SMatthias Ringwald return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8)); 11173988a59SMatthias Ringwald } 11273988a59SMatthias Ringwald 11341f9be70SMatthias Ringwald uint32_t big_endian_read_24(const uint8_t * buffer, int position) { 11441f9be70SMatthias Ringwald return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16)); 115e57a2545SMilanka Ringwald } 116e57a2545SMilanka Ringwald 11741f9be70SMatthias Ringwald uint32_t big_endian_read_32(const uint8_t * buffer, int position) { 11841f9be70SMatthias Ringwald return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24); 11973988a59SMatthias Ringwald } 12073988a59SMatthias Ringwald 12141f9be70SMatthias Ringwald void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 12241f9be70SMatthias Ringwald uint16_t pos = position; 123b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 124b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 125eb886013SMatthias Ringwald } 126eb886013SMatthias Ringwald 12741f9be70SMatthias Ringwald void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 12841f9be70SMatthias Ringwald uint16_t pos = position; 129b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 130b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 131b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 1327f535380SMilanka Ringwald } 1337f535380SMilanka Ringwald 13441f9be70SMatthias Ringwald void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 13541f9be70SMatthias Ringwald uint16_t pos = position; 136b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 137b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 138b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 139b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 140eb886013SMatthias Ringwald } 141eb886013SMatthias Ringwald 142eb886013SMatthias Ringwald // general swap/endianess utils 143b45b7749SMilanka Ringwald void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){ 144eb886013SMatthias Ringwald int i; 145eb886013SMatthias Ringwald for (i = 0; i < len; i++) 146b45b7749SMilanka Ringwald dest[len - 1 - i] = src[i]; 147eb886013SMatthias Ringwald } 148b45b7749SMilanka Ringwald void reverse_24(const uint8_t * src, uint8_t * dest){ 149b45b7749SMilanka Ringwald reverse_bytes(src, dest, 3); 150eb886013SMatthias Ringwald } 151b45b7749SMilanka Ringwald void reverse_48(const uint8_t * src, uint8_t * dest){ 152b45b7749SMilanka Ringwald reverse_bytes(src, dest, 6); 153bf1b35bfSMatthias Ringwald } 154b45b7749SMilanka Ringwald void reverse_56(const uint8_t * src, uint8_t * dest){ 155b45b7749SMilanka Ringwald reverse_bytes(src, dest, 7); 156eb886013SMatthias Ringwald } 157b45b7749SMilanka Ringwald void reverse_64(const uint8_t * src, uint8_t * dest){ 158b45b7749SMilanka Ringwald reverse_bytes(src, dest, 8); 159eb886013SMatthias Ringwald } 160b45b7749SMilanka Ringwald void reverse_128(const uint8_t * src, uint8_t * dest){ 161b45b7749SMilanka Ringwald reverse_bytes(src, dest, 16); 162eb886013SMatthias Ringwald } 163b45b7749SMilanka Ringwald void reverse_256(const uint8_t * src, uint8_t * dest){ 164b45b7749SMilanka Ringwald reverse_bytes(src, dest, 32); 165cc7a2d78SMatthias Ringwald } 166eb886013SMatthias Ringwald 167724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 168724d70a2SMatthias Ringwald reverse_bytes(src, dest, 6); 169724d70a2SMatthias Ringwald } 170724d70a2SMatthias Ringwald 171ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){ 172c1ab6cc1SMatthias Ringwald return (a < b) ? a : b; 173ebaeb1beSMatthias Ringwald } 174ebaeb1beSMatthias Ringwald 175ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){ 176c1ab6cc1SMatthias Ringwald return (a > b) ? a : b; 177ebaeb1beSMatthias Ringwald } 178ebaeb1beSMatthias Ringwald 17968af3967SMatthias Ringwald /** 18068af3967SMatthias Ringwald * @brief Calculate delta between two points in time 1816b65794dSMilanka Ringwald * @return time_a - time_b - result > 0 if time_a is newer than time_b 18268af3967SMatthias Ringwald */ 18368af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){ 18468af3967SMatthias Ringwald return (int32_t)(time_a - time_b); 18568af3967SMatthias Ringwald } 18668af3967SMatthias Ringwald 187c1c58647SMatthias Ringwald 188eb886013SMatthias Ringwald char char_for_nibble(int nibble){ 1898334d3d8SMatthias Ringwald 1908334d3d8SMatthias Ringwald static const char * char_to_nibble = "0123456789ABCDEF"; 1918334d3d8SMatthias Ringwald 192c1c58647SMatthias Ringwald if (nibble < 16){ 193c1c58647SMatthias Ringwald return char_to_nibble[nibble]; 194c1c58647SMatthias Ringwald } else { 195eb886013SMatthias Ringwald return '?'; 196eb886013SMatthias Ringwald } 197c1c58647SMatthias Ringwald } 198eb886013SMatthias Ringwald 199405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){ 200405d63a9SMatthias Ringwald return char_for_nibble((value >> 4) & 0x0f); 201405d63a9SMatthias Ringwald } 202405d63a9SMatthias Ringwald 203405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){ 204405d63a9SMatthias Ringwald return char_for_nibble(value & 0x0f); 205405d63a9SMatthias Ringwald } 206405d63a9SMatthias Ringwald 207c1c58647SMatthias Ringwald 208a6efb919SMatthias Ringwald int nibble_for_char(char c){ 209c1ab6cc1SMatthias Ringwald if ((c >= '0') && (c <= '9')) return c - '0'; 210c1ab6cc1SMatthias Ringwald if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; 211c1ab6cc1SMatthias Ringwald if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; 212a6efb919SMatthias Ringwald return -1; 213a6efb919SMatthias Ringwald } 214a6efb919SMatthias Ringwald 21546059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP 216eb886013SMatthias Ringwald void printf_hexdump(const void * data, int size){ 217c1c58647SMatthias Ringwald char buffer[4]; 218c1c58647SMatthias Ringwald buffer[2] = ' '; 219c1c58647SMatthias Ringwald buffer[3] = 0; 2209dbfa930SMatthias Ringwald const uint8_t * ptr = (const uint8_t *) data; 221c1c58647SMatthias Ringwald while (size > 0){ 2229dbfa930SMatthias Ringwald uint8_t byte = *ptr++; 223c1c58647SMatthias Ringwald buffer[0] = char_for_high_nibble(byte); 224c1c58647SMatthias Ringwald buffer[1] = char_for_low_nibble(byte); 225c1c58647SMatthias Ringwald printf("%s", buffer); 226c1c58647SMatthias Ringwald size--; 227eb886013SMatthias Ringwald } 228eb886013SMatthias Ringwald printf("\n"); 229eb886013SMatthias Ringwald } 23046059ae4SMilanka Ringwald #endif 231eb886013SMatthias Ringwald 232cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 233cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){ 234405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16 235405d63a9SMatthias Ringwald // template '0x12, ' 236405d63a9SMatthias Ringwald #define BYTES_PER_BYTE 6 237405d63a9SMatthias Ringwald char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 2387224be7eSMatthias Ringwald int i, j; 239eb886013SMatthias Ringwald j = 0; 240eb886013SMatthias Ringwald for (i=0; i<size;i++){ 2417224be7eSMatthias Ringwald 2427224be7eSMatthias Ringwald // help static analyzer proof that j stays within bounds 243c1ab6cc1SMatthias Ringwald if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){ 2447224be7eSMatthias Ringwald j = 0; 2457224be7eSMatthias Ringwald } 2467224be7eSMatthias Ringwald 247eb886013SMatthias Ringwald uint8_t byte = ((uint8_t *)data)[i]; 248eb886013SMatthias Ringwald buffer[j++] = '0'; 249eb886013SMatthias Ringwald buffer[j++] = 'x'; 250405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 251405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 252eb886013SMatthias Ringwald buffer[j++] = ','; 253eb886013SMatthias Ringwald buffer[j++] = ' '; 2547224be7eSMatthias Ringwald 255c1ab6cc1SMatthias Ringwald if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){ 256eb886013SMatthias Ringwald buffer[j] = 0; 257cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 258eb886013SMatthias Ringwald j = 0; 259eb886013SMatthias Ringwald } 260eb886013SMatthias Ringwald } 261eb886013SMatthias Ringwald if (j != 0){ 262eb886013SMatthias Ringwald buffer[j] = 0; 263cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 264eb886013SMatthias Ringwald } 265cb42147aSMatthias Ringwald } 266cb42147aSMatthias Ringwald #endif 267cb42147aSMatthias Ringwald 268cb42147aSMatthias Ringwald void log_debug_hexdump(const void * data, int size){ 269e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG 270fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 271cb42147aSMatthias Ringwald #else 2724bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2734bd79111SMatthias Ringwald UNUSED(size); // ok: no code 274cb42147aSMatthias Ringwald #endif 275cb42147aSMatthias Ringwald } 276cb42147aSMatthias Ringwald 277cb42147aSMatthias Ringwald void log_info_hexdump(const void * data, int size){ 278cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO 279fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 280d0662982SMatthias Ringwald #else 2814bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2824bd79111SMatthias Ringwald UNUSED(size); // ok: no code 2838314c363SMatthias Ringwald #endif 2847299c0feSMatthias Ringwald } 285eb886013SMatthias Ringwald 2868314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){ 28702bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO 28802bdfbf8SMatthias Ringwald char buffer[16*2+1]; 28902bdfbf8SMatthias Ringwald int i; 29002bdfbf8SMatthias Ringwald int j = 0; 29102bdfbf8SMatthias Ringwald for (i=0; i<16;i++){ 29202bdfbf8SMatthias Ringwald uint8_t byte = key[i]; 293405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 294405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 29502bdfbf8SMatthias Ringwald } 29602bdfbf8SMatthias Ringwald buffer[j] = 0; 29702bdfbf8SMatthias Ringwald log_info("%-6s %s", name, buffer); 298d0662982SMatthias Ringwald #else 299d0662982SMatthias Ringwald UNUSED(name); 300cb42147aSMatthias Ringwald (void)key; 30102bdfbf8SMatthias Ringwald #endif 302eb886013SMatthias Ringwald } 303eb886013SMatthias Ringwald 3042b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t 3052b604902SMatthias Ringwald 306eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 3072b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 308eb886013SMatthias Ringwald 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 309eb886013SMatthias Ringwald 31048cdff9cSMilanka Ringwald void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid){ 311b45b7749SMilanka Ringwald (void)memcpy(uuid128, bluetooth_base_uuid, 16); 31248cdff9cSMilanka Ringwald big_endian_store_32(uuid128, 0, short_uuid); 313eb886013SMatthias Ringwald } 314eb886013SMatthias Ringwald 3155222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 3162b604902SMatthias Ringwald return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 317eb886013SMatthias Ringwald } 318eb886013SMatthias Ringwald 319eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1]; 3205222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){ 3217224be7eSMatthias Ringwald int i; 3227224be7eSMatthias Ringwald int j = 0; 3237224be7eSMatthias Ringwald // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 3247224be7eSMatthias Ringwald const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 3257224be7eSMatthias Ringwald for (i=0;i<16;i++){ 326405d63a9SMatthias Ringwald uint8_t byte = uuid[i]; 327405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 328405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 3297224be7eSMatthias Ringwald if (dash_locations & (1<<i)){ 3307224be7eSMatthias Ringwald uuid128_to_str_buffer[j++] = '-'; 3317224be7eSMatthias Ringwald } 3327224be7eSMatthias Ringwald } 333eb886013SMatthias Ringwald return uuid128_to_str_buffer; 334eb886013SMatthias Ringwald } 335eb886013SMatthias Ringwald 336eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 33761c3ec28SMatthias Ringwald char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter){ 338eb886013SMatthias Ringwald char * p = bd_addr_to_str_buffer; 339eb886013SMatthias Ringwald int i; 340eb886013SMatthias Ringwald for (i = 0; i < 6 ; i++) { 341405d63a9SMatthias Ringwald uint8_t byte = addr[i]; 342405d63a9SMatthias Ringwald *p++ = char_for_high_nibble(byte); 343405d63a9SMatthias Ringwald *p++ = char_for_low_nibble(byte); 34461c3ec28SMatthias Ringwald *p++ = delimiter; 345eb886013SMatthias Ringwald } 346eb886013SMatthias Ringwald *--p = 0; 347eb886013SMatthias Ringwald return (char *) bd_addr_to_str_buffer; 348eb886013SMatthias Ringwald } 349eb886013SMatthias Ringwald 35061c3ec28SMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){ 35161c3ec28SMatthias Ringwald return bd_addr_to_str_with_delimiter(addr, ':'); 35261c3ec28SMatthias Ringwald } 35361c3ec28SMatthias Ringwald 3543c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){ 3553c9da642SMatthias Ringwald const int bd_addr_string_len = 17; 35630314625SMatthias Ringwald uint16_t i = 0; 35730314625SMatthias Ringwald while ((i + bd_addr_string_len) <= size){ 3583c9da642SMatthias Ringwald if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) { 3593c9da642SMatthias Ringwald i++; 3603c9da642SMatthias Ringwald continue; 3613c9da642SMatthias Ringwald } 3623c9da642SMatthias Ringwald // set address 3633c9da642SMatthias Ringwald (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len); 3643c9da642SMatthias Ringwald i += bd_addr_string_len; 3653c9da642SMatthias Ringwald } 3663c9da642SMatthias Ringwald } 3673c9da642SMatthias Ringwald 368a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 36941f9be70SMatthias Ringwald int upper_nibble = nibble_for_char(byte_string[0]); 370a6efb919SMatthias Ringwald if (upper_nibble < 0) return -1; 37141f9be70SMatthias Ringwald int lower_nibble = nibble_for_char(byte_string[1]); 372a6efb919SMatthias Ringwald if (lower_nibble < 0) return -1; 373a6efb919SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 374a6efb919SMatthias Ringwald } 375eb886013SMatthias Ringwald 376a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 37741f9be70SMatthias Ringwald const char * the_string = addr_string; 378a6efb919SMatthias Ringwald uint8_t buffer[BD_ADDR_LEN]; 379a6efb919SMatthias Ringwald int result = 0; 380eb886013SMatthias Ringwald int i; 381eb886013SMatthias Ringwald for (i = 0; i < BD_ADDR_LEN; i++) { 38241f9be70SMatthias Ringwald int single_byte = scan_hex_byte(the_string); 383a6efb919SMatthias Ringwald if (single_byte < 0) break; 38441f9be70SMatthias Ringwald the_string += 2; 385b0920f25SMilanka Ringwald buffer[i] = (uint8_t)single_byte; 38641f9be70SMatthias Ringwald // don't check separator after last byte 387c1ab6cc1SMatthias Ringwald if (i == (BD_ADDR_LEN - 1)) { 388a6efb919SMatthias Ringwald result = 1; 389a6efb919SMatthias Ringwald break; 390eb886013SMatthias Ringwald } 391cd2e416cSMatthias Ringwald // skip supported separators 39241f9be70SMatthias Ringwald char next_char = *the_string; 3935df9dc78SMatthias Ringwald if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) { 39441f9be70SMatthias Ringwald the_string++; 395cd2e416cSMatthias Ringwald } 396a6efb919SMatthias Ringwald } 397a6efb919SMatthias Ringwald 3989305033eSMatthias Ringwald if (result != 0){ 399a6efb919SMatthias Ringwald bd_addr_copy(addr, buffer); 400a6efb919SMatthias Ringwald } 401a6efb919SMatthias Ringwald return result; 402eb886013SMatthias Ringwald } 4035d067ab1SMatthias Ringwald 4045d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char * str){ 40541f9be70SMatthias Ringwald const char * the_string = str; 4065d067ab1SMatthias Ringwald uint32_t val = 0; 407ff3cc4a5SMatthias Ringwald while (true){ 40841f9be70SMatthias Ringwald char chr = *the_string++; 409c1ab6cc1SMatthias Ringwald if (!chr || (chr < '0') || (chr > '9')) 4105d067ab1SMatthias Ringwald return val; 4114ea43905SMatthias Ringwald val = (val * 10u) + (uint8_t)(chr - '0'); 4125d067ab1SMatthias Ringwald } 4135d067ab1SMatthias Ringwald } 4141f41c2c9SMatthias Ringwald 415d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){ 416d1207cd8SMilanka Ringwald if (i < 10) return 1; 417d1207cd8SMilanka Ringwald if (i < 100) return 2; 418d1207cd8SMilanka Ringwald if (i < 1000) return 3; 419d1207cd8SMilanka Ringwald if (i < 10000) return 4; 420d1207cd8SMilanka Ringwald if (i < 100000) return 5; 421d1207cd8SMilanka Ringwald if (i < 1000000) return 6; 422d1207cd8SMilanka Ringwald if (i < 10000000) return 7; 423d1207cd8SMilanka Ringwald if (i < 100000000) return 8; 424d1207cd8SMilanka Ringwald if (i < 1000000000) return 9; 425d1207cd8SMilanka Ringwald return 10; 426d1207cd8SMilanka Ringwald } 427d1207cd8SMilanka Ringwald 428d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){ 42941f9be70SMatthias Ringwald uint32_t v = x; 43041f9be70SMatthias Ringwald v = (v & 0x55555555) + ((v >> 1) & 0x55555555U); 43141f9be70SMatthias Ringwald v = (v & 0x33333333) + ((v >> 2) & 0x33333333U); 43241f9be70SMatthias Ringwald v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0FU); 43341f9be70SMatthias Ringwald v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FFU); 43441f9be70SMatthias Ringwald v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU); 43541f9be70SMatthias Ringwald return v; 436d1207cd8SMilanka Ringwald } 4371f41c2c9SMatthias Ringwald 438*ec08441fSMatthias Ringwald uint8_t btstack_clz(uint32_t value) { 439*ec08441fSMatthias Ringwald #if defined(__GNUC__) || defined (__clang__) 440*ec08441fSMatthias Ringwald // use gcc/clang intrinsic 441*ec08441fSMatthias Ringwald return (uint8_t) __builtin_clz(value); 442*ec08441fSMatthias Ringwald #elif defined(_MSC_VER) 443*ec08441fSMatthias Ringwald // use MSVC intrinsic 444*ec08441fSMatthias Ringwald DWORD leading_zero = 0; 445*ec08441fSMatthias Ringwald if (_BitScanReverse( &leading_zero, value )){ 446*ec08441fSMatthias Ringwald return (uint8_t)(31 - leading_zero); 447*ec08441fSMatthias Ringwald } else { 448*ec08441fSMatthias Ringwald return 32; 449*ec08441fSMatthias Ringwald } 450*ec08441fSMatthias Ringwald #else 451*ec08441fSMatthias Ringwald // divide-and-conquer implementation for 32-bit integers 452*ec08441fSMatthias Ringwald if (x == 0) return 32; 453*ec08441fSMatthias Ringwald uint8_t r = 0; 454*ec08441fSMatthias Ringwald if ((x & 0xffff0000u) == 0) { 455*ec08441fSMatthias Ringwald x <<= 16; 456*ec08441fSMatthias Ringwald r += 16; 457*ec08441fSMatthias Ringwald } 458*ec08441fSMatthias Ringwald if ((x & 0xff000000u) == 0) { 459*ec08441fSMatthias Ringwald x <<= 8; 460*ec08441fSMatthias Ringwald r += 8; 461*ec08441fSMatthias Ringwald } 462*ec08441fSMatthias Ringwald if ((x & 0xf0000000u) == 0) { 463*ec08441fSMatthias Ringwald x <<= 4; 464*ec08441fSMatthias Ringwald r += 4; 465*ec08441fSMatthias Ringwald } 466*ec08441fSMatthias Ringwald if ((x & 0xc0000000u) == 0) { 467*ec08441fSMatthias Ringwald x <<= 2; 468*ec08441fSMatthias Ringwald r += 2; 469*ec08441fSMatthias Ringwald } 470*ec08441fSMatthias Ringwald if ((x & 0x80000000u) == 0) { 471*ec08441fSMatthias Ringwald x <<= 1; 472*ec08441fSMatthias Ringwald r += 1; 473*ec08441fSMatthias Ringwald } 474*ec08441fSMatthias Ringwald return r; 475*ec08441fSMatthias Ringwald #endif 476*ec08441fSMatthias Ringwald } 477*ec08441fSMatthias Ringwald 4781f41c2c9SMatthias Ringwald /* 4791f41c2c9SMatthias Ringwald * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 4801f41c2c9SMatthias Ringwald */ 4811f41c2c9SMatthias Ringwald 4821f41c2c9SMatthias Ringwald #define CRC8_INIT 0xFF // Initial FCS value 4831f41c2c9SMatthias Ringwald #define CRC8_OK 0xCF // Good final FCS value 4841f41c2c9SMatthias Ringwald 4851f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 4861f41c2c9SMatthias Ringwald 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 4871f41c2c9SMatthias Ringwald 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 4881f41c2c9SMatthias Ringwald 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 4891f41c2c9SMatthias Ringwald 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 4901f41c2c9SMatthias Ringwald 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 4911f41c2c9SMatthias Ringwald 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 4921f41c2c9SMatthias Ringwald 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 4931f41c2c9SMatthias Ringwald 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 4941f41c2c9SMatthias Ringwald 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 4951f41c2c9SMatthias Ringwald 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 4961f41c2c9SMatthias Ringwald 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 4971f41c2c9SMatthias Ringwald 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 4981f41c2c9SMatthias Ringwald 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 4991f41c2c9SMatthias Ringwald 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 5001f41c2c9SMatthias Ringwald 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 5011f41c2c9SMatthias Ringwald 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 5021f41c2c9SMatthias Ringwald }; 5031f41c2c9SMatthias Ringwald 5041f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 5051f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){ 5061f41c2c9SMatthias Ringwald uint16_t count; 5071f41c2c9SMatthias Ringwald uint8_t crc = CRC8_INIT; 5081f41c2c9SMatthias Ringwald for (count = 0; count < len; count++){ 5091f41c2c9SMatthias Ringwald crc = crc8table[crc ^ data[count]]; 5101f41c2c9SMatthias Ringwald } 5111f41c2c9SMatthias Ringwald return crc; 5121f41c2c9SMatthias Ringwald } 5131f41c2c9SMatthias Ringwald 5141f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 51563dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 5161f41c2c9SMatthias Ringwald uint8_t crc; 5171f41c2c9SMatthias Ringwald crc = crc8(data, len); 5181f41c2c9SMatthias Ringwald crc = crc8table[crc ^ check_sum]; 5191f41c2c9SMatthias Ringwald if (crc == CRC8_OK){ 5201f41c2c9SMatthias Ringwald return 0; /* Valid */ 5211f41c2c9SMatthias Ringwald } else { 5221f41c2c9SMatthias Ringwald return 1; /* Failed */ 5231f41c2c9SMatthias Ringwald } 5241f41c2c9SMatthias Ringwald } 5251f41c2c9SMatthias Ringwald 5261f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 52763dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 5281f41c2c9SMatthias Ringwald /* Ones complement */ 5294ea43905SMatthias Ringwald return 0xFFu - crc8(data, len); 5301f41c2c9SMatthias Ringwald } 531a73d0b9dSMilanka Ringwald 532a73d0b9dSMilanka Ringwald uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid){ 533a73d0b9dSMilanka Ringwald uint16_t next_cid; 534a73d0b9dSMilanka Ringwald if (current_cid == 0xffff) { 535a73d0b9dSMilanka Ringwald next_cid = 1; 536a73d0b9dSMilanka Ringwald } else { 537a73d0b9dSMilanka Ringwald next_cid = current_cid + 1; 538a73d0b9dSMilanka Ringwald } 539a73d0b9dSMilanka Ringwald return next_cid; 540a73d0b9dSMilanka Ringwald } 541de22414aSMatthias Ringwald 542de22414aSMatthias Ringwald void btstack_strcpy(char * dst, uint16_t dst_size, const char * src){ 543a5f7b8d3SMatthias Ringwald uint16_t bytes_to_copy = (uint16_t) btstack_min( dst_size - 1, (uint32_t) strlen(src)); 544de22414aSMatthias Ringwald (void) memcpy(dst, src, bytes_to_copy); 5458d3d7744SMatthias Ringwald dst[bytes_to_copy] = 0; 546de22414aSMatthias Ringwald } 5473ece4788SMatthias Ringwald 5483ece4788SMatthias Ringwald void btstack_strcat(char * dst, uint16_t dst_size, const char * src){ 5493ece4788SMatthias Ringwald uint16_t src_len = (uint16_t) strlen(src); 5503ece4788SMatthias Ringwald uint16_t dst_len = (uint16_t) strlen(dst); 5513ece4788SMatthias Ringwald uint16_t bytes_to_copy = btstack_min( src_len, dst_size - dst_len - 1); 5523ece4788SMatthias Ringwald (void) memcpy( &dst[dst_len], src, bytes_to_copy); 5533ece4788SMatthias Ringwald dst[dst_len + bytes_to_copy] = 0; 5543ece4788SMatthias Ringwald } 555