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