xref: /btstack/src/btstack_util.h (revision 74d3bb9da45249c571154b6c10da92d7f001905b)
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 /**
39  * @title General Utility Functions
40  *
41  */
42 
43 #ifndef BTSTACK_UTIL_H
44 #define BTSTACK_UTIL_H
45 
46 
47 #if defined __cplusplus
48 extern "C" {
49 #endif
50 
51 #include <stdint.h>
52 #include <string.h>
53 
54 #include "bluetooth.h"
55 #include "btstack_defines.h"
56 #include "btstack_linked_list.h"
57 
58 // hack: compilation with the android ndk causes an error as there's a reverse_64 macro
59 #ifdef reverse_64
60 #undef reverse_64
61 #endif
62 
63 // use replacement in Visual Studio
64 #ifdef _MSC_VER
65 #define strncasecmp _strnicmp
66 #define strcasecmp _stricmp
67 #endif
68 
69 
70  /**
71   * @brief returns a value with number of lowest bits set to <1>
72   */
73 #define N_BITS(value) ((1<<value) - 1)
74 
75 /**
76  * @brief The device name type
77  */
78 #define DEVICE_NAME_LEN 248
79 typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];
80 
81 /* API_START */
82 
83 /**
84  * @brief Minimum function for uint32_t
85  * @param a
86  * @param b
87  * @return value
88  */
89 uint32_t btstack_min(uint32_t a, uint32_t b);
90 
91 /**
92  * @brief Maximum function for uint32_t
93  * @param a
94  * @param b
95  * @return value
96  */
97 uint32_t btstack_max(uint32_t a, uint32_t b);
98 
99 /**
100  * @brief Calculate delta between two uint32_t points in time
101  * @return time_a - time_b - result > 0 if time_a is newer than time_b
102  */
103 int32_t btstack_time_delta(uint32_t time_a, uint32_t time_b);
104 
105 /**
106  * @brief Calculate delta between two uint16_t points in time
107  * @return time_a - time_b - result > 0 if time_a is newer than time_b
108  */
109 int16_t btstack_time16_delta(uint16_t time_a, uint16_t time_b);
110 
111 /**
112  * @brief Read 08/16/24/32 bit little endian value from buffer
113  * @param buffer
114  * @param position in buffer
115  * @return value
116  */
117 uint8_t  little_endian_read_08(const uint8_t * buffer, int position);
118 uint16_t little_endian_read_16(const uint8_t * buffer, int position);
119 uint32_t little_endian_read_24(const uint8_t * buffer, int position);
120 uint32_t little_endian_read_32(const uint8_t * buffer, int position);
121 
122 
123 /**
124  * @brief Write 08/16/32 bit little endian value into buffer
125  * @param buffer
126  * @param position in buffer
127  * @param value
128  */
129 void little_endian_store_08(uint8_t * buffer, uint16_t position, uint8_t value);
130 void little_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value);
131 void little_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value);
132 void little_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value);
133 
134 /**
135  * @brief Read 08/16/24/32 bit big endian value from buffer
136  * @param buffer
137  * @param position in buffer
138  * @return value
139  */
140 uint32_t big_endian_read_08(const uint8_t* buffer, int position);
141 uint32_t big_endian_read_16(const uint8_t * buffer, int position);
142 uint32_t big_endian_read_24(const uint8_t * buffer, int position);
143 uint32_t big_endian_read_32(const uint8_t * buffer, int position);
144 
145 /**
146  * @brief Write 08/16/32 bit big endian value into buffer
147  * @param buffer
148  * @param position in buffer
149  * @param value
150  */
151 void big_endian_store_08(uint8_t * buffer, uint16_t position, uint8_t value);
152 void big_endian_store_16(uint8_t * buffer, uint16_t position, uint16_t value);
153 void big_endian_store_24(uint8_t * buffer, uint16_t position, uint32_t value);
154 void big_endian_store_32(uint8_t * buffer, uint16_t position, uint32_t value);
155 
156 
157 /**
158  * @brief Swap bytes in 16 bit integer
159  */
btstack_flip_16(uint16_t value)160 static inline uint16_t btstack_flip_16(uint16_t value){
161     return (uint16_t)((value & 0xffu) << 8) | (value >> 8);
162 }
163 
164 /**
165  * @brief Check for big endian system
166  * @return 1 if on big endian
167  */
btstack_is_big_endian(void)168 static inline int btstack_is_big_endian(void){
169 	uint16_t sample = 0x0100;
170 	return (int) *(uint8_t*) &sample;
171 }
172 
173 /**
174  * @brief Check for little endian system
175  * @return 1 if on little endian
176  */
btstack_is_little_endian(void)177 static inline int btstack_is_little_endian(void){
178 	uint16_t sample = 0x0001;
179 	return (int) *(uint8_t*) &sample;
180 }
181 
182 /**
183  * @brief Copy from source to destination and reverse byte order
184  * @param src
185  * @param dest
186  * @param len
187  */
188 void reverse_bytes(const uint8_t * src, uint8_t * dest, int len);
189 
190 /**
191  * @brief Wrapper around reverse_bytes for common buffer sizes
192  * @param src
193  * @param dest
194  */
195 void reverse_24 (const uint8_t * src, uint8_t * dest);
196 void reverse_48 (const uint8_t * src, uint8_t * dest);
197 void reverse_56 (const uint8_t * src, uint8_t * dest);
198 void reverse_64 (const uint8_t * src, uint8_t * dest);
199 void reverse_128(const uint8_t * src, uint8_t * dest);
200 void reverse_256(const uint8_t * src, uint8_t * dest);
201 
202 void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest);
203 
204 /**
205  * @brief Check if all bytes in buffer are zero
206  * @param buffer
207  * @param size
208  * @return true if all bytes is buffer are zero
209  */
210 bool btstack_is_null(const uint8_t * buffer, uint16_t size);
211 
212 /**
213  * @brief Check if all bytes in a bd_addr_t are zero
214  * @param addr
215  * @return true if all bytes in addr are zero
216  */
217 bool btstack_is_null_bd_addr( const bd_addr_t addr );
218 
219 /**
220  * @brief ASCII character for 4-bit nibble
221  * @return character
222  */
223 char char_for_nibble(uint8_t nibble);
224 
225 /**
226  * @brif 4-bit nibble from ASCII character
227  * @return value
228  */
229 int nibble_for_char(char c);
230 
231 /**
232  * @brief Compare two Bluetooth addresses
233  * @param a
234  * @param b
235  * @return 0 if equal
236  */
237 int bd_addr_cmp(const bd_addr_t a, const bd_addr_t b);
238 
239 /**
240  * @brief Copy Bluetooth address
241  * @param dest
242  * @param src
243  */
244 void bd_addr_copy(bd_addr_t dest, const bd_addr_t src);
245 
246 /**
247  * @brief Use printf to write hexdump as single line of data
248  */
249 void printf_hexdump(const void * data, int size);
250 
251 /**
252  * @brief Create human readable representation for UUID128
253  * @note uses fixed global buffer
254  * @return pointer to UUID128 string
255  */
256 char * uuid128_to_str(const uint8_t * uuid);
257 
258 /**
259  * @brief Create human readable represenationt of Bluetooth address
260  * @note uses fixed global buffer
261  * @param delimiter
262  * @return pointer to Bluetooth address string
263  */
264 char * bd_addr_to_str_with_delimiter(const bd_addr_t addr, char delimiter);
265 
266 /**
267  * @brief Create human readable represenationt of Bluetooth address
268  * @note uses fixed global buffer
269  * @return pointer to Bluetooth address string
270  */
271 char * bd_addr_to_str(const bd_addr_t addr);
272 
273 /**
274  * @brief Replace address placeholder '00:00:00:00:00:00' with Bluetooth address
275  * @param buffer
276  * @param size
277  * @param address
278  */
279 void btstack_replace_bd_addr_placeholder(uint8_t * buffer, uint16_t size, const bd_addr_t address);
280 
281 /**
282  * @brief Parse Bluetooth address
283  * @param address_string
284  * @param buffer for parsed address
285  * @return 1 if string was parsed successfully
286  */
287 int sscanf_bd_addr(const char * addr_string, bd_addr_t addr);
288 
289 /**
290  * @brief Constructs UUID128 from 16 or 32 bit UUID using Bluetooth base UUID
291  * @param uuid128 output buffer
292  * @param short_uuid
293  */
294 void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid);
295 
296 /**
297  * @brief Checks if UUID128 has Bluetooth base UUID prefix
298  * @param uui128 to test
299  * @return true if it can be expressed as UUID32
300  */
301 bool uuid_has_bluetooth_prefix(const uint8_t * uuid128);
302 
303 /**
304  * @brief Parse unsigned number
305  * @param str to parse
306  * @return value
307  */
308 uint32_t btstack_atoi(const char * str);
309 
310 /**
311  * @brief Return number of digits of a uint32 number
312  * @param uint32_number
313  * @return num_digits
314  */
315 int string_len_for_uint32(uint32_t i);
316 
317 /**
318  * @brief Return number of set bits in a uint32 number
319  * @param uint32_number
320  * @return num_set_bits
321  */
322 int count_set_bits_uint32(uint32_t x);
323 
324 /**
325  * @brief Check CRC8 using ETSI TS 101 369 V6.3.0.
326  * @note Only used by RFCOMM
327  * @param data
328  * @param len
329  * @param check_sum
330  */
331 uint8_t btstack_crc8_check(uint8_t * data, uint16_t len, uint8_t check_sum);
332 
333 /**
334  * @brief Calculate CRC8 using ETSI TS 101 369 V6.3.0.
335  * @note Only used by RFCOMM
336  * @param data
337  * @param len
338  */
339 uint8_t btstack_crc8_calc(uint8_t * data, uint16_t len);
340 
341 
342 /**
343  * @brief Calculate the initial CRC32 value using ISO 3309 (HDLC), polynomial (normal) 0x04c11db7
344  * @note Used by OTS Service.
345  *
346  * @return  The initial crc value.
347  */
348 uint32_t btstack_crc32_init(void);
349 
350 /**
351  * @brief Update the CRC32 value with new data.
352  *
353  * @param crc      The current crc value.
354  * @param data     Pointer to a buffer of \a data_len bytes.
355  * @param data_len Number of bytes in the \a data buffer.
356  * @return             The updated crc value.
357  */
358 uint32_t btstack_crc32_update(uint32_t crc, const uint8_t * data, uint32_t data_len);
359 
360 /**
361  * @brief Calculate the final CRC32 value.
362  *
363  * @param crc  The current crc value.
364  * @return     The final crc value.
365  */
366 uint32_t btstack_crc32_finalize(uint32_t crc);
367 
368 /**
369  * @brief Get next cid
370  * @param current_cid
371  * @return next cid skiping 0
372  */
373 uint16_t btstack_next_cid_ignoring_zero(uint16_t current_cid);
374 
375 /**
376  * @brief Copy string (up to dst_size-1 characters) from src into dst buffer with terminating '\0'
377  * @note replaces strncpy + dst[dst_size-1] = '\0'
378  * @param dst
379  * @param dst_size
380  * @param src
381  * @retun bytes_copied including trailing 0
382  */
383 uint16_t btstack_strcpy(char * dst, uint16_t dst_size, const char * src);
384 
385 /**
386  * @brief Append src string to string in dst buffer with terminating '\0'
387  * @note max total string length will be dst_size-1 characters
388  * @param dst
389  * @param dst_size
390  * @param src
391  */
392 void btstack_strcat(char * dst, uint16_t dst_size, const char * src);
393 
394 /**
395  * @brief Calculated the number of characters that would get printed
396  * @note same as calling snprintf without a buffer
397  * @param format
398  * @param argsq
399  * @return number of characters, or negative value on error
400  */
401 int btstack_printf_strlen(const char * format, ...)
402 #ifdef __GNUC__
403 __attribute__ ((format (__printf__, 1, 2)))
404 #endif
405 ;
406 
407 
408 /**
409  * @brief Format string into buffer with '\0' and assert it is large enough
410  * @note same as calling snprintf and assert that the string was not truncated
411  * @param buffer
412  * @param size of buffer
413  * @param format
414  * @param argsq
415  * @return number of characters
416  */
417 uint16_t btstack_snprintf_assert_complete(char * buffer, size_t size, const char * format, ...)
418 #ifdef __GNUC__
419 __attribute__ ((format (__printf__, 3, 4)))
420 #endif
421 ;
422 
423 /**
424  * @brief Format string into buffer, truncated if necessary. Output string is '\0' terminated
425  * @note similar to calling snprintf but returns the length of the output string
426  * @param buffer
427  * @param size of buffer
428  * @param format
429  * @param argsq
430  * @return number of characters
431  */
432 uint16_t btstack_snprintf_best_effort(char * buffer, size_t size, const char * format, ...)
433 #ifdef __GNUC__
434 __attribute__ ((format (__printf__, 3, 4)))
435 #endif
436 ;
437 
438 /**
439  * Returns the number of leading 0-bits in x, starting at the most significant bit position.
440  * If x is 0, the result is undefined.
441  * @note maps to __builtin_clz for gcc and clang
442  * @param value
443  * @return number of leading 0-bits
444  */
445 uint8_t btstack_clz(uint32_t value);
446 
447 /**
448  * @brief Copy chunk of data into a virtual buffer backed by a physical buffer.
449  * Used to provide chunk of data of larger buffer that is constructed on the fly, e.g. serializing data struct
450  *
451  * For example, copy field2 to buffer, with buffer_offset = 11
452  *
453  *           field1  field2  field3     field4        field5  filed6
454  * struct:  -------|-------|----------|-------------|-------|--------------
455  * buffer:             ------------------
456  * result:             ----|
457  *
458  * When also copying field3 and field4 to buffer, with buffer_offset = 11
459  *
460  *           field1  field2  field3     field4        field5  filed6
461  * struct:  -------|-------|----------|-------------|-------|--------------
462  * buffer:             ------------------
463  * result:             ----|----------|--
464  *
465  * @param field_data
466  * @param field_len
467  * @param field_offset  position of field in complete data block
468  * @param buffer_data
469  * @param buffer_len
470  * @param buffer_offset position of buffer in complete data block
471  * @return bytes_copied number of bytes actually stored in buffer
472  */
473 uint16_t btstack_virtual_memcpy(
474     const uint8_t * field_data, uint16_t field_len, uint16_t field_offset,
475     uint8_t * buffer, uint16_t buffer_size, uint16_t buffer_offset);
476 
477 
478 /* API_END */
479 
480 #if defined __cplusplus
481 }
482 #endif
483 
484 #endif // BTSTACK_UTIL_H
485