1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "btstack_util.c" 39 40 /* 41 * btstack_util.c 42 * 43 * General utility functions 44 * 45 * Created by Matthias Ringwald on 7/23/09. 46 */ 47 48 #include "btstack_config.h" 49 #include "btstack_debug.h" 50 #include "btstack_util.h" 51 52 #include <stdio.h> 53 #include <string.h> 54 55 /** 56 * @brief Compare two Bluetooth addresses 57 * @param a 58 * @param b 59 * @return 0 if equal 60 */ 61 int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){ 62 return memcmp(a,b, BD_ADDR_LEN); 63 } 64 65 /** 66 * @brief Copy Bluetooth address 67 * @param dest 68 * @param src 69 */ 70 void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){ 71 memcpy(dest,src,BD_ADDR_LEN); 72 } 73 74 uint16_t little_endian_read_16(const uint8_t * buffer, int pos){ 75 return (uint16_t)(((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8)); 76 } 77 uint32_t little_endian_read_24(const uint8_t * buffer, int pos){ 78 return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16); 79 } 80 uint32_t little_endian_read_32(const uint8_t * buffer, int pos){ 81 return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16) | (((uint32_t) buffer[(pos)+3]) << 24); 82 } 83 84 void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 85 buffer[pos++] = (uint8_t)value; 86 buffer[pos++] = (uint8_t)(value >> 8); 87 } 88 89 void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 90 buffer[pos++] = (uint8_t)(value); 91 buffer[pos++] = (uint8_t)(value >> 8); 92 buffer[pos++] = (uint8_t)(value >> 16); 93 buffer[pos++] = (uint8_t)(value >> 24); 94 } 95 96 uint32_t big_endian_read_16( const uint8_t * buffer, int pos) { 97 return (uint16_t)(((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos ]) << 8)); 98 } 99 100 uint32_t big_endian_read_24( const uint8_t * buffer, int pos) { 101 return ( ((uint32_t)buffer[(pos)+2]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t) buffer[pos]) << 16)); 102 } 103 104 uint32_t big_endian_read_32( const uint8_t * buffer, int pos) { 105 return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24); 106 } 107 108 void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 109 buffer[pos++] = (uint8_t)(value >> 8); 110 buffer[pos++] = (uint8_t)(value); 111 } 112 113 void big_endian_store_24(uint8_t *buffer, uint16_t pos, uint32_t value){ 114 buffer[pos++] = (uint8_t)(value >> 16); 115 buffer[pos++] = (uint8_t)(value >> 8); 116 buffer[pos++] = (uint8_t)(value); 117 } 118 119 void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 120 buffer[pos++] = (uint8_t)(value >> 24); 121 buffer[pos++] = (uint8_t)(value >> 16); 122 buffer[pos++] = (uint8_t)(value >> 8); 123 buffer[pos++] = (uint8_t)(value); 124 } 125 126 // general swap/endianess utils 127 void reverse_bytes(const uint8_t *src, uint8_t *dst, int len){ 128 int i; 129 for (i = 0; i < len; i++) 130 dst[len - 1 - i] = src[i]; 131 } 132 void reverse_24(const uint8_t * src, uint8_t * dst){ 133 reverse_bytes(src, dst, 3); 134 } 135 void reverse_48(const uint8_t * src, uint8_t * dst){ 136 reverse_bytes(src, dst, 6); 137 } 138 void reverse_56(const uint8_t * src, uint8_t * dst){ 139 reverse_bytes(src, dst, 7); 140 } 141 void reverse_64(const uint8_t * src, uint8_t * dst){ 142 reverse_bytes(src, dst, 8); 143 } 144 void reverse_128(const uint8_t * src, uint8_t * dst){ 145 reverse_bytes(src, dst, 16); 146 } 147 void reverse_256(const uint8_t * src, uint8_t * dst){ 148 reverse_bytes(src, dst, 32); 149 } 150 151 void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 152 reverse_bytes(src, dest, 6); 153 } 154 155 uint32_t btstack_min(uint32_t a, uint32_t b){ 156 return a < b ? a : b; 157 } 158 159 uint32_t btstack_max(uint32_t a, uint32_t b){ 160 return a > b ? a : b; 161 } 162 163 char char_for_nibble(int nibble){ 164 if (nibble < 10) return (char)('0' + nibble); 165 nibble -= 10; 166 if (nibble < 6) return (char)('A' + nibble); 167 return '?'; 168 } 169 170 static inline char char_for_high_nibble(int value){ 171 return char_for_nibble((value >> 4) & 0x0f); 172 } 173 174 static inline char char_for_low_nibble(int value){ 175 return char_for_nibble(value & 0x0f); 176 } 177 178 int nibble_for_char(char c){ 179 if (c >= '0' && c <= '9') return c - '0'; 180 if (c >= 'a' && c <= 'f') return c - 'a' + 10; 181 if (c >= 'A' && c <= 'F') return c - 'A' + 10; 182 return -1; 183 } 184 185 void printf_hexdump(const void *data, int size){ 186 if (size <= 0) return; 187 int i; 188 for (i=0; i<size;i++){ 189 printf("%02X ", ((uint8_t *)data)[i]); 190 } 191 printf("\n"); 192 } 193 194 #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 195 static void log_hexdump(int level, const void * data, int size){ 196 #define ITEMS_PER_LINE 16 197 // template '0x12, ' 198 #define BYTES_PER_BYTE 6 199 char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 200 int i, j; 201 j = 0; 202 for (i=0; i<size;i++){ 203 204 // help static analyzer proof that j stays within bounds 205 if (j > BYTES_PER_BYTE * (ITEMS_PER_LINE-1)){ 206 j = 0; 207 } 208 209 uint8_t byte = ((uint8_t *)data)[i]; 210 buffer[j++] = '0'; 211 buffer[j++] = 'x'; 212 buffer[j++] = char_for_high_nibble(byte); 213 buffer[j++] = char_for_low_nibble(byte); 214 buffer[j++] = ','; 215 buffer[j++] = ' '; 216 217 if (j >= BYTES_PER_BYTE * ITEMS_PER_LINE ){ 218 buffer[j] = 0; 219 HCI_DUMP_LOG(level, "%s", buffer); 220 j = 0; 221 } 222 } 223 if (j != 0){ 224 buffer[j] = 0; 225 HCI_DUMP_LOG(level, "%s", buffer); 226 } 227 } 228 #endif 229 230 void log_debug_hexdump(const void *data, int size){ 231 #ifdef ENABLE_LOG_DEBUG 232 log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 233 #else 234 UNUSED(data); // ok: no code 235 UNUSED(size); // ok: no code 236 #endif 237 } 238 239 void log_info_hexdump(const void *data, int size){ 240 #ifdef ENABLE_LOG_INFO 241 log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 242 #else 243 UNUSED(data); // ok: no code 244 UNUSED(size); // ok: no code 245 #endif 246 } 247 248 void log_info_key(const char * name, sm_key_t key){ 249 #ifdef ENABLE_LOG_INFO 250 char buffer[16*2+1]; 251 int i; 252 int j = 0; 253 for (i=0; i<16;i++){ 254 uint8_t byte = key[i]; 255 buffer[j++] = char_for_high_nibble(byte); 256 buffer[j++] = char_for_low_nibble(byte); 257 } 258 buffer[j] = 0; 259 log_info("%-6s %s", name, buffer); 260 #else 261 UNUSED(name); 262 (void)key; 263 #endif 264 } 265 266 // UUIDs are stored in big endian, similar to bd_addr_t 267 268 // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 269 const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 270 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 271 272 void uuid_add_bluetooth_prefix(uint8_t *uuid, uint32_t shortUUID){ 273 memcpy(uuid, bluetooth_base_uuid, 16); 274 big_endian_store_32(uuid, 0, shortUUID); 275 } 276 277 int uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 278 return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 279 } 280 281 static char uuid128_to_str_buffer[32+4+1]; 282 char * uuid128_to_str(const uint8_t * uuid){ 283 int i; 284 int j = 0; 285 // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 286 const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 287 for (i=0;i<16;i++){ 288 uint8_t byte = uuid[i]; 289 uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 290 uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 291 if (dash_locations & (1<<i)){ 292 uuid128_to_str_buffer[j++] = '-'; 293 } 294 } 295 return uuid128_to_str_buffer; 296 } 297 298 static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 299 char * bd_addr_to_str(const bd_addr_t addr){ 300 // orig code 301 // sprintf(bd_addr_to_str_buffer, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 302 // sprintf-free code 303 char * p = bd_addr_to_str_buffer; 304 int i; 305 for (i = 0; i < 6 ; i++) { 306 uint8_t byte = addr[i]; 307 *p++ = char_for_high_nibble(byte); 308 *p++ = char_for_low_nibble(byte); 309 *p++ = ':'; 310 } 311 *--p = 0; 312 return (char *) bd_addr_to_str_buffer; 313 } 314 315 static int scan_hex_byte(const char * byte_string){ 316 int upper_nibble = nibble_for_char(*byte_string++); 317 if (upper_nibble < 0) return -1; 318 int lower_nibble = nibble_for_char(*byte_string); 319 if (lower_nibble < 0) return -1; 320 return (upper_nibble << 4) | lower_nibble; 321 } 322 323 int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 324 uint8_t buffer[BD_ADDR_LEN]; 325 int result = 0; 326 int i; 327 for (i = 0; i < BD_ADDR_LEN; i++) { 328 int single_byte = scan_hex_byte(addr_string); 329 if (single_byte < 0) break; 330 addr_string += 2; 331 buffer[i] = (uint8_t)single_byte; 332 // don't check seperator after last byte 333 if (i == BD_ADDR_LEN - 1) { 334 result = 1; 335 break; 336 } 337 // skip supported separators 338 char next_char = *addr_string; 339 if (next_char == ':' || next_char == '-' || next_char == ' ') { 340 addr_string++; 341 } 342 } 343 344 if (result){ 345 bd_addr_copy(addr, buffer); 346 } 347 return result; 348 } 349 350 uint32_t btstack_atoi(const char *str){ 351 uint32_t val = 0; 352 while (1){ 353 char chr = *str; 354 if (!chr || chr < '0' || chr > '9') 355 return val; 356 val = (val * 10) + (uint8_t)(chr - '0'); 357 str++; 358 } 359 } 360 361 int string_len_for_uint32(uint32_t i){ 362 if (i < 10) return 1; 363 if (i < 100) return 2; 364 if (i < 1000) return 3; 365 if (i < 10000) return 4; 366 if (i < 100000) return 5; 367 if (i < 1000000) return 6; 368 if (i < 10000000) return 7; 369 if (i < 100000000) return 8; 370 if (i < 1000000000) return 9; 371 return 10; 372 } 373 374 int count_set_bits_uint32(uint32_t x){ 375 x = (x & 0x55555555) + ((x >> 1) & 0x55555555); 376 x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 377 x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); 378 x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); 379 x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); 380 return x; 381 } 382 383 /* 384 * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 385 */ 386 387 #define CRC8_INIT 0xFF // Initial FCS value 388 #define CRC8_OK 0xCF // Good final FCS value 389 390 static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 391 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 392 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 393 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 394 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 395 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 396 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 397 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 398 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 399 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 400 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 401 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 402 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 403 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 404 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 405 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 406 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 407 }; 408 409 /*-----------------------------------------------------------------------------------*/ 410 static uint8_t crc8(uint8_t *data, uint16_t len){ 411 uint16_t count; 412 uint8_t crc = CRC8_INIT; 413 for (count = 0; count < len; count++){ 414 crc = crc8table[crc ^ data[count]]; 415 } 416 return crc; 417 } 418 419 /*-----------------------------------------------------------------------------------*/ 420 uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 421 uint8_t crc; 422 crc = crc8(data, len); 423 crc = crc8table[crc ^ check_sum]; 424 if (crc == CRC8_OK){ 425 return 0; /* Valid */ 426 } else { 427 return 1; /* Failed */ 428 } 429 } 430 431 /*-----------------------------------------------------------------------------------*/ 432 uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 433 /* Ones complement */ 434 return 0xFF - crc8(data, len); 435 } 436