1eb886013SMatthias Ringwald /* 2eb886013SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3eb886013SMatthias Ringwald * 4eb886013SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5eb886013SMatthias Ringwald * modification, are permitted provided that the following conditions 6eb886013SMatthias Ringwald * are met: 7eb886013SMatthias Ringwald * 8eb886013SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9eb886013SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10eb886013SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11eb886013SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12eb886013SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13eb886013SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14eb886013SMatthias Ringwald * contributors may be used to endorse or promote products derived 15eb886013SMatthias Ringwald * from this software without specific prior written permission. 16eb886013SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17eb886013SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18eb886013SMatthias Ringwald * monetary gain. 19eb886013SMatthias Ringwald * 20eb886013SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21eb886013SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22eb886013SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23eb886013SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24eb886013SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25eb886013SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26eb886013SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27eb886013SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28eb886013SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29eb886013SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30eb886013SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31eb886013SMatthias Ringwald * SUCH DAMAGE. 32eb886013SMatthias Ringwald * 33eb886013SMatthias Ringwald * Please inquire about commercial licensing options at 34eb886013SMatthias Ringwald * [email protected] 35eb886013SMatthias Ringwald * 36eb886013SMatthias Ringwald */ 37eb886013SMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_util.c" 39ab2c6ae4SMatthias Ringwald 40eb886013SMatthias Ringwald /* 41eb886013SMatthias Ringwald * btstack_util.c 42eb886013SMatthias Ringwald * 43eb886013SMatthias Ringwald * General utility functions 44eb886013SMatthias Ringwald * 45eb886013SMatthias Ringwald * Created by Matthias Ringwald on 7/23/09. 46eb886013SMatthias Ringwald */ 47eb886013SMatthias Ringwald 487907f069SMatthias Ringwald #include "btstack_config.h" 4902bdfbf8SMatthias Ringwald #include "btstack_debug.h" 50eb886013SMatthias Ringwald #include "btstack_util.h" 5102bdfbf8SMatthias Ringwald 52eb886013SMatthias Ringwald #include <stdio.h> 53eb886013SMatthias Ringwald #include <string.h> 54eb886013SMatthias Ringwald 5573988a59SMatthias Ringwald /** 5673988a59SMatthias Ringwald * @brief Compare two Bluetooth addresses 5773988a59SMatthias Ringwald * @param a 5873988a59SMatthias Ringwald * @param b 59969fc1c5SMilanka Ringwald * @return 0 if equal 6073988a59SMatthias Ringwald */ 615222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){ 6273988a59SMatthias Ringwald return memcmp(a,b, BD_ADDR_LEN); 6373988a59SMatthias Ringwald } 6473988a59SMatthias Ringwald 6573988a59SMatthias Ringwald /** 6673988a59SMatthias Ringwald * @brief Copy Bluetooth address 6773988a59SMatthias Ringwald * @param dest 6873988a59SMatthias Ringwald * @param src 6973988a59SMatthias Ringwald */ 705222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){ 716535961aSMatthias Ringwald (void)memcpy(dest, src, BD_ADDR_LEN); 7273988a59SMatthias Ringwald } 7373988a59SMatthias Ringwald 7473988a59SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int pos){ 75b0920f25SMilanka Ringwald return (uint16_t)(((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8)); 7673988a59SMatthias Ringwald } 7773988a59SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int pos){ 7873988a59SMatthias Ringwald return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16); 7973988a59SMatthias Ringwald } 8073988a59SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int pos){ 8173988a59SMatthias Ringwald return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16) | (((uint32_t) buffer[(pos)+3]) << 24); 8273988a59SMatthias Ringwald } 8373988a59SMatthias Ringwald 84f8fbdce0SMatthias Ringwald void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 85b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)value; 86b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 87eb886013SMatthias Ringwald } 88eb886013SMatthias Ringwald 89adbdd27aSMilanka Ringwald void little_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){ 90adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value); 91adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 92adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 93adbdd27aSMilanka Ringwald } 94adbdd27aSMilanka Ringwald 95f8fbdce0SMatthias Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 96b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 97b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 98b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 99b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 100eb886013SMatthias Ringwald } 101eb886013SMatthias Ringwald 10273988a59SMatthias Ringwald uint32_t big_endian_read_16( const uint8_t * buffer, int pos) { 103b0920f25SMilanka Ringwald return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos ]) << 8)); 10473988a59SMatthias Ringwald } 10573988a59SMatthias Ringwald 106e57a2545SMilanka Ringwald uint32_t big_endian_read_24( const uint8_t * buffer, int pos) { 107e57a2545SMilanka Ringwald return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16)); 108e57a2545SMilanka Ringwald } 109e57a2545SMilanka Ringwald 11073988a59SMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) { 11173988a59SMatthias Ringwald return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24); 11273988a59SMatthias Ringwald } 11373988a59SMatthias Ringwald 114f8fbdce0SMatthias Ringwald void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 115b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 116b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 117eb886013SMatthias Ringwald } 118eb886013SMatthias Ringwald 1197f535380SMilanka Ringwald void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){ 120b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 121b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 122b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 1237f535380SMilanka Ringwald } 1247f535380SMilanka Ringwald 125f8fbdce0SMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 126b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 127b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 128b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 129b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 130eb886013SMatthias Ringwald } 131eb886013SMatthias Ringwald 132eb886013SMatthias Ringwald // general swap/endianess utils 1339c80e4ccSMatthias Ringwald void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){ 134eb886013SMatthias Ringwald int i; 135eb886013SMatthias Ringwald for (i = 0; i < len; i++) 136eb886013SMatthias Ringwald dst[len - 1 - i] = src[i]; 137eb886013SMatthias Ringwald } 1389c80e4ccSMatthias Ringwald void reverse_24(const uint8_t * src, uint8_t * dst){ 1399c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 3); 140eb886013SMatthias Ringwald } 1419c80e4ccSMatthias Ringwald void reverse_48(const uint8_t * src, uint8_t * dst){ 1429c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 6); 143bf1b35bfSMatthias Ringwald } 1449c80e4ccSMatthias Ringwald void reverse_56(const uint8_t * src, uint8_t * dst){ 1459c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 7); 146eb886013SMatthias Ringwald } 1479c80e4ccSMatthias Ringwald void reverse_64(const uint8_t * src, uint8_t * dst){ 1489c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 8); 149eb886013SMatthias Ringwald } 1509c80e4ccSMatthias Ringwald void reverse_128(const uint8_t * src, uint8_t * dst){ 1519c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 16); 152eb886013SMatthias Ringwald } 153cc7a2d78SMatthias Ringwald void reverse_256(const uint8_t * src, uint8_t * dst){ 154cc7a2d78SMatthias Ringwald reverse_bytes(src, dst, 32); 155cc7a2d78SMatthias Ringwald } 156eb886013SMatthias Ringwald 157724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 158724d70a2SMatthias Ringwald reverse_bytes(src, dest, 6); 159724d70a2SMatthias Ringwald } 160724d70a2SMatthias Ringwald 161ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){ 162c1ab6cc1SMatthias Ringwald return (a < b) ? a : b; 163ebaeb1beSMatthias Ringwald } 164ebaeb1beSMatthias Ringwald 165ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){ 166c1ab6cc1SMatthias Ringwald return (a > b) ? a : b; 167ebaeb1beSMatthias Ringwald } 168ebaeb1beSMatthias Ringwald 16968af3967SMatthias Ringwald /** 17068af3967SMatthias Ringwald * @brief Calculate delta between two points in time 17168af3967SMatthias Ringwald * @returns time_a - time_b - result > 0 if time_a is newer than time_b 17268af3967SMatthias Ringwald */ 17368af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){ 17468af3967SMatthias Ringwald return (int32_t)(time_a - time_b); 17568af3967SMatthias Ringwald } 17668af3967SMatthias Ringwald 177c1c58647SMatthias Ringwald 178eb886013SMatthias Ringwald char char_for_nibble(int nibble){ 1798334d3d8SMatthias Ringwald 1808334d3d8SMatthias Ringwald static const char * char_to_nibble = "0123456789ABCDEF"; 1818334d3d8SMatthias Ringwald 182c1c58647SMatthias Ringwald if (nibble < 16){ 183c1c58647SMatthias Ringwald return char_to_nibble[nibble]; 184c1c58647SMatthias Ringwald } else { 185eb886013SMatthias Ringwald return '?'; 186eb886013SMatthias Ringwald } 187c1c58647SMatthias Ringwald } 188eb886013SMatthias Ringwald 189405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){ 190405d63a9SMatthias Ringwald return char_for_nibble((value >> 4) & 0x0f); 191405d63a9SMatthias Ringwald } 192405d63a9SMatthias Ringwald 193405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){ 194405d63a9SMatthias Ringwald return char_for_nibble(value & 0x0f); 195405d63a9SMatthias Ringwald } 196405d63a9SMatthias Ringwald 197c1c58647SMatthias Ringwald 198a6efb919SMatthias Ringwald int nibble_for_char(char c){ 199c1ab6cc1SMatthias Ringwald if ((c >= '0') && (c <= '9')) return c - '0'; 200c1ab6cc1SMatthias Ringwald if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; 201c1ab6cc1SMatthias Ringwald if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; 202a6efb919SMatthias Ringwald return -1; 203a6efb919SMatthias Ringwald } 204a6efb919SMatthias Ringwald 205eb886013SMatthias Ringwald void printf_hexdump(const void *data, int size){ 206c1c58647SMatthias Ringwald char buffer[4]; 207c1c58647SMatthias Ringwald buffer[2] = ' '; 208c1c58647SMatthias Ringwald buffer[3] = 0; 2099dbfa930SMatthias Ringwald const uint8_t * ptr = (const uint8_t *) data; 210c1c58647SMatthias Ringwald while (size > 0){ 2119dbfa930SMatthias Ringwald uint8_t byte = *ptr++; 212c1c58647SMatthias Ringwald buffer[0] = char_for_high_nibble(byte); 213c1c58647SMatthias Ringwald buffer[1] = char_for_low_nibble(byte); 214c1c58647SMatthias Ringwald printf("%s", buffer); 215c1c58647SMatthias Ringwald size--; 216eb886013SMatthias Ringwald } 217eb886013SMatthias Ringwald printf("\n"); 218eb886013SMatthias Ringwald } 219eb886013SMatthias Ringwald 220cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 221cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){ 222405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16 223405d63a9SMatthias Ringwald // template '0x12, ' 224405d63a9SMatthias Ringwald #define BYTES_PER_BYTE 6 225405d63a9SMatthias Ringwald char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 2267224be7eSMatthias Ringwald int i, j; 227eb886013SMatthias Ringwald j = 0; 228eb886013SMatthias Ringwald for (i=0; i<size;i++){ 2297224be7eSMatthias Ringwald 2307224be7eSMatthias Ringwald // help static analyzer proof that j stays within bounds 231c1ab6cc1SMatthias Ringwald if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){ 2327224be7eSMatthias Ringwald j = 0; 2337224be7eSMatthias Ringwald } 2347224be7eSMatthias Ringwald 235eb886013SMatthias Ringwald uint8_t byte = ((uint8_t *)data)[i]; 236eb886013SMatthias Ringwald buffer[j++] = '0'; 237eb886013SMatthias Ringwald buffer[j++] = 'x'; 238405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 239405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 240eb886013SMatthias Ringwald buffer[j++] = ','; 241eb886013SMatthias Ringwald buffer[j++] = ' '; 2427224be7eSMatthias Ringwald 243c1ab6cc1SMatthias Ringwald if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){ 244eb886013SMatthias Ringwald buffer[j] = 0; 245cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 246eb886013SMatthias Ringwald j = 0; 247eb886013SMatthias Ringwald } 248eb886013SMatthias Ringwald } 249eb886013SMatthias Ringwald if (j != 0){ 250eb886013SMatthias Ringwald buffer[j] = 0; 251cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 252eb886013SMatthias Ringwald } 253cb42147aSMatthias Ringwald } 254cb42147aSMatthias Ringwald #endif 255cb42147aSMatthias Ringwald 256cb42147aSMatthias Ringwald void log_debug_hexdump(const void *data, int size){ 257e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG 258fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 259cb42147aSMatthias Ringwald #else 2604bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2614bd79111SMatthias Ringwald UNUSED(size); // ok: no code 262cb42147aSMatthias Ringwald #endif 263cb42147aSMatthias Ringwald } 264cb42147aSMatthias Ringwald 265cb42147aSMatthias Ringwald void log_info_hexdump(const void *data, int size){ 266cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO 267fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 268d0662982SMatthias Ringwald #else 2694bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2704bd79111SMatthias Ringwald UNUSED(size); // ok: no code 2718314c363SMatthias Ringwald #endif 2727299c0feSMatthias Ringwald } 273eb886013SMatthias Ringwald 2748314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){ 27502bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO 27602bdfbf8SMatthias Ringwald char buffer[16*2+1]; 27702bdfbf8SMatthias Ringwald int i; 27802bdfbf8SMatthias Ringwald int j = 0; 27902bdfbf8SMatthias Ringwald for (i=0; i<16;i++){ 28002bdfbf8SMatthias Ringwald uint8_t byte = key[i]; 281405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 282405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 28302bdfbf8SMatthias Ringwald } 28402bdfbf8SMatthias Ringwald buffer[j] = 0; 28502bdfbf8SMatthias Ringwald log_info("%-6s %s", name, buffer); 286d0662982SMatthias Ringwald #else 287d0662982SMatthias Ringwald UNUSED(name); 288cb42147aSMatthias Ringwald (void)key; 28902bdfbf8SMatthias Ringwald #endif 290eb886013SMatthias Ringwald } 291eb886013SMatthias Ringwald 2922b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t 2932b604902SMatthias Ringwald 294eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 2952b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 296eb886013SMatthias Ringwald 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 297eb886013SMatthias Ringwald 298e1a125dfSMatthias Ringwald void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){ 2996535961aSMatthias Ringwald (void)memcpy(uuid, bluetooth_base_uuid, 16); 300f8fbdce0SMatthias Ringwald big_endian_store_32(uuid, 0, shortUUID); 301eb886013SMatthias Ringwald } 302eb886013SMatthias Ringwald 3035222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 3042b604902SMatthias Ringwald return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 305eb886013SMatthias Ringwald } 306eb886013SMatthias Ringwald 307eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1]; 3085222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){ 3097224be7eSMatthias Ringwald int i; 3107224be7eSMatthias Ringwald int j = 0; 3117224be7eSMatthias Ringwald // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 3127224be7eSMatthias Ringwald const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 3137224be7eSMatthias Ringwald for (i=0;i<16;i++){ 314405d63a9SMatthias Ringwald uint8_t byte = uuid[i]; 315405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 316405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 3177224be7eSMatthias Ringwald if (dash_locations & (1<<i)){ 3187224be7eSMatthias Ringwald uuid128_to_str_buffer[j++] = '-'; 3197224be7eSMatthias Ringwald } 3207224be7eSMatthias Ringwald } 321eb886013SMatthias Ringwald return uuid128_to_str_buffer; 322eb886013SMatthias Ringwald } 323eb886013SMatthias Ringwald 324eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 3255222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){ 326eb886013SMatthias Ringwald // orig code 327eb886013SMatthias Ringwald // sprintf(bd_addr_to_str_buffer, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 328eb886013SMatthias Ringwald // sprintf-free code 329eb886013SMatthias Ringwald char * p = bd_addr_to_str_buffer; 330eb886013SMatthias Ringwald int i; 331eb886013SMatthias Ringwald for (i = 0; i < 6 ; i++) { 332405d63a9SMatthias Ringwald uint8_t byte = addr[i]; 333405d63a9SMatthias Ringwald *p++ = char_for_high_nibble(byte); 334405d63a9SMatthias Ringwald *p++ = char_for_low_nibble(byte); 335eb886013SMatthias Ringwald *p++ = ':'; 336eb886013SMatthias Ringwald } 337eb886013SMatthias Ringwald *--p = 0; 338eb886013SMatthias Ringwald return (char *) bd_addr_to_str_buffer; 339eb886013SMatthias Ringwald } 340eb886013SMatthias Ringwald 3413c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){ 3423c9da642SMatthias Ringwald const int bd_addr_string_len = 17; 34330314625SMatthias Ringwald uint16_t i = 0; 34430314625SMatthias Ringwald while ((i + bd_addr_string_len) <= size){ 3453c9da642SMatthias Ringwald if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) { 3463c9da642SMatthias Ringwald i++; 3473c9da642SMatthias Ringwald continue; 3483c9da642SMatthias Ringwald } 3493c9da642SMatthias Ringwald // set address 3503c9da642SMatthias Ringwald (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len); 3513c9da642SMatthias Ringwald i += bd_addr_string_len; 3523c9da642SMatthias Ringwald } 3533c9da642SMatthias Ringwald } 3543c9da642SMatthias Ringwald 355a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 356a6efb919SMatthias Ringwald int upper_nibble = nibble_for_char(*byte_string++); 357a6efb919SMatthias Ringwald if (upper_nibble < 0) return -1; 358a6efb919SMatthias Ringwald int lower_nibble = nibble_for_char(*byte_string); 359a6efb919SMatthias Ringwald if (lower_nibble < 0) return -1; 360a6efb919SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 361a6efb919SMatthias Ringwald } 362eb886013SMatthias Ringwald 363a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 364a6efb919SMatthias Ringwald uint8_t buffer[BD_ADDR_LEN]; 365a6efb919SMatthias Ringwald int result = 0; 366eb886013SMatthias Ringwald int i; 367eb886013SMatthias Ringwald for (i = 0; i < BD_ADDR_LEN; i++) { 368a6efb919SMatthias Ringwald int single_byte = scan_hex_byte(addr_string); 369a6efb919SMatthias Ringwald if (single_byte < 0) break; 370a6efb919SMatthias Ringwald addr_string += 2; 371b0920f25SMilanka Ringwald buffer[i] = (uint8_t)single_byte; 372a6efb919SMatthias Ringwald // don't check seperator after last byte 373c1ab6cc1SMatthias Ringwald if (i == (BD_ADDR_LEN - 1)) { 374a6efb919SMatthias Ringwald result = 1; 375a6efb919SMatthias Ringwald break; 376eb886013SMatthias Ringwald } 377cd2e416cSMatthias Ringwald // skip supported separators 378cd2e416cSMatthias Ringwald char next_char = *addr_string; 3795df9dc78SMatthias Ringwald if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) { 380cd2e416cSMatthias Ringwald addr_string++; 381cd2e416cSMatthias Ringwald } 382a6efb919SMatthias Ringwald } 383a6efb919SMatthias Ringwald 384a6efb919SMatthias Ringwald if (result){ 385a6efb919SMatthias Ringwald bd_addr_copy(addr, buffer); 386a6efb919SMatthias Ringwald } 387a6efb919SMatthias Ringwald return result; 388eb886013SMatthias Ringwald } 3895d067ab1SMatthias Ringwald 3905d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){ 3915d067ab1SMatthias Ringwald uint32_t val = 0; 392ff3cc4a5SMatthias Ringwald while (true){ 3935d067ab1SMatthias Ringwald char chr = *str; 394c1ab6cc1SMatthias Ringwald if (!chr || (chr < '0') || (chr > '9')) 3955d067ab1SMatthias Ringwald return val; 396*4ea43905SMatthias Ringwald val = (val * 10u) + (uint8_t)(chr - '0'); 3975d067ab1SMatthias Ringwald str++; 3985d067ab1SMatthias Ringwald } 3995d067ab1SMatthias Ringwald } 4001f41c2c9SMatthias Ringwald 401d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){ 402d1207cd8SMilanka Ringwald if (i < 10) return 1; 403d1207cd8SMilanka Ringwald if (i < 100) return 2; 404d1207cd8SMilanka Ringwald if (i < 1000) return 3; 405d1207cd8SMilanka Ringwald if (i < 10000) return 4; 406d1207cd8SMilanka Ringwald if (i < 100000) return 5; 407d1207cd8SMilanka Ringwald if (i < 1000000) return 6; 408d1207cd8SMilanka Ringwald if (i < 10000000) return 7; 409d1207cd8SMilanka Ringwald if (i < 100000000) return 8; 410d1207cd8SMilanka Ringwald if (i < 1000000000) return 9; 411d1207cd8SMilanka Ringwald return 10; 412d1207cd8SMilanka Ringwald } 413d1207cd8SMilanka Ringwald 414d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){ 415d1207cd8SMilanka Ringwald x = (x & 0x55555555) + ((x >> 1) & 0x55555555); 416d1207cd8SMilanka Ringwald x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 417d1207cd8SMilanka Ringwald x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); 418d1207cd8SMilanka Ringwald x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); 419d1207cd8SMilanka Ringwald x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); 420d1207cd8SMilanka Ringwald return x; 421d1207cd8SMilanka Ringwald } 4221f41c2c9SMatthias Ringwald 4231f41c2c9SMatthias Ringwald /* 4241f41c2c9SMatthias Ringwald * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 4251f41c2c9SMatthias Ringwald */ 4261f41c2c9SMatthias Ringwald 4271f41c2c9SMatthias Ringwald #define CRC8_INIT 0xFF // Initial FCS value 4281f41c2c9SMatthias Ringwald #define CRC8_OK 0xCF // Good final FCS value 4291f41c2c9SMatthias Ringwald 4301f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 4311f41c2c9SMatthias Ringwald 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 4321f41c2c9SMatthias Ringwald 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 4331f41c2c9SMatthias Ringwald 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 4341f41c2c9SMatthias Ringwald 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 4351f41c2c9SMatthias Ringwald 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 4361f41c2c9SMatthias Ringwald 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 4371f41c2c9SMatthias Ringwald 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 4381f41c2c9SMatthias Ringwald 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 4391f41c2c9SMatthias Ringwald 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 4401f41c2c9SMatthias Ringwald 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 4411f41c2c9SMatthias Ringwald 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 4421f41c2c9SMatthias Ringwald 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 4431f41c2c9SMatthias Ringwald 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 4441f41c2c9SMatthias Ringwald 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 4451f41c2c9SMatthias Ringwald 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 4461f41c2c9SMatthias Ringwald 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 4471f41c2c9SMatthias Ringwald }; 4481f41c2c9SMatthias Ringwald 4491f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 4501f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){ 4511f41c2c9SMatthias Ringwald uint16_t count; 4521f41c2c9SMatthias Ringwald uint8_t crc = CRC8_INIT; 4531f41c2c9SMatthias Ringwald for (count = 0; count < len; count++){ 4541f41c2c9SMatthias Ringwald crc = crc8table[crc ^ data[count]]; 4551f41c2c9SMatthias Ringwald } 4561f41c2c9SMatthias Ringwald return crc; 4571f41c2c9SMatthias Ringwald } 4581f41c2c9SMatthias Ringwald 4591f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 46063dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 4611f41c2c9SMatthias Ringwald uint8_t crc; 4621f41c2c9SMatthias Ringwald crc = crc8(data, len); 4631f41c2c9SMatthias Ringwald crc = crc8table[crc ^ check_sum]; 4641f41c2c9SMatthias Ringwald if (crc == CRC8_OK){ 4651f41c2c9SMatthias Ringwald return 0; /* Valid */ 4661f41c2c9SMatthias Ringwald } else { 4671f41c2c9SMatthias Ringwald return 1; /* Failed */ 4681f41c2c9SMatthias Ringwald } 4691f41c2c9SMatthias Ringwald } 4701f41c2c9SMatthias Ringwald 4711f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 47263dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 4731f41c2c9SMatthias Ringwald /* Ones complement */ 474*4ea43905SMatthias Ringwald return 0xFFu - crc8(data, len); 4751f41c2c9SMatthias Ringwald } 476