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 BLUEKITCHEN 24 * GMBH 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 * General utility functions 42 */ 43 44 #include "btstack_config.h" 45 #include "btstack_debug.h" 46 #include "btstack_util.h" 47 48 #ifdef _MSC_VER 49 #include <intrin.h> 50 #include <windows.h> 51 #endif 52 53 #ifdef ENABLE_PRINTF_HEXDUMP 54 #include <stdio.h> 55 #endif 56 57 #include <string.h> 58 59 /** 60 * @brief Compare two Bluetooth addresses 61 * @param a 62 * @param b 63 * @return 0 if equal 64 */ 65 int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){ 66 return memcmp(a,b, BD_ADDR_LEN); 67 } 68 69 /** 70 * @brief Copy Bluetooth address 71 * @param dest 72 * @param src 73 */ 74 void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){ 75 (void)memcpy(dest, src, BD_ADDR_LEN); 76 } 77 78 uint16_t little_endian_read_16(const uint8_t * buffer, int position){ 79 return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8)); 80 } 81 uint32_t little_endian_read_24(const uint8_t * buffer, int position){ 82 return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16); 83 } 84 uint32_t little_endian_read_32(const uint8_t * buffer, int position){ 85 return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24); 86 } 87 88 void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 89 uint16_t pos = position; 90 buffer[pos++] = (uint8_t)value; 91 buffer[pos++] = (uint8_t)(value >> 8); 92 } 93 94 void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 95 uint16_t pos = position; 96 buffer[pos++] = (uint8_t)(value); 97 buffer[pos++] = (uint8_t)(value >> 8); 98 buffer[pos++] = (uint8_t)(value >> 16); 99 } 100 101 void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 102 uint16_t pos = position; 103 buffer[pos++] = (uint8_t)(value); 104 buffer[pos++] = (uint8_t)(value >> 8); 105 buffer[pos++] = (uint8_t)(value >> 16); 106 buffer[pos++] = (uint8_t)(value >> 24); 107 } 108 109 uint32_t big_endian_read_16(const uint8_t * buffer, int position) { 110 return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8)); 111 } 112 113 uint32_t big_endian_read_24(const uint8_t * buffer, int position) { 114 return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16)); 115 } 116 117 uint32_t big_endian_read_32(const uint8_t * buffer, int position) { 118 return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24); 119 } 120 121 void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 122 uint16_t pos = position; 123 buffer[pos++] = (uint8_t)(value >> 8); 124 buffer[pos++] = (uint8_t)(value); 125 } 126 127 void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 128 uint16_t pos = position; 129 buffer[pos++] = (uint8_t)(value >> 16); 130 buffer[pos++] = (uint8_t)(value >> 8); 131 buffer[pos++] = (uint8_t)(value); 132 } 133 134 void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 135 uint16_t pos = position; 136 buffer[pos++] = (uint8_t)(value >> 24); 137 buffer[pos++] = (uint8_t)(value >> 16); 138 buffer[pos++] = (uint8_t)(value >> 8); 139 buffer[pos++] = (uint8_t)(value); 140 } 141 142 // general swap/endianess utils 143 void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){ 144 int i; 145 for (i = 0; i < len; i++) 146 dest[len - 1 - i] = src[i]; 147 } 148 void reverse_24(const uint8_t * src, uint8_t * dest){ 149 reverse_bytes(src, dest, 3); 150 } 151 void reverse_48(const uint8_t * src, uint8_t * dest){ 152 reverse_bytes(src, dest, 6); 153 } 154 void reverse_56(const uint8_t * src, uint8_t * dest){ 155 reverse_bytes(src, dest, 7); 156 } 157 void reverse_64(const uint8_t * src, uint8_t * dest){ 158 reverse_bytes(src, dest, 8); 159 } 160 void reverse_128(const uint8_t * src, uint8_t * dest){ 161 reverse_bytes(src, dest, 16); 162 } 163 void reverse_256(const uint8_t * src, uint8_t * dest){ 164 reverse_bytes(src, dest, 32); 165 } 166 167 void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 168 reverse_bytes(src, dest, 6); 169 } 170 171 bool btstack_is_null(const uint8_t * buffer, uint16_t size){ 172 uint16_t i; 173 for (i=0; i < size ; i++){ 174 if (buffer[i] != 0) { 175 return false; 176 } 177 } 178 return true; 179 } 180 181 bool btstack_is_null_bd_addr( const bd_addr_t addr ){ 182 return btstack_is_null( addr, sizeof(bd_addr_t) ); 183 } 184 185 uint32_t btstack_min(uint32_t a, uint32_t b){ 186 return (a < b) ? a : b; 187 } 188 189 uint32_t btstack_max(uint32_t a, uint32_t b){ 190 return (a > b) ? a : b; 191 } 192 193 /** 194 * @brief Calculate delta between two uint32_t points in time 195 * @return time_a - time_b - result > 0 if time_a is newer than time_b 196 */ 197 int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){ 198 return (int32_t)(time_a - time_b); 199 } 200 201 /** 202 * @brief Calculate delta between two uint16_t points in time 203 * @return time_a - time_b - result > 0 if time_a is newer than time_b 204 */ 205 int16_t btstack_time16_delta(uint16_t time_a, uint16_t time_b){ 206 return (int16_t)(time_a - time_b); 207 } 208 209 char char_for_nibble(int nibble){ 210 211 static const char * char_to_nibble = "0123456789ABCDEF"; 212 213 if (nibble < 16){ 214 return char_to_nibble[nibble]; 215 } else { 216 return '?'; 217 } 218 } 219 220 static inline char char_for_high_nibble(int value){ 221 return char_for_nibble((value >> 4) & 0x0f); 222 } 223 224 static inline char char_for_low_nibble(int value){ 225 return char_for_nibble(value & 0x0f); 226 } 227 228 229 int nibble_for_char(char c){ 230 if ((c >= '0') && (c <= '9')) return c - '0'; 231 if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; 232 if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; 233 return -1; 234 } 235 236 #ifdef ENABLE_PRINTF_HEXDUMP 237 void printf_hexdump(const void * data, int size){ 238 char buffer[4]; 239 buffer[2] = ' '; 240 buffer[3] = 0; 241 const uint8_t * ptr = (const uint8_t *) data; 242 while (size > 0){ 243 uint8_t byte = *ptr++; 244 buffer[0] = char_for_high_nibble(byte); 245 buffer[1] = char_for_low_nibble(byte); 246 printf("%s", buffer); 247 size--; 248 } 249 printf("\n"); 250 } 251 #endif 252 253 #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 254 static void log_hexdump(int level, const void * data, int size){ 255 #define ITEMS_PER_LINE 16 256 // template '0x12, ' 257 #define BYTES_PER_BYTE 6 258 char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 259 int i, j; 260 j = 0; 261 for (i=0; i<size;i++){ 262 263 // help static analyzer proof that j stays within bounds 264 if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){ 265 j = 0; 266 } 267 268 uint8_t byte = ((uint8_t *)data)[i]; 269 buffer[j++] = '0'; 270 buffer[j++] = 'x'; 271 buffer[j++] = char_for_high_nibble(byte); 272 buffer[j++] = char_for_low_nibble(byte); 273 buffer[j++] = ','; 274 buffer[j++] = ' '; 275 276 if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){ 277 buffer[j] = 0; 278 HCI_DUMP_LOG(level, "%s", buffer); 279 j = 0; 280 } 281 } 282 if (j != 0){ 283 buffer[j] = 0; 284 HCI_DUMP_LOG(level, "%s", buffer); 285 } 286 } 287 #endif 288 289 void log_debug_hexdump(const void * data, int size){ 290 #ifdef ENABLE_LOG_DEBUG 291 log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 292 #else 293 UNUSED(data); // ok: no code 294 UNUSED(size); // ok: no code 295 #endif 296 } 297 298 void log_info_hexdump(const void * data, int size){ 299 #ifdef ENABLE_LOG_INFO 300 log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 301 #else 302 UNUSED(data); // ok: no code 303 UNUSED(size); // ok: no code 304 #endif 305 } 306 307 void log_info_key(const char * name, sm_key_t key){ 308 #ifdef ENABLE_LOG_INFO 309 char buffer[16*2+1]; 310 int i; 311 int j = 0; 312 for (i=0; i<16;i++){ 313 uint8_t byte = key[i]; 314 buffer[j++] = char_for_high_nibble(byte); 315 buffer[j++] = char_for_low_nibble(byte); 316 } 317 buffer[j] = 0; 318 log_info("%-6s %s", name, buffer); 319 #else 320 UNUSED(name); 321 (void)key; 322 #endif 323 } 324 325 // UUIDs are stored in big endian, similar to bd_addr_t 326 327 // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 328 const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 329 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 330 331 void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid){ 332 (void)memcpy(uuid128, bluetooth_base_uuid, 16); 333 big_endian_store_32(uuid128, 0, short_uuid); 334 } 335 336 int uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 337 return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 338 } 339 340 static char uuid128_to_str_buffer[32+4+1]; 341 char * uuid128_to_str(const uint8_t * uuid){ 342 int i; 343 int j = 0; 344 // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 345 const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 346 for (i=0;i<16;i++){ 347 uint8_t byte = uuid[i]; 348 uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 349 uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 350 if (dash_locations & (1<<i)){ 351 uuid128_to_str_buffer[j++] = '-'; 352 } 353 } 354 return uuid128_to_str_buffer; 355 } 356 357 static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 358 char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter){ 359 char * p = bd_addr_to_str_buffer; 360 int i; 361 for (i = 0; i < 6 ; i++) { 362 uint8_t byte = addr[i]; 363 *p++ = char_for_high_nibble(byte); 364 *p++ = char_for_low_nibble(byte); 365 *p++ = delimiter; 366 } 367 *--p = 0; 368 return (char *) bd_addr_to_str_buffer; 369 } 370 371 char * bd_addr_to_str(const bd_addr_t addr){ 372 return bd_addr_to_str_with_delimiter(addr, ':'); 373 } 374 375 void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){ 376 const int bd_addr_string_len = 17; 377 uint16_t i = 0; 378 while ((i + bd_addr_string_len) <= size){ 379 if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) { 380 i++; 381 continue; 382 } 383 // set address 384 (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len); 385 i += bd_addr_string_len; 386 } 387 } 388 389 static int scan_hex_byte(const char * byte_string){ 390 int upper_nibble = nibble_for_char(byte_string[0]); 391 if (upper_nibble < 0) return -1; 392 int lower_nibble = nibble_for_char(byte_string[1]); 393 if (lower_nibble < 0) return -1; 394 return (upper_nibble << 4) | lower_nibble; 395 } 396 397 int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 398 const char * the_string = addr_string; 399 uint8_t buffer[BD_ADDR_LEN]; 400 int result = 0; 401 int i; 402 for (i = 0; i < BD_ADDR_LEN; i++) { 403 int single_byte = scan_hex_byte(the_string); 404 if (single_byte < 0) break; 405 the_string += 2; 406 buffer[i] = (uint8_t)single_byte; 407 // don't check separator after last byte 408 if (i == (BD_ADDR_LEN - 1)) { 409 result = 1; 410 break; 411 } 412 // skip supported separators 413 char next_char = *the_string; 414 if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) { 415 the_string++; 416 } 417 } 418 419 if (result != 0){ 420 bd_addr_copy(addr, buffer); 421 } 422 return result; 423 } 424 425 uint32_t btstack_atoi(const char * str){ 426 const char * the_string = str; 427 uint32_t val = 0; 428 while (true){ 429 char chr = *the_string++; 430 if (!chr || (chr < '0') || (chr > '9')) 431 return val; 432 val = (val * 10u) + (uint8_t)(chr - '0'); 433 } 434 } 435 436 int string_len_for_uint32(uint32_t i){ 437 if (i < 10) return 1; 438 if (i < 100) return 2; 439 if (i < 1000) return 3; 440 if (i < 10000) return 4; 441 if (i < 100000) return 5; 442 if (i < 1000000) return 6; 443 if (i < 10000000) return 7; 444 if (i < 100000000) return 8; 445 if (i < 1000000000) return 9; 446 return 10; 447 } 448 449 int count_set_bits_uint32(uint32_t x){ 450 uint32_t v = x; 451 v = (v & 0x55555555) + ((v >> 1) & 0x55555555U); 452 v = (v & 0x33333333) + ((v >> 2) & 0x33333333U); 453 v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0FU); 454 v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FFU); 455 v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU); 456 return v; 457 } 458 459 uint8_t btstack_clz(uint32_t value) { 460 #if defined(__GNUC__) || defined (__clang__) 461 // use gcc/clang intrinsic 462 return (uint8_t) __builtin_clz(value); 463 #elif defined(_MSC_VER) 464 // use MSVC intrinsic 465 DWORD leading_zero = 0; 466 if (_BitScanReverse( &leading_zero, value )){ 467 return (uint8_t)(31 - leading_zero); 468 } else { 469 return 32; 470 } 471 #else 472 // divide-and-conquer implementation for 32-bit integers 473 uint32_t x = value; 474 if (x == 0) return 32; 475 uint8_t r = 0; 476 if ((x & 0xffff0000u) == 0) { 477 x <<= 16; 478 r += 16; 479 } 480 if ((x & 0xff000000u) == 0) { 481 x <<= 8; 482 r += 8; 483 } 484 if ((x & 0xf0000000u) == 0) { 485 x <<= 4; 486 r += 4; 487 } 488 if ((x & 0xc0000000u) == 0) { 489 x <<= 2; 490 r += 2; 491 } 492 if ((x & 0x80000000u) == 0) { 493 x <<= 1; 494 r += 1; 495 } 496 return r; 497 #endif 498 } 499 500 /* 501 * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 502 */ 503 504 #define CRC8_INIT 0xFF // Initial FCS value 505 #define CRC8_OK 0xCF // Good final FCS value 506 507 static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 508 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 509 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 510 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 511 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 512 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 513 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 514 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 515 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 516 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 517 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 518 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 519 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 520 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 521 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 522 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 523 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 524 }; 525 526 /*-----------------------------------------------------------------------------------*/ 527 static uint8_t crc8(uint8_t *data, uint16_t len){ 528 uint16_t count; 529 uint8_t crc = CRC8_INIT; 530 for (count = 0; count < len; count++){ 531 crc = crc8table[crc ^ data[count]]; 532 } 533 return crc; 534 } 535 536 /*-----------------------------------------------------------------------------------*/ 537 uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 538 uint8_t crc; 539 crc = crc8(data, len); 540 crc = crc8table[crc ^ check_sum]; 541 if (crc == CRC8_OK){ 542 return 0; /* Valid */ 543 } else { 544 return 1; /* Failed */ 545 } 546 } 547 548 /*-----------------------------------------------------------------------------------*/ 549 uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 550 /* Ones complement */ 551 return 0xFFu - crc8(data, len); 552 } 553 554 uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid){ 555 uint16_t next_cid; 556 if (current_cid == 0xffff) { 557 next_cid = 1; 558 } else { 559 next_cid = current_cid + 1; 560 } 561 return next_cid; 562 } 563 564 uint16_t btstack_strcpy(char * dst, uint16_t dst_size, const char * src){ 565 uint16_t bytes_to_copy = (uint16_t) btstack_min( dst_size - 1, strlen(src)); 566 (void) memcpy(dst, src, bytes_to_copy); 567 dst[bytes_to_copy] = 0; 568 return bytes_to_copy + 1; 569 } 570 571 void btstack_strcat(char * dst, uint16_t dst_size, const char * src){ 572 uint16_t src_len = (uint16_t) strlen(src); 573 uint16_t dst_len = (uint16_t) strlen(dst); 574 uint16_t bytes_to_copy = btstack_min( src_len, dst_size - dst_len - 1); 575 (void) memcpy( &dst[dst_len], src, bytes_to_copy); 576 dst[dst_len + bytes_to_copy] = 0; 577 } 578 579 uint16_t btstack_virtual_memcpy( 580 const uint8_t * field_data, uint16_t field_len, uint16_t field_offset, // position of field in complete data block 581 uint8_t * buffer, uint16_t buffer_size, uint16_t buffer_offset){ 582 583 uint16_t after_buffer = buffer_offset + buffer_size ; 584 // bail before buffer 585 if ((field_offset + field_len) < buffer_offset){ 586 return 0; 587 } 588 // bail after buffer 589 if (field_offset >= after_buffer){ 590 return 0; 591 } 592 // calc overlap 593 uint16_t bytes_to_copy = field_len; 594 595 uint16_t skip_at_start = 0; 596 if (field_offset < buffer_offset){ 597 skip_at_start = buffer_offset - field_offset; 598 bytes_to_copy -= skip_at_start; 599 } 600 601 uint16_t skip_at_end = 0; 602 if ((field_offset + field_len) > after_buffer){ 603 skip_at_end = (field_offset + field_len) - after_buffer; 604 bytes_to_copy -= skip_at_end; 605 } 606 607 btstack_assert((skip_at_end + skip_at_start) <= field_len); 608 btstack_assert(bytes_to_copy <= field_len); 609 610 memcpy(&buffer[(field_offset + skip_at_start) - buffer_offset], &field_data[skip_at_start], bytes_to_copy); 611 return bytes_to_copy; 612 } 613