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 38ab2c6ae4SMatthias 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){ 7173988a59SMatthias Ringwald 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 89f8fbdce0SMatthias Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 90b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 91b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 92b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 93b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 94eb886013SMatthias Ringwald } 95eb886013SMatthias Ringwald 9673988a59SMatthias Ringwald uint32_t big_endian_read_16( const uint8_t * buffer, int pos) { 97b0920f25SMilanka Ringwald return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos ]) << 8)); 9873988a59SMatthias Ringwald } 9973988a59SMatthias Ringwald 100e57a2545SMilanka Ringwald uint32_t big_endian_read_24( const uint8_t * buffer, int pos) { 101e57a2545SMilanka Ringwald return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16)); 102e57a2545SMilanka Ringwald } 103e57a2545SMilanka Ringwald 10473988a59SMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) { 10573988a59SMatthias Ringwald return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24); 10673988a59SMatthias Ringwald } 10773988a59SMatthias Ringwald 108f8fbdce0SMatthias Ringwald void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 109b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 110b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 111eb886013SMatthias Ringwald } 112eb886013SMatthias Ringwald 1137f535380SMilanka Ringwald void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){ 114b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 115b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 116b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 1177f535380SMilanka Ringwald } 1187f535380SMilanka Ringwald 119f8fbdce0SMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 120b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 121b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 122b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 123b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 124eb886013SMatthias Ringwald } 125eb886013SMatthias Ringwald 126eb886013SMatthias Ringwald // general swap/endianess utils 1279c80e4ccSMatthias Ringwald void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){ 128eb886013SMatthias Ringwald int i; 129eb886013SMatthias Ringwald for (i = 0; i < len; i++) 130eb886013SMatthias Ringwald dst[len - 1 - i] = src[i]; 131eb886013SMatthias Ringwald } 1329c80e4ccSMatthias Ringwald void reverse_24(const uint8_t * src, uint8_t * dst){ 1339c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 3); 134eb886013SMatthias Ringwald } 1359c80e4ccSMatthias Ringwald void reverse_48(const uint8_t * src, uint8_t * dst){ 1369c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 6); 137bf1b35bfSMatthias Ringwald } 1389c80e4ccSMatthias Ringwald void reverse_56(const uint8_t * src, uint8_t * dst){ 1399c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 7); 140eb886013SMatthias Ringwald } 1419c80e4ccSMatthias Ringwald void reverse_64(const uint8_t * src, uint8_t * dst){ 1429c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 8); 143eb886013SMatthias Ringwald } 1449c80e4ccSMatthias Ringwald void reverse_128(const uint8_t * src, uint8_t * dst){ 1459c80e4ccSMatthias Ringwald reverse_bytes(src, dst, 16); 146eb886013SMatthias Ringwald } 147cc7a2d78SMatthias Ringwald void reverse_256(const uint8_t * src, uint8_t * dst){ 148cc7a2d78SMatthias Ringwald reverse_bytes(src, dst, 32); 149cc7a2d78SMatthias Ringwald } 150eb886013SMatthias Ringwald 151724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 152724d70a2SMatthias Ringwald reverse_bytes(src, dest, 6); 153724d70a2SMatthias Ringwald } 154724d70a2SMatthias Ringwald 155ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){ 156ebaeb1beSMatthias Ringwald return a < b ? a : b; 157ebaeb1beSMatthias Ringwald } 158ebaeb1beSMatthias Ringwald 159ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){ 160ebaeb1beSMatthias Ringwald return a > b ? a : b; 161ebaeb1beSMatthias Ringwald } 162ebaeb1beSMatthias Ringwald 163eb886013SMatthias Ringwald char char_for_nibble(int nibble){ 164b0920f25SMilanka Ringwald if (nibble < 10) return (char)('0' + nibble); 165eb886013SMatthias Ringwald nibble -= 10; 166b0920f25SMilanka Ringwald if (nibble < 6) return (char)('A' + nibble); 167eb886013SMatthias Ringwald return '?'; 168eb886013SMatthias Ringwald } 169eb886013SMatthias Ringwald 170405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){ 171405d63a9SMatthias Ringwald return char_for_nibble((value >> 4) & 0x0f); 172405d63a9SMatthias Ringwald } 173405d63a9SMatthias Ringwald 174405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){ 175405d63a9SMatthias Ringwald return char_for_nibble(value & 0x0f); 176405d63a9SMatthias Ringwald } 177405d63a9SMatthias Ringwald 178a6efb919SMatthias Ringwald int nibble_for_char(char c){ 179a6efb919SMatthias Ringwald if (c >= '0' && c <= '9') return c - '0'; 1809f507070SMatthias Ringwald if (c >= 'a' && c <= 'f') return c - 'a' + 10; 1819f507070SMatthias Ringwald if (c >= 'A' && c <= 'F') return c - 'A' + 10; 182a6efb919SMatthias Ringwald return -1; 183a6efb919SMatthias Ringwald } 184a6efb919SMatthias Ringwald 185eb886013SMatthias Ringwald void printf_hexdump(const void *data, int size){ 186eb886013SMatthias Ringwald if (size <= 0) return; 187eb886013SMatthias Ringwald int i; 188eb886013SMatthias Ringwald for (i=0; i<size;i++){ 189eb886013SMatthias Ringwald printf("%02X ", ((uint8_t *)data)[i]); 190eb886013SMatthias Ringwald } 191eb886013SMatthias Ringwald printf("\n"); 192eb886013SMatthias Ringwald } 193eb886013SMatthias Ringwald 194cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 195cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){ 196405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16 197405d63a9SMatthias Ringwald // template '0x12, ' 198405d63a9SMatthias Ringwald #define BYTES_PER_BYTE 6 199405d63a9SMatthias Ringwald char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 2007224be7eSMatthias Ringwald int i, j; 201eb886013SMatthias Ringwald j = 0; 202eb886013SMatthias Ringwald for (i=0; i<size;i++){ 2037224be7eSMatthias Ringwald 2047224be7eSMatthias Ringwald // help static analyzer proof that j stays within bounds 205405d63a9SMatthias Ringwald if (j > BYTES_PER_BYTE * (ITEMS_PER_LINE-1)){ 2067224be7eSMatthias Ringwald j = 0; 2077224be7eSMatthias Ringwald } 2087224be7eSMatthias Ringwald 209eb886013SMatthias Ringwald uint8_t byte = ((uint8_t *)data)[i]; 210eb886013SMatthias Ringwald buffer[j++] = '0'; 211eb886013SMatthias Ringwald buffer[j++] = 'x'; 212405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 213405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 214eb886013SMatthias Ringwald buffer[j++] = ','; 215eb886013SMatthias Ringwald buffer[j++] = ' '; 2167224be7eSMatthias Ringwald 217405d63a9SMatthias Ringwald if (j >= BYTES_PER_BYTE * ITEMS_PER_LINE ){ 218eb886013SMatthias Ringwald buffer[j] = 0; 219cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 220eb886013SMatthias Ringwald j = 0; 221eb886013SMatthias Ringwald } 222eb886013SMatthias Ringwald } 223eb886013SMatthias Ringwald if (j != 0){ 224eb886013SMatthias Ringwald buffer[j] = 0; 225cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 226eb886013SMatthias Ringwald } 227cb42147aSMatthias Ringwald } 228cb42147aSMatthias Ringwald #endif 229cb42147aSMatthias Ringwald 230cb42147aSMatthias Ringwald void log_debug_hexdump(const void *data, int size){ 231e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG 232fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 233cb42147aSMatthias Ringwald #else 2344bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2354bd79111SMatthias Ringwald UNUSED(size); // ok: no code 236cb42147aSMatthias Ringwald #endif 237cb42147aSMatthias Ringwald } 238cb42147aSMatthias Ringwald 239cb42147aSMatthias Ringwald void log_info_hexdump(const void *data, int size){ 240cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO 241fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 242d0662982SMatthias Ringwald #else 2434bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2444bd79111SMatthias Ringwald UNUSED(size); // ok: no code 2458314c363SMatthias Ringwald #endif 2467299c0feSMatthias Ringwald } 247eb886013SMatthias Ringwald 2488314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){ 24902bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO 25002bdfbf8SMatthias Ringwald char buffer[16*2+1]; 25102bdfbf8SMatthias Ringwald int i; 25202bdfbf8SMatthias Ringwald int j = 0; 25302bdfbf8SMatthias Ringwald for (i=0; i<16;i++){ 25402bdfbf8SMatthias Ringwald uint8_t byte = key[i]; 255405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 256405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 25702bdfbf8SMatthias Ringwald } 25802bdfbf8SMatthias Ringwald buffer[j] = 0; 25902bdfbf8SMatthias Ringwald log_info("%-6s %s", name, buffer); 260d0662982SMatthias Ringwald #else 261d0662982SMatthias Ringwald UNUSED(name); 262cb42147aSMatthias Ringwald (void)key; 26302bdfbf8SMatthias Ringwald #endif 264eb886013SMatthias Ringwald } 265eb886013SMatthias Ringwald 2662b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t 2672b604902SMatthias Ringwald 268eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 2692b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 270eb886013SMatthias Ringwald 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 271eb886013SMatthias Ringwald 272e1a125dfSMatthias Ringwald void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){ 2732b604902SMatthias Ringwald memcpy(uuid, bluetooth_base_uuid, 16); 274f8fbdce0SMatthias Ringwald big_endian_store_32(uuid, 0, shortUUID); 275eb886013SMatthias Ringwald } 276eb886013SMatthias Ringwald 2775222912bSMatthias Ringwald int uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 2782b604902SMatthias Ringwald return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 279eb886013SMatthias Ringwald } 280eb886013SMatthias Ringwald 281eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1]; 2825222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){ 2837224be7eSMatthias Ringwald int i; 2847224be7eSMatthias Ringwald int j = 0; 2857224be7eSMatthias Ringwald // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 2867224be7eSMatthias Ringwald const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 2877224be7eSMatthias Ringwald for (i=0;i<16;i++){ 288405d63a9SMatthias Ringwald uint8_t byte = uuid[i]; 289405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 290405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 2917224be7eSMatthias Ringwald if (dash_locations & (1<<i)){ 2927224be7eSMatthias Ringwald uuid128_to_str_buffer[j++] = '-'; 2937224be7eSMatthias Ringwald } 2947224be7eSMatthias Ringwald } 295eb886013SMatthias Ringwald return uuid128_to_str_buffer; 296eb886013SMatthias Ringwald } 297eb886013SMatthias Ringwald 298eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 2995222912bSMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){ 300eb886013SMatthias Ringwald // orig code 301eb886013SMatthias 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]); 302eb886013SMatthias Ringwald // sprintf-free code 303eb886013SMatthias Ringwald char * p = bd_addr_to_str_buffer; 304eb886013SMatthias Ringwald int i; 305eb886013SMatthias Ringwald for (i = 0; i < 6 ; i++) { 306405d63a9SMatthias Ringwald uint8_t byte = addr[i]; 307405d63a9SMatthias Ringwald *p++ = char_for_high_nibble(byte); 308405d63a9SMatthias Ringwald *p++ = char_for_low_nibble(byte); 309eb886013SMatthias Ringwald *p++ = ':'; 310eb886013SMatthias Ringwald } 311eb886013SMatthias Ringwald *--p = 0; 312eb886013SMatthias Ringwald return (char *) bd_addr_to_str_buffer; 313eb886013SMatthias Ringwald } 314eb886013SMatthias Ringwald 315a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 316a6efb919SMatthias Ringwald int upper_nibble = nibble_for_char(*byte_string++); 317a6efb919SMatthias Ringwald if (upper_nibble < 0) return -1; 318a6efb919SMatthias Ringwald int lower_nibble = nibble_for_char(*byte_string); 319a6efb919SMatthias Ringwald if (lower_nibble < 0) return -1; 320a6efb919SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 321a6efb919SMatthias Ringwald } 322eb886013SMatthias Ringwald 323a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 324a6efb919SMatthias Ringwald uint8_t buffer[BD_ADDR_LEN]; 325a6efb919SMatthias Ringwald int result = 0; 326eb886013SMatthias Ringwald int i; 327eb886013SMatthias Ringwald for (i = 0; i < BD_ADDR_LEN; i++) { 328a6efb919SMatthias Ringwald int single_byte = scan_hex_byte(addr_string); 329a6efb919SMatthias Ringwald if (single_byte < 0) break; 330a6efb919SMatthias Ringwald addr_string += 2; 331b0920f25SMilanka Ringwald buffer[i] = (uint8_t)single_byte; 332a6efb919SMatthias Ringwald // don't check seperator after last byte 333a6efb919SMatthias Ringwald if (i == BD_ADDR_LEN - 1) { 334a6efb919SMatthias Ringwald result = 1; 335a6efb919SMatthias Ringwald break; 336eb886013SMatthias Ringwald } 337*cd2e416cSMatthias Ringwald // skip supported separators 338*cd2e416cSMatthias Ringwald char next_char = *addr_string; 339*cd2e416cSMatthias Ringwald if (next_char == ':' || next_char == '-' || next_char == ' ') { 340*cd2e416cSMatthias Ringwald addr_string++; 341*cd2e416cSMatthias Ringwald } 342a6efb919SMatthias Ringwald } 343a6efb919SMatthias Ringwald 344a6efb919SMatthias Ringwald if (result){ 345a6efb919SMatthias Ringwald bd_addr_copy(addr, buffer); 346a6efb919SMatthias Ringwald } 347a6efb919SMatthias Ringwald return result; 348eb886013SMatthias Ringwald } 3495d067ab1SMatthias Ringwald 3505d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){ 3515d067ab1SMatthias Ringwald uint32_t val = 0; 3525d067ab1SMatthias Ringwald while (1){ 3535d067ab1SMatthias Ringwald char chr = *str; 3545d067ab1SMatthias Ringwald if (!chr || chr < '0' || chr > '9') 3555d067ab1SMatthias Ringwald return val; 356b0920f25SMilanka Ringwald val = (val * 10) + (uint8_t)(chr - '0'); 3575d067ab1SMatthias Ringwald str++; 3585d067ab1SMatthias Ringwald } 3595d067ab1SMatthias Ringwald } 3601f41c2c9SMatthias Ringwald 361d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){ 362d1207cd8SMilanka Ringwald if (i < 10) return 1; 363d1207cd8SMilanka Ringwald if (i < 100) return 2; 364d1207cd8SMilanka Ringwald if (i < 1000) return 3; 365d1207cd8SMilanka Ringwald if (i < 10000) return 4; 366d1207cd8SMilanka Ringwald if (i < 100000) return 5; 367d1207cd8SMilanka Ringwald if (i < 1000000) return 6; 368d1207cd8SMilanka Ringwald if (i < 10000000) return 7; 369d1207cd8SMilanka Ringwald if (i < 100000000) return 8; 370d1207cd8SMilanka Ringwald if (i < 1000000000) return 9; 371d1207cd8SMilanka Ringwald return 10; 372d1207cd8SMilanka Ringwald } 373d1207cd8SMilanka Ringwald 374d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){ 375d1207cd8SMilanka Ringwald x = (x & 0x55555555) + ((x >> 1) & 0x55555555); 376d1207cd8SMilanka Ringwald x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 377d1207cd8SMilanka Ringwald x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); 378d1207cd8SMilanka Ringwald x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); 379d1207cd8SMilanka Ringwald x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); 380d1207cd8SMilanka Ringwald return x; 381d1207cd8SMilanka Ringwald } 3821f41c2c9SMatthias Ringwald 3831f41c2c9SMatthias Ringwald /* 3841f41c2c9SMatthias Ringwald * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 3851f41c2c9SMatthias Ringwald */ 3861f41c2c9SMatthias Ringwald 3871f41c2c9SMatthias Ringwald #define CRC8_INIT 0xFF // Initial FCS value 3881f41c2c9SMatthias Ringwald #define CRC8_OK 0xCF // Good final FCS value 3891f41c2c9SMatthias Ringwald 3901f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 3911f41c2c9SMatthias Ringwald 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 3921f41c2c9SMatthias Ringwald 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 3931f41c2c9SMatthias Ringwald 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 3941f41c2c9SMatthias Ringwald 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 3951f41c2c9SMatthias Ringwald 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 3961f41c2c9SMatthias Ringwald 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 3971f41c2c9SMatthias Ringwald 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 3981f41c2c9SMatthias Ringwald 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 3991f41c2c9SMatthias Ringwald 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 4001f41c2c9SMatthias Ringwald 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 4011f41c2c9SMatthias Ringwald 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 4021f41c2c9SMatthias Ringwald 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 4031f41c2c9SMatthias Ringwald 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 4041f41c2c9SMatthias Ringwald 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 4051f41c2c9SMatthias Ringwald 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 4061f41c2c9SMatthias Ringwald 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 4071f41c2c9SMatthias Ringwald }; 4081f41c2c9SMatthias Ringwald 4091f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 4101f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){ 4111f41c2c9SMatthias Ringwald uint16_t count; 4121f41c2c9SMatthias Ringwald uint8_t crc = CRC8_INIT; 4131f41c2c9SMatthias Ringwald for (count = 0; count < len; count++){ 4141f41c2c9SMatthias Ringwald crc = crc8table[crc ^ data[count]]; 4151f41c2c9SMatthias Ringwald } 4161f41c2c9SMatthias Ringwald return crc; 4171f41c2c9SMatthias Ringwald } 4181f41c2c9SMatthias Ringwald 4191f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 42063dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 4211f41c2c9SMatthias Ringwald uint8_t crc; 4221f41c2c9SMatthias Ringwald crc = crc8(data, len); 4231f41c2c9SMatthias Ringwald crc = crc8table[crc ^ check_sum]; 4241f41c2c9SMatthias Ringwald if (crc == CRC8_OK){ 4251f41c2c9SMatthias Ringwald return 0; /* Valid */ 4261f41c2c9SMatthias Ringwald } else { 4271f41c2c9SMatthias Ringwald return 1; /* Failed */ 4281f41c2c9SMatthias Ringwald } 4291f41c2c9SMatthias Ringwald } 4301f41c2c9SMatthias Ringwald 4311f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 43263dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 4331f41c2c9SMatthias Ringwald /* Ones complement */ 4341f41c2c9SMatthias Ringwald return 0xFF - crc8(data, len); 4351f41c2c9SMatthias Ringwald } 436