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 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH 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 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_util.c" 39ab2c6ae4SMatthias Ringwald 40eb886013SMatthias Ringwald /* 41eb886013SMatthias Ringwald * General utility functions 42eb886013SMatthias Ringwald */ 43eb886013SMatthias Ringwald 447907f069SMatthias Ringwald #include "btstack_config.h" 4502bdfbf8SMatthias Ringwald #include "btstack_debug.h" 46eb886013SMatthias Ringwald #include "btstack_util.h" 4702bdfbf8SMatthias Ringwald 48*ad144fa1SMatthias Ringwald #include <stdio.h> // vsnprintf 49*ad144fa1SMatthias Ringwald #include <string.h> // memcpy 50*ad144fa1SMatthias Ringwald 51ec08441fSMatthias Ringwald #ifdef _MSC_VER 52ec08441fSMatthias Ringwald #include <intrin.h> 53ec08441fSMatthias Ringwald #include <windows.h> 54ec08441fSMatthias Ringwald #endif 55ec08441fSMatthias Ringwald 56eb886013SMatthias Ringwald 5773988a59SMatthias Ringwald /** 5873988a59SMatthias Ringwald * @brief Compare two Bluetooth addresses 5973988a59SMatthias Ringwald * @param a 6073988a59SMatthias Ringwald * @param b 61969fc1c5SMilanka Ringwald * @return 0 if equal 6273988a59SMatthias Ringwald */ 635222912bSMatthias Ringwald int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b){ 6473988a59SMatthias Ringwald return memcmp(a,b, BD_ADDR_LEN); 6573988a59SMatthias Ringwald } 6673988a59SMatthias Ringwald 6773988a59SMatthias Ringwald /** 6873988a59SMatthias Ringwald * @brief Copy Bluetooth address 6973988a59SMatthias Ringwald * @param dest 7073988a59SMatthias Ringwald * @param src 7173988a59SMatthias Ringwald */ 725222912bSMatthias Ringwald void bd_addr_copy(bd_addr_t dest, const bd_addr_t src){ 736535961aSMatthias Ringwald (void)memcpy(dest, src, BD_ADDR_LEN); 7473988a59SMatthias Ringwald } 7573988a59SMatthias Ringwald 7641f9be70SMatthias Ringwald uint16_t little_endian_read_16(const uint8_t * buffer, int position){ 7741f9be70SMatthias Ringwald return (uint16_t)(((uint16_t) buffer[position]) | (((uint16_t)buffer[position+1]) << 8)); 7873988a59SMatthias Ringwald } 7941f9be70SMatthias Ringwald uint32_t little_endian_read_24(const uint8_t * buffer, int position){ 8041f9be70SMatthias Ringwald return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16); 8173988a59SMatthias Ringwald } 8241f9be70SMatthias Ringwald uint32_t little_endian_read_32(const uint8_t * buffer, int position){ 8341f9be70SMatthias Ringwald return ((uint32_t) buffer[position]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t)buffer[position+2]) << 16) | (((uint32_t) buffer[position+3]) << 24); 8473988a59SMatthias Ringwald } 8573988a59SMatthias Ringwald 8641f9be70SMatthias Ringwald void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 8741f9be70SMatthias Ringwald uint16_t pos = position; 88b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)value; 89b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 90eb886013SMatthias Ringwald } 91eb886013SMatthias Ringwald 9241f9be70SMatthias Ringwald void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 9341f9be70SMatthias Ringwald uint16_t pos = position; 94adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value); 95adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 96adbdd27aSMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 97adbdd27aSMilanka Ringwald } 98adbdd27aSMilanka Ringwald 9941f9be70SMatthias Ringwald void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 10041f9be70SMatthias Ringwald uint16_t pos = position; 101b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 102b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 103b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 104b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 105eb886013SMatthias Ringwald } 106eb886013SMatthias Ringwald 10741f9be70SMatthias Ringwald uint32_t big_endian_read_16(const uint8_t * buffer, int position) { 10841f9be70SMatthias Ringwald return (uint16_t)(((uint16_t) buffer[position+1]) | (((uint16_t)buffer[position]) << 8)); 10973988a59SMatthias Ringwald } 11073988a59SMatthias Ringwald 11141f9be70SMatthias Ringwald uint32_t big_endian_read_24(const uint8_t * buffer, int position) { 11241f9be70SMatthias Ringwald return ( ((uint32_t)buffer[position+2]) | (((uint32_t)buffer[position+1]) << 8) | (((uint32_t) buffer[position]) << 16)); 113e57a2545SMilanka Ringwald } 114e57a2545SMilanka Ringwald 11541f9be70SMatthias Ringwald uint32_t big_endian_read_32(const uint8_t * buffer, int position) { 11641f9be70SMatthias Ringwald return ((uint32_t) buffer[position+3]) | (((uint32_t)buffer[position+2]) << 8) | (((uint32_t)buffer[position+1]) << 16) | (((uint32_t) buffer[position]) << 24); 11773988a59SMatthias Ringwald } 11873988a59SMatthias Ringwald 11941f9be70SMatthias Ringwald void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value){ 12041f9be70SMatthias Ringwald uint16_t pos = position; 121b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 122b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 123eb886013SMatthias Ringwald } 124eb886013SMatthias Ringwald 12541f9be70SMatthias Ringwald void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value){ 12641f9be70SMatthias Ringwald uint16_t pos = position; 127b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 128b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 129b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 1307f535380SMilanka Ringwald } 1317f535380SMilanka Ringwald 13241f9be70SMatthias Ringwald void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value){ 13341f9be70SMatthias Ringwald uint16_t pos = position; 134b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 24); 135b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 16); 136b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value >> 8); 137b0920f25SMilanka Ringwald buffer[pos++] = (uint8_t)(value); 138eb886013SMatthias Ringwald } 139eb886013SMatthias Ringwald 140eb886013SMatthias Ringwald // general swap/endianess utils 141b45b7749SMilanka Ringwald void reverse_bytes(const uint8_t * src, uint8_t * dest, int len){ 142eb886013SMatthias Ringwald int i; 143eb886013SMatthias Ringwald for (i = 0; i < len; i++) 144b45b7749SMilanka Ringwald dest[len - 1 - i] = src[i]; 145eb886013SMatthias Ringwald } 146b45b7749SMilanka Ringwald void reverse_24(const uint8_t * src, uint8_t * dest){ 147b45b7749SMilanka Ringwald reverse_bytes(src, dest, 3); 148eb886013SMatthias Ringwald } 149b45b7749SMilanka Ringwald void reverse_48(const uint8_t * src, uint8_t * dest){ 150b45b7749SMilanka Ringwald reverse_bytes(src, dest, 6); 151bf1b35bfSMatthias Ringwald } 152b45b7749SMilanka Ringwald void reverse_56(const uint8_t * src, uint8_t * dest){ 153b45b7749SMilanka Ringwald reverse_bytes(src, dest, 7); 154eb886013SMatthias Ringwald } 155b45b7749SMilanka Ringwald void reverse_64(const uint8_t * src, uint8_t * dest){ 156b45b7749SMilanka Ringwald reverse_bytes(src, dest, 8); 157eb886013SMatthias Ringwald } 158b45b7749SMilanka Ringwald void reverse_128(const uint8_t * src, uint8_t * dest){ 159b45b7749SMilanka Ringwald reverse_bytes(src, dest, 16); 160eb886013SMatthias Ringwald } 161b45b7749SMilanka Ringwald void reverse_256(const uint8_t * src, uint8_t * dest){ 162b45b7749SMilanka Ringwald reverse_bytes(src, dest, 32); 163cc7a2d78SMatthias Ringwald } 164eb886013SMatthias Ringwald 165724d70a2SMatthias Ringwald void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){ 166724d70a2SMatthias Ringwald reverse_bytes(src, dest, 6); 167724d70a2SMatthias Ringwald } 168724d70a2SMatthias Ringwald 16977955af6SMatthias Ringwald bool btstack_is_null(const uint8_t * buffer, uint16_t size){ 17077955af6SMatthias Ringwald uint16_t i; 17177955af6SMatthias Ringwald for (i=0; i < size ; i++){ 17277955af6SMatthias Ringwald if (buffer[i] != 0) { 17377955af6SMatthias Ringwald return false; 17477955af6SMatthias Ringwald } 17577955af6SMatthias Ringwald } 17677955af6SMatthias Ringwald return true; 17777955af6SMatthias Ringwald } 17877955af6SMatthias Ringwald 1796d708481SDirk Helbig bool btstack_is_null_bd_addr( const bd_addr_t addr ){ 1806d708481SDirk Helbig return btstack_is_null( addr, sizeof(bd_addr_t) ); 1816d708481SDirk Helbig } 1826d708481SDirk Helbig 183ebaeb1beSMatthias Ringwald uint32_t btstack_min(uint32_t a, uint32_t b){ 184c1ab6cc1SMatthias Ringwald return (a < b) ? a : b; 185ebaeb1beSMatthias Ringwald } 186ebaeb1beSMatthias Ringwald 187ebaeb1beSMatthias Ringwald uint32_t btstack_max(uint32_t a, uint32_t b){ 188c1ab6cc1SMatthias Ringwald return (a > b) ? a : b; 189ebaeb1beSMatthias Ringwald } 190ebaeb1beSMatthias Ringwald 19168af3967SMatthias Ringwald /** 192a9d566f7SMatthias Ringwald * @brief Calculate delta between two uint32_t points in time 1936b65794dSMilanka Ringwald * @return time_a - time_b - result > 0 if time_a is newer than time_b 19468af3967SMatthias Ringwald */ 19568af3967SMatthias Ringwald int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b){ 19668af3967SMatthias Ringwald return (int32_t)(time_a - time_b); 19768af3967SMatthias Ringwald } 19868af3967SMatthias Ringwald 199a9d566f7SMatthias Ringwald /** 200a9d566f7SMatthias Ringwald * @brief Calculate delta between two uint16_t points in time 201a9d566f7SMatthias Ringwald * @return time_a - time_b - result > 0 if time_a is newer than time_b 202a9d566f7SMatthias Ringwald */ 203a9d566f7SMatthias Ringwald int16_t btstack_time16_delta(uint16_t time_a, uint16_t time_b){ 204a9d566f7SMatthias Ringwald return (int16_t)(time_a - time_b); 205a9d566f7SMatthias Ringwald } 206c1c58647SMatthias Ringwald 207d7d45b32SMatthias Ringwald char char_for_nibble(uint8_t nibble){ 2088334d3d8SMatthias Ringwald 2098334d3d8SMatthias Ringwald static const char * char_to_nibble = "0123456789ABCDEF"; 2108334d3d8SMatthias Ringwald 211c1c58647SMatthias Ringwald if (nibble < 16){ 212c1c58647SMatthias Ringwald return char_to_nibble[nibble]; 213c1c58647SMatthias Ringwald } else { 214eb886013SMatthias Ringwald return '?'; 215eb886013SMatthias Ringwald } 216c1c58647SMatthias Ringwald } 217eb886013SMatthias Ringwald 218405d63a9SMatthias Ringwald static inline char char_for_high_nibble(int value){ 219405d63a9SMatthias Ringwald return char_for_nibble((value >> 4) & 0x0f); 220405d63a9SMatthias Ringwald } 221405d63a9SMatthias Ringwald 222405d63a9SMatthias Ringwald static inline char char_for_low_nibble(int value){ 223405d63a9SMatthias Ringwald return char_for_nibble(value & 0x0f); 224405d63a9SMatthias Ringwald } 225405d63a9SMatthias Ringwald 226c1c58647SMatthias Ringwald 227a6efb919SMatthias Ringwald int nibble_for_char(char c){ 228c1ab6cc1SMatthias Ringwald if ((c >= '0') && (c <= '9')) return c - '0'; 229c1ab6cc1SMatthias Ringwald if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; 230c1ab6cc1SMatthias Ringwald if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; 231a6efb919SMatthias Ringwald return -1; 232a6efb919SMatthias Ringwald } 233a6efb919SMatthias Ringwald 23446059ae4SMilanka Ringwald #ifdef ENABLE_PRINTF_HEXDUMP 235eb886013SMatthias Ringwald void printf_hexdump(const void * data, int size){ 236c1c58647SMatthias Ringwald char buffer[4]; 237c1c58647SMatthias Ringwald buffer[2] = ' '; 238c1c58647SMatthias Ringwald buffer[3] = 0; 2399dbfa930SMatthias Ringwald const uint8_t * ptr = (const uint8_t *) data; 240c1c58647SMatthias Ringwald while (size > 0){ 2419dbfa930SMatthias Ringwald uint8_t byte = *ptr++; 242c1c58647SMatthias Ringwald buffer[0] = char_for_high_nibble(byte); 243c1c58647SMatthias Ringwald buffer[1] = char_for_low_nibble(byte); 244c1c58647SMatthias Ringwald printf("%s", buffer); 245c1c58647SMatthias Ringwald size--; 246eb886013SMatthias Ringwald } 247eb886013SMatthias Ringwald printf("\n"); 248eb886013SMatthias Ringwald } 24946059ae4SMilanka Ringwald #endif 250eb886013SMatthias Ringwald 251cb42147aSMatthias Ringwald #if defined(ENABLE_LOG_INFO) || defined(ENABLE_LOG_DEBUG) 252cb42147aSMatthias Ringwald static void log_hexdump(int level, const void * data, int size){ 253405d63a9SMatthias Ringwald #define ITEMS_PER_LINE 16 254405d63a9SMatthias Ringwald // template '0x12, ' 255405d63a9SMatthias Ringwald #define BYTES_PER_BYTE 6 256405d63a9SMatthias Ringwald char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1]; 2577224be7eSMatthias Ringwald int i, j; 258eb886013SMatthias Ringwald j = 0; 259eb886013SMatthias Ringwald for (i=0; i<size;i++){ 2607224be7eSMatthias Ringwald 2617224be7eSMatthias Ringwald // help static analyzer proof that j stays within bounds 262c1ab6cc1SMatthias Ringwald if (j > (BYTES_PER_BYTE * (ITEMS_PER_LINE-1))){ 2637224be7eSMatthias Ringwald j = 0; 2647224be7eSMatthias Ringwald } 2657224be7eSMatthias Ringwald 266eb886013SMatthias Ringwald uint8_t byte = ((uint8_t *)data)[i]; 267eb886013SMatthias Ringwald buffer[j++] = '0'; 268eb886013SMatthias Ringwald buffer[j++] = 'x'; 269405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 270405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 271eb886013SMatthias Ringwald buffer[j++] = ','; 272eb886013SMatthias Ringwald buffer[j++] = ' '; 2737224be7eSMatthias Ringwald 274c1ab6cc1SMatthias Ringwald if (j >= (BYTES_PER_BYTE * ITEMS_PER_LINE) ){ 275eb886013SMatthias Ringwald buffer[j] = 0; 276cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 277eb886013SMatthias Ringwald j = 0; 278eb886013SMatthias Ringwald } 279eb886013SMatthias Ringwald } 280eb886013SMatthias Ringwald if (j != 0){ 281eb886013SMatthias Ringwald buffer[j] = 0; 282cb42147aSMatthias Ringwald HCI_DUMP_LOG(level, "%s", buffer); 283eb886013SMatthias Ringwald } 284cb42147aSMatthias Ringwald } 285cb42147aSMatthias Ringwald #endif 286cb42147aSMatthias Ringwald 287cb42147aSMatthias Ringwald void log_debug_hexdump(const void * data, int size){ 288e950fa96SMatthias Ringwald #ifdef ENABLE_LOG_DEBUG 289fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_DEBUG, data, size); 290cb42147aSMatthias Ringwald #else 2914bd79111SMatthias Ringwald UNUSED(data); // ok: no code 2924bd79111SMatthias Ringwald UNUSED(size); // ok: no code 293cb42147aSMatthias Ringwald #endif 294cb42147aSMatthias Ringwald } 295cb42147aSMatthias Ringwald 296cb42147aSMatthias Ringwald void log_info_hexdump(const void * data, int size){ 297cb42147aSMatthias Ringwald #ifdef ENABLE_LOG_INFO 298fa087deaSMatthias Ringwald log_hexdump(HCI_DUMP_LOG_LEVEL_INFO, data, size); 299d0662982SMatthias Ringwald #else 3004bd79111SMatthias Ringwald UNUSED(data); // ok: no code 3014bd79111SMatthias Ringwald UNUSED(size); // ok: no code 3028314c363SMatthias Ringwald #endif 3037299c0feSMatthias Ringwald } 304eb886013SMatthias Ringwald 3058314c363SMatthias Ringwald void log_info_key(const char * name, sm_key_t key){ 30602bdfbf8SMatthias Ringwald #ifdef ENABLE_LOG_INFO 30702bdfbf8SMatthias Ringwald char buffer[16*2+1]; 30802bdfbf8SMatthias Ringwald int i; 30902bdfbf8SMatthias Ringwald int j = 0; 31002bdfbf8SMatthias Ringwald for (i=0; i<16;i++){ 31102bdfbf8SMatthias Ringwald uint8_t byte = key[i]; 312405d63a9SMatthias Ringwald buffer[j++] = char_for_high_nibble(byte); 313405d63a9SMatthias Ringwald buffer[j++] = char_for_low_nibble(byte); 31402bdfbf8SMatthias Ringwald } 31502bdfbf8SMatthias Ringwald buffer[j] = 0; 31602bdfbf8SMatthias Ringwald log_info("%-6s %s", name, buffer); 317d0662982SMatthias Ringwald #else 318d0662982SMatthias Ringwald UNUSED(name); 319cb42147aSMatthias Ringwald (void)key; 32002bdfbf8SMatthias Ringwald #endif 321eb886013SMatthias Ringwald } 322eb886013SMatthias Ringwald 3232b604902SMatthias Ringwald // UUIDs are stored in big endian, similar to bd_addr_t 3242b604902SMatthias Ringwald 325eb886013SMatthias Ringwald // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 3262b604902SMatthias Ringwald const uint8_t bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 327eb886013SMatthias Ringwald 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 328eb886013SMatthias Ringwald 32948cdff9cSMilanka Ringwald void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid){ 330b45b7749SMilanka Ringwald (void)memcpy(uuid128, bluetooth_base_uuid, 16); 33148cdff9cSMilanka Ringwald big_endian_store_32(uuid128, 0, short_uuid); 332eb886013SMatthias Ringwald } 333eb886013SMatthias Ringwald 3348933879eSMatthias Ringwald bool uuid_has_bluetooth_prefix(const uint8_t * uuid128){ 3352b604902SMatthias Ringwald return memcmp(&uuid128[4], &bluetooth_base_uuid[4], 12) == 0; 336eb886013SMatthias Ringwald } 337eb886013SMatthias Ringwald 338eb886013SMatthias Ringwald static char uuid128_to_str_buffer[32+4+1]; 3395222912bSMatthias Ringwald char * uuid128_to_str(const uint8_t * uuid){ 3407224be7eSMatthias Ringwald int i; 3417224be7eSMatthias Ringwald int j = 0; 3427224be7eSMatthias Ringwald // after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash 3437224be7eSMatthias Ringwald const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9); 3447224be7eSMatthias Ringwald for (i=0;i<16;i++){ 345405d63a9SMatthias Ringwald uint8_t byte = uuid[i]; 346405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_high_nibble(byte); 347405d63a9SMatthias Ringwald uuid128_to_str_buffer[j++] = char_for_low_nibble(byte); 3487224be7eSMatthias Ringwald if (dash_locations & (1<<i)){ 3497224be7eSMatthias Ringwald uuid128_to_str_buffer[j++] = '-'; 3507224be7eSMatthias Ringwald } 3517224be7eSMatthias Ringwald } 352eb886013SMatthias Ringwald return uuid128_to_str_buffer; 353eb886013SMatthias Ringwald } 354eb886013SMatthias Ringwald 355eb886013SMatthias Ringwald static char bd_addr_to_str_buffer[6*3]; // 12:45:78:01:34:67\0 35661c3ec28SMatthias Ringwald char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter){ 357eb886013SMatthias Ringwald char * p = bd_addr_to_str_buffer; 358eb886013SMatthias Ringwald int i; 359eb886013SMatthias Ringwald for (i = 0; i < 6 ; i++) { 360405d63a9SMatthias Ringwald uint8_t byte = addr[i]; 361405d63a9SMatthias Ringwald *p++ = char_for_high_nibble(byte); 362405d63a9SMatthias Ringwald *p++ = char_for_low_nibble(byte); 36361c3ec28SMatthias Ringwald *p++ = delimiter; 364eb886013SMatthias Ringwald } 365eb886013SMatthias Ringwald *--p = 0; 366eb886013SMatthias Ringwald return (char *) bd_addr_to_str_buffer; 367eb886013SMatthias Ringwald } 368eb886013SMatthias Ringwald 36961c3ec28SMatthias Ringwald char * bd_addr_to_str(const bd_addr_t addr){ 37061c3ec28SMatthias Ringwald return bd_addr_to_str_with_delimiter(addr, ':'); 37161c3ec28SMatthias Ringwald } 37261c3ec28SMatthias Ringwald 3733c9da642SMatthias Ringwald void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address){ 3743c9da642SMatthias Ringwald const int bd_addr_string_len = 17; 37530314625SMatthias Ringwald uint16_t i = 0; 37630314625SMatthias Ringwald while ((i + bd_addr_string_len) <= size){ 3773c9da642SMatthias Ringwald if (memcmp(&buffer[i], "00:00:00:00:00:00", bd_addr_string_len)) { 3783c9da642SMatthias Ringwald i++; 3793c9da642SMatthias Ringwald continue; 3803c9da642SMatthias Ringwald } 3813c9da642SMatthias Ringwald // set address 3823c9da642SMatthias Ringwald (void)memcpy(&buffer[i], bd_addr_to_str(address), bd_addr_string_len); 3833c9da642SMatthias Ringwald i += bd_addr_string_len; 3843c9da642SMatthias Ringwald } 3853c9da642SMatthias Ringwald } 3863c9da642SMatthias Ringwald 387a6efb919SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 38841f9be70SMatthias Ringwald int upper_nibble = nibble_for_char(byte_string[0]); 389a6efb919SMatthias Ringwald if (upper_nibble < 0) return -1; 39041f9be70SMatthias Ringwald int lower_nibble = nibble_for_char(byte_string[1]); 391a6efb919SMatthias Ringwald if (lower_nibble < 0) return -1; 392a6efb919SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 393a6efb919SMatthias Ringwald } 394eb886013SMatthias Ringwald 395a6efb919SMatthias Ringwald int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){ 39641f9be70SMatthias Ringwald const char * the_string = addr_string; 397a6efb919SMatthias Ringwald uint8_t buffer[BD_ADDR_LEN]; 398a6efb919SMatthias Ringwald int result = 0; 399eb886013SMatthias Ringwald int i; 400eb886013SMatthias Ringwald for (i = 0; i < BD_ADDR_LEN; i++) { 40141f9be70SMatthias Ringwald int single_byte = scan_hex_byte(the_string); 402a6efb919SMatthias Ringwald if (single_byte < 0) break; 40341f9be70SMatthias Ringwald the_string += 2; 404b0920f25SMilanka Ringwald buffer[i] = (uint8_t)single_byte; 40541f9be70SMatthias Ringwald // don't check separator after last byte 406c1ab6cc1SMatthias Ringwald if (i == (BD_ADDR_LEN - 1)) { 407a6efb919SMatthias Ringwald result = 1; 408a6efb919SMatthias Ringwald break; 409eb886013SMatthias Ringwald } 410cd2e416cSMatthias Ringwald // skip supported separators 41141f9be70SMatthias Ringwald char next_char = *the_string; 4125df9dc78SMatthias Ringwald if ((next_char == ':') || (next_char == '-') || (next_char == ' ')) { 41341f9be70SMatthias Ringwald the_string++; 414cd2e416cSMatthias Ringwald } 415a6efb919SMatthias Ringwald } 416a6efb919SMatthias Ringwald 4179305033eSMatthias Ringwald if (result != 0){ 418a6efb919SMatthias Ringwald bd_addr_copy(addr, buffer); 419a6efb919SMatthias Ringwald } 420a6efb919SMatthias Ringwald return result; 421eb886013SMatthias Ringwald } 4225d067ab1SMatthias Ringwald 4235d067ab1SMatthias Ringwald uint32_t btstack_atoi(const char * str){ 42441f9be70SMatthias Ringwald const char * the_string = str; 4255d067ab1SMatthias Ringwald uint32_t val = 0; 426ff3cc4a5SMatthias Ringwald while (true){ 42741f9be70SMatthias Ringwald char chr = *the_string++; 428c1ab6cc1SMatthias Ringwald if (!chr || (chr < '0') || (chr > '9')) 4295d067ab1SMatthias Ringwald return val; 4304ea43905SMatthias Ringwald val = (val * 10u) + (uint8_t)(chr - '0'); 4315d067ab1SMatthias Ringwald } 4325d067ab1SMatthias Ringwald } 4331f41c2c9SMatthias Ringwald 434d1207cd8SMilanka Ringwald int string_len_for_uint32(uint32_t i){ 435d1207cd8SMilanka Ringwald if (i < 10) return 1; 436d1207cd8SMilanka Ringwald if (i < 100) return 2; 437d1207cd8SMilanka Ringwald if (i < 1000) return 3; 438d1207cd8SMilanka Ringwald if (i < 10000) return 4; 439d1207cd8SMilanka Ringwald if (i < 100000) return 5; 440d1207cd8SMilanka Ringwald if (i < 1000000) return 6; 441d1207cd8SMilanka Ringwald if (i < 10000000) return 7; 442d1207cd8SMilanka Ringwald if (i < 100000000) return 8; 443d1207cd8SMilanka Ringwald if (i < 1000000000) return 9; 444d1207cd8SMilanka Ringwald return 10; 445d1207cd8SMilanka Ringwald } 446d1207cd8SMilanka Ringwald 447d1207cd8SMilanka Ringwald int count_set_bits_uint32(uint32_t x){ 44841f9be70SMatthias Ringwald uint32_t v = x; 44941f9be70SMatthias Ringwald v = (v & 0x55555555) + ((v >> 1) & 0x55555555U); 45041f9be70SMatthias Ringwald v = (v & 0x33333333) + ((v >> 2) & 0x33333333U); 45141f9be70SMatthias Ringwald v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0FU); 45241f9be70SMatthias Ringwald v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FFU); 45341f9be70SMatthias Ringwald v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFFU); 45441f9be70SMatthias Ringwald return v; 455d1207cd8SMilanka Ringwald } 4561f41c2c9SMatthias Ringwald 457ec08441fSMatthias Ringwald uint8_t btstack_clz(uint32_t value) { 4581a8c5172SDirk Helbig btstack_assert( value != 0 ); 459ec08441fSMatthias Ringwald #if defined(__GNUC__) || defined (__clang__) 460ec08441fSMatthias Ringwald // use gcc/clang intrinsic 461ec08441fSMatthias Ringwald return (uint8_t) __builtin_clz(value); 462ec08441fSMatthias Ringwald #elif defined(_MSC_VER) 463ec08441fSMatthias Ringwald // use MSVC intrinsic 464ec08441fSMatthias Ringwald DWORD leading_zero = 0; 4656f5aa202SMatthias Ringwald _BitScanReverse( &leading_zero, value ); 466ec08441fSMatthias Ringwald return (uint8_t)(31 - leading_zero); 467ec08441fSMatthias Ringwald #else 468ec08441fSMatthias Ringwald // divide-and-conquer implementation for 32-bit integers 469af0ac871SAlec Cantor uint32_t x = value; 470ec08441fSMatthias Ringwald uint8_t r = 0; 471ec08441fSMatthias Ringwald if ((x & 0xffff0000u) == 0) { 472ec08441fSMatthias Ringwald x <<= 16; 473ec08441fSMatthias Ringwald r += 16; 474ec08441fSMatthias Ringwald } 475ec08441fSMatthias Ringwald if ((x & 0xff000000u) == 0) { 476ec08441fSMatthias Ringwald x <<= 8; 477ec08441fSMatthias Ringwald r += 8; 478ec08441fSMatthias Ringwald } 479ec08441fSMatthias Ringwald if ((x & 0xf0000000u) == 0) { 480ec08441fSMatthias Ringwald x <<= 4; 481ec08441fSMatthias Ringwald r += 4; 482ec08441fSMatthias Ringwald } 483ec08441fSMatthias Ringwald if ((x & 0xc0000000u) == 0) { 484ec08441fSMatthias Ringwald x <<= 2; 485ec08441fSMatthias Ringwald r += 2; 486ec08441fSMatthias Ringwald } 487ec08441fSMatthias Ringwald if ((x & 0x80000000u) == 0) { 488ec08441fSMatthias Ringwald x <<= 1; 489ec08441fSMatthias Ringwald r += 1; 490ec08441fSMatthias Ringwald } 491ec08441fSMatthias Ringwald return r; 492ec08441fSMatthias Ringwald #endif 493ec08441fSMatthias Ringwald } 494ec08441fSMatthias Ringwald 4951f41c2c9SMatthias Ringwald /* 49642fea667SMilanka Ringwald * CRC-8 (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. 4971f41c2c9SMatthias Ringwald */ 4981f41c2c9SMatthias Ringwald 4991f41c2c9SMatthias Ringwald #define CRC8_INIT 0xFF // Initial FCS value 5001f41c2c9SMatthias Ringwald #define CRC8_OK 0xCF // Good final FCS value 5011f41c2c9SMatthias Ringwald 5021f41c2c9SMatthias Ringwald static const uint8_t crc8table[256] = { /* reversed, 8-bit, poly=0x07 */ 5031f41c2c9SMatthias Ringwald 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 5041f41c2c9SMatthias Ringwald 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 5051f41c2c9SMatthias Ringwald 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 5061f41c2c9SMatthias Ringwald 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 5071f41c2c9SMatthias Ringwald 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 5081f41c2c9SMatthias Ringwald 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 5091f41c2c9SMatthias Ringwald 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 5101f41c2c9SMatthias Ringwald 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 5111f41c2c9SMatthias Ringwald 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 5121f41c2c9SMatthias Ringwald 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 5131f41c2c9SMatthias Ringwald 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 5141f41c2c9SMatthias Ringwald 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 5151f41c2c9SMatthias Ringwald 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 5161f41c2c9SMatthias Ringwald 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 5171f41c2c9SMatthias Ringwald 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 5181f41c2c9SMatthias Ringwald 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 5191f41c2c9SMatthias Ringwald }; 5201f41c2c9SMatthias Ringwald 5211f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 5221f41c2c9SMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len){ 5231f41c2c9SMatthias Ringwald uint16_t count; 5241f41c2c9SMatthias Ringwald uint8_t crc = CRC8_INIT; 5251f41c2c9SMatthias Ringwald for (count = 0; count < len; count++){ 5261f41c2c9SMatthias Ringwald crc = crc8table[crc ^ data[count]]; 5271f41c2c9SMatthias Ringwald } 5281f41c2c9SMatthias Ringwald return crc; 5291f41c2c9SMatthias Ringwald } 5301f41c2c9SMatthias Ringwald 5311f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 53263dd1c76SMatthias Ringwald uint8_t btstack_crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum){ 5331f41c2c9SMatthias Ringwald uint8_t crc; 5341f41c2c9SMatthias Ringwald crc = crc8(data, len); 5351f41c2c9SMatthias Ringwald crc = crc8table[crc ^ check_sum]; 5361f41c2c9SMatthias Ringwald if (crc == CRC8_OK){ 5371f41c2c9SMatthias Ringwald return 0; /* Valid */ 5381f41c2c9SMatthias Ringwald } else { 5391f41c2c9SMatthias Ringwald return 1; /* Failed */ 5401f41c2c9SMatthias Ringwald } 5411f41c2c9SMatthias Ringwald } 5421f41c2c9SMatthias Ringwald 5431f41c2c9SMatthias Ringwald /*-----------------------------------------------------------------------------------*/ 54463dd1c76SMatthias Ringwald uint8_t btstack_crc8_calc(uint8_t *data, uint16_t len){ 5451f41c2c9SMatthias Ringwald /* Ones complement */ 5464ea43905SMatthias Ringwald return 0xFFu - crc8(data, len); 5471f41c2c9SMatthias Ringwald } 548a73d0b9dSMilanka Ringwald 54942fea667SMilanka Ringwald /* 55042fea667SMilanka Ringwald * CRC-32 lookup table as calculated by the table generator. Polynomial (normal) 0x04c11db7, ISO 3309 (HDLC) 55142fea667SMilanka Ringwald * 55242fea667SMilanka Ringwald * Created using pycrc tool (https://pycrc.org) with "crc-32" as model, and "table-driven" algorithm 55342fea667SMilanka Ringwald * python3 pycrc.py --model crc-32 --algorithm table-driven --generate h -o crc32.h 55442fea667SMilanka Ringwald * python3 pycrc.py --model crc-32 --algorithm table-driven --generate c -o crc32.c 55542fea667SMilanka Ringwald */ 55642fea667SMilanka Ringwald 55742fea667SMilanka Ringwald /** 55842fea667SMilanka Ringwald * Static table used for the table_driven implementation. 55942fea667SMilanka Ringwald */ 56042fea667SMilanka Ringwald static const uint32_t crc_table[256] = { 56142fea667SMilanka Ringwald 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 56242fea667SMilanka Ringwald 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 56342fea667SMilanka Ringwald 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 56442fea667SMilanka Ringwald 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 56542fea667SMilanka Ringwald 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 56642fea667SMilanka Ringwald 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 56742fea667SMilanka Ringwald 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 56842fea667SMilanka Ringwald 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 56942fea667SMilanka Ringwald 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 57042fea667SMilanka Ringwald 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 57142fea667SMilanka Ringwald 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 57242fea667SMilanka Ringwald 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 57342fea667SMilanka Ringwald 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 57442fea667SMilanka Ringwald 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 57542fea667SMilanka Ringwald 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 57642fea667SMilanka Ringwald 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 57742fea667SMilanka Ringwald 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 57842fea667SMilanka Ringwald 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 57942fea667SMilanka Ringwald 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 58042fea667SMilanka Ringwald 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 58142fea667SMilanka Ringwald 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 58242fea667SMilanka Ringwald 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 58342fea667SMilanka Ringwald 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 58442fea667SMilanka Ringwald 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 58542fea667SMilanka Ringwald 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 58642fea667SMilanka Ringwald 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 58742fea667SMilanka Ringwald 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 58842fea667SMilanka Ringwald 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 58942fea667SMilanka Ringwald 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 59042fea667SMilanka Ringwald 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 59142fea667SMilanka Ringwald 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 59242fea667SMilanka Ringwald 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 59342fea667SMilanka Ringwald }; 59442fea667SMilanka Ringwald 59542fea667SMilanka Ringwald uint32_t btstack_crc32_init(void){ 59642fea667SMilanka Ringwald return 0xffffffff; 59742fea667SMilanka Ringwald } 59842fea667SMilanka Ringwald 59942fea667SMilanka Ringwald uint32_t btstack_crc32_update(uint32_t crc, const uint8_t * data, uint32_t data_len){ 60076468bbdSMilanka Ringwald const uint8_t *d = data; 60142fea667SMilanka Ringwald uint32_t tbl_idx; 60242fea667SMilanka Ringwald 60342fea667SMilanka Ringwald while (data_len--) { 60442fea667SMilanka Ringwald tbl_idx = (crc ^ *d) & 0xff; 60542fea667SMilanka Ringwald crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; 60642fea667SMilanka Ringwald d++; 60742fea667SMilanka Ringwald } 60842fea667SMilanka Ringwald return crc & 0xffffffff; 60942fea667SMilanka Ringwald } 61042fea667SMilanka Ringwald 61142fea667SMilanka Ringwald uint32_t btstack_crc32_finalize(uint32_t crc){ 61242fea667SMilanka Ringwald return crc ^ 0xffffffff; 61342fea667SMilanka Ringwald } 61442fea667SMilanka Ringwald 61542fea667SMilanka Ringwald /*-----------------------------------------------------------------------------------*/ 61642fea667SMilanka Ringwald 617a73d0b9dSMilanka Ringwald uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid){ 618a73d0b9dSMilanka Ringwald uint16_t next_cid; 619a73d0b9dSMilanka Ringwald if (current_cid == 0xffff) { 620a73d0b9dSMilanka Ringwald next_cid = 1; 621a73d0b9dSMilanka Ringwald } else { 622a73d0b9dSMilanka Ringwald next_cid = current_cid + 1; 623a73d0b9dSMilanka Ringwald } 624a73d0b9dSMilanka Ringwald return next_cid; 625a73d0b9dSMilanka Ringwald } 626de22414aSMatthias Ringwald 627ed7a067cSMilanka Ringwald uint16_t btstack_strcpy(char * dst, uint16_t dst_size, const char * src){ 6281a3bc516SMatthias Ringwald uint16_t bytes_to_copy = (uint16_t) btstack_min( dst_size - 1, (uint16_t) strlen(src)); 629de22414aSMatthias Ringwald (void) memcpy(dst, src, bytes_to_copy); 630981f700bSMatthias Ringwald dst[bytes_to_copy] = 0; 631ed7a067cSMilanka Ringwald return bytes_to_copy + 1; 632de22414aSMatthias Ringwald } 6333ece4788SMatthias Ringwald 6343ece4788SMatthias Ringwald void btstack_strcat(char * dst, uint16_t dst_size, const char * src){ 6353ece4788SMatthias Ringwald uint16_t src_len = (uint16_t) strlen(src); 6363ece4788SMatthias Ringwald uint16_t dst_len = (uint16_t) strlen(dst); 6373ece4788SMatthias Ringwald uint16_t bytes_to_copy = btstack_min( src_len, dst_size - dst_len - 1); 6383ece4788SMatthias Ringwald (void) memcpy( &dst[dst_len], src, bytes_to_copy); 6393ece4788SMatthias Ringwald dst[dst_len + bytes_to_copy] = 0; 6403ece4788SMatthias Ringwald } 641f819d1d9SMilanka Ringwald 642*ad144fa1SMatthias Ringwald int btstack_printf_strlen(const char * format, ...){ 643*ad144fa1SMatthias Ringwald va_list argptr; 644*ad144fa1SMatthias Ringwald va_start(argptr, format); 645*ad144fa1SMatthias Ringwald char dummy_buffer[1]; 646*ad144fa1SMatthias Ringwald int len = vsnprintf(dummy_buffer, sizeof(dummy_buffer), format, argptr); 647*ad144fa1SMatthias Ringwald va_end(argptr); 648*ad144fa1SMatthias Ringwald return len; 649*ad144fa1SMatthias Ringwald } 650*ad144fa1SMatthias Ringwald 651*ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_assert_complete(char * buffer, size_t size, const char * format, ...){ 652*ad144fa1SMatthias Ringwald va_list argptr; 653*ad144fa1SMatthias Ringwald va_start(argptr, format); 654*ad144fa1SMatthias Ringwald int len = vsnprintf(buffer, size, format, argptr); 655*ad144fa1SMatthias Ringwald va_end(argptr); 656*ad144fa1SMatthias Ringwald 657*ad144fa1SMatthias Ringwald // check for no error and no truncation 658*ad144fa1SMatthias Ringwald btstack_assert(len >= 0); 659*ad144fa1SMatthias Ringwald btstack_assert(len < size); 660*ad144fa1SMatthias Ringwald return (uint16_t) len; 661*ad144fa1SMatthias Ringwald } 662*ad144fa1SMatthias Ringwald 663*ad144fa1SMatthias Ringwald uint16_t btstack_snprintf_best_effort(char * buffer, size_t size, const char * format, ...){ 664*ad144fa1SMatthias Ringwald btstack_assert(size > 0); 665*ad144fa1SMatthias Ringwald va_list argptr; 666*ad144fa1SMatthias Ringwald va_start(argptr, format); 667*ad144fa1SMatthias Ringwald int len = vsnprintf(buffer, size, format, argptr); 668*ad144fa1SMatthias Ringwald va_end(argptr); 669*ad144fa1SMatthias Ringwald if (len < 0) { 670*ad144fa1SMatthias Ringwald // error -> len = 0 671*ad144fa1SMatthias Ringwald return 0; 672*ad144fa1SMatthias Ringwald } else { 673*ad144fa1SMatthias Ringwald // min of total string len and buffer size 674*ad144fa1SMatthias Ringwald return (uint16_t) btstack_min((uint32_t) len, (uint32_t) size - 1); 675*ad144fa1SMatthias Ringwald } 676*ad144fa1SMatthias Ringwald } 677*ad144fa1SMatthias Ringwald 678f819d1d9SMilanka Ringwald uint16_t btstack_virtual_memcpy( 679f819d1d9SMilanka Ringwald const uint8_t * field_data, uint16_t field_len, uint16_t field_offset, // position of field in complete data block 680f819d1d9SMilanka Ringwald uint8_t * buffer, uint16_t buffer_size, uint16_t buffer_offset){ 681f819d1d9SMilanka Ringwald 682f819d1d9SMilanka Ringwald uint16_t after_buffer = buffer_offset + buffer_size ; 683f819d1d9SMilanka Ringwald // bail before buffer 684f819d1d9SMilanka Ringwald if ((field_offset + field_len) < buffer_offset){ 685f819d1d9SMilanka Ringwald return 0; 686f819d1d9SMilanka Ringwald } 687f819d1d9SMilanka Ringwald // bail after buffer 688f819d1d9SMilanka Ringwald if (field_offset >= after_buffer){ 689f819d1d9SMilanka Ringwald return 0; 690f819d1d9SMilanka Ringwald } 691f819d1d9SMilanka Ringwald // calc overlap 692f819d1d9SMilanka Ringwald uint16_t bytes_to_copy = field_len; 693f819d1d9SMilanka Ringwald 694f819d1d9SMilanka Ringwald uint16_t skip_at_start = 0; 695f819d1d9SMilanka Ringwald if (field_offset < buffer_offset){ 696f819d1d9SMilanka Ringwald skip_at_start = buffer_offset - field_offset; 697f819d1d9SMilanka Ringwald bytes_to_copy -= skip_at_start; 698f819d1d9SMilanka Ringwald } 699f819d1d9SMilanka Ringwald 700f819d1d9SMilanka Ringwald uint16_t skip_at_end = 0; 701f819d1d9SMilanka Ringwald if ((field_offset + field_len) > after_buffer){ 702f819d1d9SMilanka Ringwald skip_at_end = (field_offset + field_len) - after_buffer; 703f819d1d9SMilanka Ringwald bytes_to_copy -= skip_at_end; 704f819d1d9SMilanka Ringwald } 705f819d1d9SMilanka Ringwald 706f819d1d9SMilanka Ringwald btstack_assert((skip_at_end + skip_at_start) <= field_len); 707f819d1d9SMilanka Ringwald btstack_assert(bytes_to_copy <= field_len); 708f819d1d9SMilanka Ringwald 709f819d1d9SMilanka Ringwald memcpy(&buffer[(field_offset + skip_at_start) - buffer_offset], &field_data[skip_at_start], bytes_to_copy); 710f819d1d9SMilanka Ringwald return bytes_to_copy; 711f819d1d9SMilanka Ringwald } 712