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 232cb42147aSMatthias Ringwald log_hexdump(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 241cb42147aSMatthias Ringwald log_hexdump(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 } 337a6efb919SMatthias Ringwald char separator = *addr_string++; 338a6efb919SMatthias Ringwald if (separator != ':' && separator != '-' && separator != ' ') break; 339a6efb919SMatthias Ringwald } 340a6efb919SMatthias Ringwald 341a6efb919SMatthias Ringwald if (result){ 342a6efb919SMatthias Ringwald bd_addr_copy(addr, buffer); 343a6efb919SMatthias Ringwald } 344a6efb919SMatthias Ringwald return result; 345eb886013SMatthias Ringwald } 3465d067ab1SMatthias Ringwald 3475d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char *str){ 3485d067ab1SMatthias Ringwald uint32_t val = 0; 3495d067ab1SMatthias Ringwald while (1){ 3505d067ab1SMatthias Ringwald char chr = *str; 3515d067ab1SMatthias Ringwald if (!chr || chr < '0' || chr > '9') 3525d067ab1SMatthias Ringwald return val; 353b0920f25SMilanka Ringwald val = (val * 10) + (uint8_t)(chr - '0'); 3545d067ab1SMatthias Ringwald str++; 3555d067ab1SMatthias Ringwald } 3565d067ab1SMatthias Ringwald } 357*1f41c2c9SMatthias Ringwald 358*1f41c2c9SMatthias Ringwald 359*1f41c2c9SMatthias Ringwald /* 360*1f41c2c9SMatthias Ringwald * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 361*1f41c2c9SMatthias Ringwald */ 362*1f41c2c9SMatthias Ringwald 363*1f41c2c9SMatthias Ringwald #define CRC8_INIT 0xFF // Initial FCS value 364*1f41c2c9SMatthias Ringwald #define CRC8_OK 0xCF // Good final FCS value 365*1f41c2c9SMatthias Ringwald 366*1f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 367*1f41c2c9SMatthias Ringwald 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 368*1f41c2c9SMatthias Ringwald 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 369*1f41c2c9SMatthias Ringwald 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 370*1f41c2c9SMatthias Ringwald 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 371*1f41c2c9SMatthias Ringwald 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 372*1f41c2c9SMatthias Ringwald 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 373*1f41c2c9SMatthias Ringwald 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 374*1f41c2c9SMatthias Ringwald 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 375*1f41c2c9SMatthias Ringwald 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 376*1f41c2c9SMatthias Ringwald 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 377*1f41c2c9SMatthias Ringwald 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 378*1f41c2c9SMatthias Ringwald 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 379*1f41c2c9SMatthias Ringwald 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 380*1f41c2c9SMatthias Ringwald 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 381*1f41c2c9SMatthias Ringwald 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 382*1f41c2c9SMatthias Ringwald 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 383*1f41c2c9SMatthias Ringwald }; 384*1f41c2c9SMatthias Ringwald 385*1f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 386*1f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){ 387*1f41c2c9SMatthias Ringwald uint16_t count; 388*1f41c2c9SMatthias Ringwald uint8_t crc = CRC8_INIT; 389*1f41c2c9SMatthias Ringwald for (count = 0; count < len; count++){ 390*1f41c2c9SMatthias Ringwald crc = crc8table[crc ^ data[count]]; 391*1f41c2c9SMatthias Ringwald } 392*1f41c2c9SMatthias Ringwald return crc; 393*1f41c2c9SMatthias Ringwald } 394*1f41c2c9SMatthias Ringwald 395*1f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 396*1f41c2c9SMatthias Ringwald uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 397*1f41c2c9SMatthias Ringwald uint8_t crc; 398*1f41c2c9SMatthias Ringwald crc = crc8(data, len); 399*1f41c2c9SMatthias Ringwald crc = crc8table[crc ^ check_sum]; 400*1f41c2c9SMatthias Ringwald if (crc == CRC8_OK){ 401*1f41c2c9SMatthias Ringwald return 0; /* Valid */ 402*1f41c2c9SMatthias Ringwald } else { 403*1f41c2c9SMatthias Ringwald return 1; /* Failed */ 404*1f41c2c9SMatthias Ringwald } 405*1f41c2c9SMatthias Ringwald } 406*1f41c2c9SMatthias Ringwald 407*1f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 408*1f41c2c9SMatthias Ringwald uint8_t crc8_calc(uint8_t *data, uint16_t len){ 409*1f41c2c9SMatthias Ringwald /* Ones complement */ 410*1f41c2c9SMatthias Ringwald return 0xFF - crc8(data, len); 411*1f41c2c9SMatthias Ringwald } 412