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