• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef _BLE_COMMON_UTILS_H
16 #define _BLE_COMMON_UTILS_H
17 
18 #include <stdint.h>       // standard definitions
19 #include <stddef.h>       // standard definitions
20 #include "bt_common.h"        // common bt definitions
21 #include "ble_ip_config.h"  // SW configuration
22 #include "ble_ip.h"         // SW configuration
23 #include "compiler.h"     // for inline functions
24 
25 /// Number of '1' bits in a byte
26 #define NB_ONE_BITS(byte)   (one_bits[byte & 0x0F] + one_bits[byte >> 4])
27 
28 /// Get the number of elements within an array, give also number of rows in a 2-D array
29 #define ARRAY_LEN(array)   (sizeof((array))/sizeof((array)[0]))
30 
31 /// Get the number of columns within a 2-D array
32 #define ARRAY_NB_COLUMNS(array)  (sizeof((array[0]))/sizeof((array)[0][0]))
33 
34 
35 /// Macro for LMP message handler function declaration or definition
36 #define LMP_MSG_HANDLER(msg_name)   __STATIC int lmp_##msg_name##_handler(struct lmp_##msg_name const *param,  \
37                                                                                 ke_task_id_t const dest_id)
38 /// Macro for LMP message handler function declaration or definition
39 #define LLCP_MSG_HANDLER(msg_name)   __STATIC int llcp_##msg_name##_handler(struct llcp_##msg_name const *param,  \
40                                                                                 ke_task_id_t const dest_id)
41 
42 /// Macro for HCI message handler function declaration or definition (for multi-instantiated tasks)
43 #define HCI_CMD_HANDLER_C(cmd_name, param_struct)   __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param,  \
44                                                                                 ke_task_id_t const dest_id,  \
45                                                                                 uint16_t opcode)
46 
47 /// Macro for HCI message handler function declaration or definition (with parameters)
48 #define HCI_CMD_HANDLER(cmd_name, param_struct)   __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param,  \
49                                                                                 uint16_t opcode)
50 
51 /// Macro for HCI message handler function declaration or definition (with parameters)
52 #define HCI_CMD_HANDLER_TAB(task)   __STATIC const struct task##_hci_cmd_handler task##_hci_command_handler_tab[] =
53 
54 
55 /// MACRO to build a subversion field from the Minor and Release fields
56 #define CO_SUBVERSION_BUILD(minor, release)     (((minor) << 8) | (release))
57 
58 
59 /// Macro to get a structure from one of its structure field
60 #define CONTAINER_OF(ptr, type, member)    ((type *)( (char *)ptr - offsetof(type,member) ))
61 
62 
63 /// Increment value and make sure it's never greater or equals max (else wrap to 0)
64 #define CO_VAL_INC(_val, _max)      \
65     (_val) = (_val) + 1;            \
66     if((_val) >= (_max)) (_val) = 0
67 
68 
69 /// Add value and make sure it's never greater or equals max (else wrap)
70 /// _add must be less that _max
71 #define CO_VAL_ADD(_val, _add, _max)      \
72     (_val) = (_val) + (_add);             \
73     if((_val) >= (_max)) (_val) -= (_max)
74 
75 /// sub value and make sure it's never greater or equals max (else wrap)
76 /// _sub must be less that _max
77 #define CO_VAL_SUB(_val, _sub, _max)      \
78     if((_val) < (_sub)) (_val) += _max;   \
79     (_val) = (_val) - (_sub)
80 
81 /*
82  * ENUMERATIONS DEFINITIONS
83  ****************************************************************************************
84  */
85 
86 /// Status returned by generic packer-unpacker
87 enum CO_UTIL_PACK_STATUS
88 {
89     CO_UTIL_PACK_OK,
90     CO_UTIL_PACK_IN_BUF_OVFLW,
91     CO_UTIL_PACK_OUT_BUF_OVFLW,
92     CO_UTIL_PACK_WRONG_FORMAT,
93     CO_UTIL_PACK_ERROR,
94 };
95 
96 
97 /// Rate information
98 /*@TRACE*/
99 enum phy_rate
100 {
101     /// 1 Mbits/s Rate
102     CO_RATE_1MBPS   = 0,
103     /// 2 Mbits/s Rate
104     CO_RATE_2MBPS   = 1,
105     /// 125 Kbits/s Rate
106     CO_RATE_125KBPS = 2,
107     /// 500 Kbits/s Rate
108     CO_RATE_500KBPS = 3,
109     /// Undefined rate (used for reporting when no packet is received)
110     CO_RATE_UNDEF   = 4,
111 
112     CO_RATE_MAX     = 4,
113 };
114 
115 
116 /*
117  * FUNCTION DECLARATIONS
118  ****************************************************************************************
119  */
120 
121 /*
122  * TYPE DEFINITIONS
123  ****************************************************************************************
124  */
125 
126 
127 /*
128  * CONSTANT DECLARATIONS
129  ****************************************************************************************
130  */
131 
132 /// Number of '1' bits in values from 0 to 15, used to fasten bit counting
133 extern const unsigned char one_bits[16];
134 
135 /// Conversion table Sleep Clock Accuracy to PPM
136 extern const uint16_t co_sca2ppm[];
137 
138 /// NULL BD address
139 extern const struct bd_addr co_null_bdaddr;
140 
141 /// Default BD address
142 extern const struct bd_addr co_default_bdaddr;
143 
144 /// Table for converting rate to PHY
145 extern const uint8_t co_rate_to_phy[];
146 
147 /// Table for converting PHY to rate (Warning: the coded PHY is converted to 125K by default)
148 extern const uint8_t co_phy_to_rate[];
149 
150 /// Convert PHY mask (with one single bit set) to a value
151 extern const uint8_t co_phy_mask_to_value[];
152 
153 /// Convert PHY a value to the corresponding mask bit
154 extern const uint8_t co_phy_value_to_mask[];
155 
156 /// Convert Rate value to the corresponding PHY mask bit
157 extern const uint8_t co_rate_to_phy_mask[];
158 
159 /// Convert PHY mask bit to the corresponding Rate value
160 extern const uint8_t co_phy_mask_to_rate[];
161 
162 /// Convert Rate value to byte duration in us
163 extern const uint8_t co_rate_to_byte_dur_us[];
164 
165 /*
166  * OPERATIONS ON BT CLOCK
167  ****************************************************************************************
168  */
169 
170 /**
171  ****************************************************************************************
172  * @brief Clocks addition with 2 operands
173  *
174  * @param[in]   clock_a   1st operand value (in BT half-slots)
175  * @param[in]   clock_b   2nd operand value (in BT half-slots)
176  * @return      result    operation result (in BT half-slots)
177  ****************************************************************************************
178  */
179 #define CLK_ADD_2(clock_a, clock_b)     ((uint32_t)(((clock_a) + (clock_b)) & RWIP_MAX_CLOCK_TIME))
180 
181 /**
182  ****************************************************************************************
183  * @brief Clocks addition with 3 operands
184  *
185  * @param[in]   clock_a   1st operand value (in BT half-slots)
186  * @param[in]   clock_b   2nd operand value (in BT half-slots)
187  * @param[in]   clock_c   3rd operand value (in BT half-slots)
188  * @return      result    operation result (in BT half-slots)
189  ****************************************************************************************
190  */
191 #define CLK_ADD_3(clock_a, clock_b, clock_c)     ((uint32_t)(((clock_a) + (clock_b) + (clock_c)) & RWIP_MAX_CLOCK_TIME))
192 
193 /**
194  ****************************************************************************************
195  * @brief Clocks subtraction
196  *
197  * @param[in]   clock_a   1st operand value (in BT half-slots)
198  * @param[in]   clock_b   2nd operand value (in BT half-slots)
199  * @return      result    operation result (in BT half-slots)
200  ****************************************************************************************
201  */
202 #define CLK_SUB(clock_a, clock_b)     ((uint32_t)(((clock_a) - (clock_b)) & RWIP_MAX_CLOCK_TIME))
203 
204 /**
205  ****************************************************************************************
206  * @brief Clocks time difference
207  *
208  * @param[in]   clock_a   1st operand value (in BT half-slots)
209  * @param[in]   clock_b   2nd operand value (in BT half-slots)
210  * @return      result    return the time difference from clock A to clock B
211  *                           - result < 0  => clock_b is in the past
212  *                           - result == 0 => clock_a is equal to clock_b
213  *                           - result > 0  => clock_b is in the future
214  ****************************************************************************************
215  */
216 #define CLK_DIFF(clock_a, clock_b)     ( (CLK_SUB((clock_b), (clock_a)) > ((RWIP_MAX_CLOCK_TIME+1) >> 1)) ?                      \
217                           ((int32_t)((-CLK_SUB((clock_a), (clock_b))))) : ((int32_t)((CLK_SUB((clock_b), (clock_a))))) )
218 
219 
220 
221 /// macro to extract a field from a value containing several fields
222 /// @param[in] __r bit field value
223 /// @param[in] __f field name
224 /// @return the value of the register masked and shifted
225 #define GETF(__r, __f)                                                           \
226     (( (__r) & (__f##_MASK) ) >> (__f##_LSB))
227 
228 /// macro to set a field value into a value  containing several fields.
229 /// @param[in] __r bit field value
230 /// @param[in] __f field name
231 /// @param[in] __v value to put in field
232 #define SETF(__r, __f, __v)                                                      \
233     do {                                                                         \
234         ASSERT_INFO( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0 ,(__f##_MASK), (__v)); \
235         __r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB));                  \
236     } while (0)
237 
238 
239 
240 /// macro to extract a bit field from a value containing several fields
241 /// @param[in] __r bit field value
242 /// @param[in] __b bit field name
243 /// @return the value of the register masked and shifted
244 #define GETB(__r, __b)                                                           \
245     (( (__r) & (__b##_BIT) ) >> (__b##_POS))
246 
247 /// macro to set a bit field value into a value containing several fields.
248 /// @param[in] __r bit field value
249 /// @param[in] __b bit field name
250 /// @param[in] __v value to put in field
251 #define SETB(__r, __b, __v)                                                      \
252     do {                                                                         \
253         ASSERT_ERR( ( ( ( (__v) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \
254         __r = (((__r) & ~(__b##_BIT)) | (__v) << (__b##_POS));                  \
255     } while (0)
256 
257 /// macro to toggle a bit into a value containing several bits.
258 /// @param[in] __r bit field value
259 /// @param[in] __b bit field name
260 #define TOGB(__r, __b)                                                           \
261     do {                                                                         \
262         __r = ((__r) ^ (__b##_BIT));                                             \
263     } while (0)
264 
265 /**
266  ****************************************************************************************
267  * @brief Check if clock_a is equal to clock_b
268  *
269  * @param[in]   clock_a   Clock A value (in BT half-slots)
270  * @param[in]   clock_b   Clock B value (in BT half-slots)
271  * @return      result    True: clock_a lower than or equal to clock_b | False: else
272  ****************************************************************************************
273  */
274 #define CLK_EQ(clock_a, clock_b)      (clock_b == clock_a)
275 
276 /**
277  ****************************************************************************************
278  * @brief Check if clock_a is lower than or equal to clock_b
279  *
280  * @param[in]   clock_a   Clock A value (in BT half-slots)
281  * @param[in]   clock_b   Clock B value (in BT half-slots)
282  * @return      result    True: clock_a lower than or equal to clock_b | False: else
283  ****************************************************************************************
284  */
285 #define CLK_LOWER_EQ(clock_a, clock_b)      (CLK_SUB(clock_b, clock_a) < (RWIP_MAX_CLOCK_TIME >> 1))
286 
287 /**
288  ****************************************************************************************
289  * @brief Check if clock A is lower than or equal to clock B (with half-us precision)
290  *
291  * @param[in]   int_a     Integer part of clock A (in BT half-slots)
292  * @param[in]   fract_a   Fractional part of clock A (in half-us) (range: 0 to 624)
293  * @param[in]   int_b     Integer part of clock B (in BT half-slots)
294  * @param[in]   fract_b   Fractional part of clock B (in half-us) (range: 0 to 624)
295  * @return      result    True: clock A lower than or equal to clock B | False: else
296  ****************************************************************************************
297  */
298 #define CLK_LOWER_EQ_HUS(int_a, fract_a, int_b, fract_b)      (  CLK_GREATER_THAN(int_b, int_a)  \
299                                                                  || (   CLK_EQ(int_a, int_b)     \
300                                                                      && (fract_a <= fract_b) ) ) \
301 
302 /**
303  ****************************************************************************************
304  * @brief Check if clock_a is greater than clock_b
305  *
306  * @param[in]   clock_a   Clock A value (in BT half-slots)
307  * @param[in]   clock_b   Clock B value (in BT half-slots)
308  * @return      result    True: clock_a is greater than clock_b | False: else
309  ****************************************************************************************
310  */
311 #define CLK_GREATER_THAN(clock_a, clock_b)    !(CLK_LOWER_EQ(clock_a, clock_b))
312 
313 /**
314  ****************************************************************************************
315  * @brief Check if clock A is greater than clock B (with half-us precision)
316  *
317  * @param[in]   int_a     Integer part of clock A (in BT half-slots)
318  * @param[in]   fract_a   Fractional part of clock A (in half-us) (range: 0 to 624)
319  * @param[in]   int_b     Integer part of clock B (in BT half-slots)
320  * @param[in]   fract_b   Fractional part of clock B (in half-us) (range: 0 to 624)
321  * @return      result    True: clock A greater than clock B | False: else
322  ****************************************************************************************
323  */
324 #define CLK_GREATER_THAN_HUS(int_a, fract_a, int_b, fract_b)      (  CLK_GREATER_THAN(int_a, int_b)  \
325                                                                      || (   CLK_EQ(int_a, int_b)     \
326                                                                          && (fract_a > fract_b) ) )  \
327 
328 #if (BLE_EMB_PRESENT)
329 /**
330  ******************************************************************************
331  * @brief Compare 2 BLE instants (connection event counter)
332  * @param[in]   instant_a   1st operand value (connection event counter)
333  * @param[in]   instant_b   2nd operand value (connection event counter)
334  * @return      result      True: B is greater or equal to A | False: B is smaller than A
335  ******************************************************************************
336  */
337 #define CO_BLE_INSTANT_PASSED(instant_a, instant_b)    ((uint16_t)(instant_b - instant_a) < 32767)
338 
339 /**
340  ******************************************************************************
341  * @brief Compute difference between two event counter
342  * @param[in]   evt_cnt_a   1st operand value (connection event counter)
343  * @param[in]   evt_cnt_b   2nd operand value (connection event counter)
344  * @return      result    return the time difference from evt_cnt_a to evt_cnt_b
345  *                           - result < 0  => evt_cnt_b is in the past
346  *                           - result == 0 => evt_cnt_a is equal to evt_cnt_b
347  *                           - result > 0  => evt_cnt_b is in the future
348  ******************************************************************************
349  */
350 #define CO_BLE_EVT_CNT_DIFF(evt_cnt_a, evt_cnt_b)    ((((uint16_t) (evt_cnt_b)) - ((uint16_t) (evt_cnt_a)) > 32768) \
351                                                    ? ((int16_t)(-(((uint16_t) (evt_cnt_a)) - ((uint16_t) (evt_cnt_b))))) \
352                                                    : ((int16_t)(-(((uint16_t) (evt_cnt_b)) - ((uint16_t) (evt_cnt_a))))))
353 
354 #endif //BLE_EMB_PRESENT
355 
356 
357 /*
358  * FUNCTION DECLARATIONS
359  ****************************************************************************************
360  */
361 
362 /**
363  ****************************************************************************************
364  * @brief Read a packed 16 bits word.
365  * @param[in] ptr16 The address of the first byte of the 16 bits word.
366  * @return The 16 bits value.
367  ****************************************************************************************
368  */
ble_read16p(void const * ptr16)369 __INLINE uint16_t ble_read16p(void const *ptr16)
370 {
371     uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8;
372     return value;
373 }
374 
375 /**
376  ****************************************************************************************
377  * @brief Read a packed 24 bits word.
378  * @param[in] ptr24 The address of the first byte of the 24 bits word.
379  * @return The 24 bits value.
380  ****************************************************************************************
381  */
382 
ble_read24p(void const * ptr24)383 __INLINE uint32_t ble_read24p(void const *ptr24)
384 {
385     uint16_t addr_l, addr_h;
386     addr_l = ble_read16p(ptr24);
387     addr_h = *((uint8_t *)ptr24 + 2) & 0x00FF;
388     return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
389 }
390 
391 /**
392  ****************************************************************************************
393  * @brief Write a packed 24 bits word.
394  * @param[in] ptr24 The address of the first byte of the 24 bits word.
395  * @param[in] value The value to write.
396  ****************************************************************************************
397  */
398 
ble_write24p(void const * ptr24,uint32_t value)399 __INLINE void ble_write24p(void const *ptr24, uint32_t value)
400 {
401     uint8_t *ptr=(uint8_t*)ptr24;
402 
403     *ptr++ = (uint8_t)(value&0xff);
404     *ptr++ = (uint8_t)((value&0xff00)>>8);
405     *ptr++ = (uint8_t)((value&0xff0000)>>16);
406 }
407 
408 /**
409  ****************************************************************************************
410  * @brief Read a packed 32 bits word.
411  * @param[in] ptr32 The address of the first byte of the 32 bits word.
412  * @return The 32 bits value.
413  ****************************************************************************************
414  */
ble_read32p(void const * ptr32)415 __INLINE uint32_t ble_read32p(void const *ptr32)
416 {
417     uint16_t addr_l, addr_h;
418     addr_l = ble_read16p(ptr32);
419     addr_h = ble_read16p((uint8_t *)ptr32 + 2);
420     return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
421 }
422 /**
423  ****************************************************************************************
424  * @brief Write a packed 32 bits word.
425  * @param[in] ptr32 The address of the first byte of the 32 bits word.
426  * @param[in] value The value to write.
427  ****************************************************************************************
428  */
ble_write32p(void const * ptr32,uint32_t value)429 __INLINE void ble_write32p(void const *ptr32, uint32_t value)
430 {
431     uint8_t *ptr=(uint8_t*)ptr32;
432 
433     *ptr++ = (uint8_t)(value&0xff);
434     *ptr++ = (uint8_t)((value&0xff00)>>8);
435     *ptr++ = (uint8_t)((value&0xff0000)>>16);
436     *ptr = (uint8_t)((value&0xff000000)>>24);
437 }
438 
439 /**
440  ****************************************************************************************
441  * @brief Write a packed 16 bits word.
442  * @param[in] ptr16 The address of the first byte of the 16 bits word.
443  * @param[in] value The value to write.
444  ****************************************************************************************
445  */
ble_write16p(void const * ptr16,uint16_t value)446 __INLINE void ble_write16p(void const *ptr16, uint16_t value)
447 {
448     uint8_t *ptr=(uint8_t*)ptr16;
449 
450     *ptr++ = value&0xff;
451     *ptr = (value&0xff00)>>8;
452 }
453 
454 #if (RW_DEBUG || DISPLAY_SUPPORT)
455 
456 /**
457  ****************************************************************************************
458  * @brief Convert bytes to hexadecimal string
459  *
460  * @param[out] dest      Pointer to the destination string (must be 2x longer than input table)
461  * @param[in]  src       Pointer to the bytes table
462  * @param[in]  nb_bytes  Number of bytes to display in the string
463  ****************************************************************************************
464  */
465 void co_bytes_to_string(char* dest, uint8_t* src, uint8_t nb_bytes);
466 #endif //(RW_DEBUG || DISPLAY_SUPPORT)
467 
468 /**
469  ****************************************************************************************
470  * @brief Compares two Bluetooth device addresses
471  *
472  * This function checks if the two bd address are equal.
473  *
474  * @param[in] bd_address1        Pointer on the first bd address to be compared.
475  * @param[in] bd_address2        Pointer on the second bd address to be compared.
476  *
477  * @return result of the comparison (true: equal | false: different).
478  ****************************************************************************************
479  */
480 bool co_bdaddr_compare(struct bd_addr const *bd_address1, struct bd_addr const *bd_address2);
481 
482 #if (BLE_EMB_PRESENT)
483 /**
484  ******************************************************************************
485  * @brief Count the number of good channels in a LE map
486  * @param[in]  map  Channel Map (bit fields for the 40 BT RF channels)
487  * @return  Number of good channels
488  ******************************************************************************
489  */
490 uint8_t co_nb_good_le_channels(const struct le_chnl_map* map);
491 #endif //BLE_EMB_PRESENT
492 
493 #if (BT_EMB_PRESENT)
494 
495 /**
496  ******************************************************************************
497  * @brief Convert an duration in baseband slot to a duration in number of ticks.
498  * @param[in]  slot_cnt  Duration in number of baseband slot
499  * @return  Duration (in number of ticks).
500  ******************************************************************************
501  */
502 uint32_t co_slot_to_duration(uint32_t slot_cnt);
503 
504 /**
505  ******************************************************************************
506  * @brief Count the number of good channels in a map
507  * @param[in]  map  Channel Map (bit fields for the 79 BT RF channels)
508  * @return  Number of good channels
509  ******************************************************************************
510  */
511 uint8_t co_nb_good_channels(const struct chnl_map* map);
512 
513 #endif //BT_EMB_PRESENT
514 
515 /**
516  ****************************************************************************************
517  * @brief Pack parameters from a C structure to a packed buffer
518  *
519  * This function packs parameters according to a specific format. It takes care of the
520  * endianess, padding, required by the compiler.
521  *
522  * By default output format is LSB but it can be changed with first character of format string
523  *     - <  : LSB output format
524  *     - >  : MSB output format
525  *
526  * Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built
527  * up from Format Characters, which specify the type of data being packed/unpacked.
528  *     - B  : byte - 8bits value
529  *     - H  : word - 16bits value
530  *     - L  : long - 32-bits value
531  *     - D  : 24 bits value
532  *     - XXB: table of several bytes, where XX is the byte number, in decimal
533  *     - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess
534  *     - nB : table size over 1 byte, followed by the table of bytes
535  *     - NB : table size over 2 bytes, followed by the table of bytes
536  *
537  * Example:   "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table
538  *
539  * Note: the function works in the same buffer
540  *
541  * @param[out]     out         Output Data Buffer
542  * @param[in]      in          Input Data Buffer
543  * @param[out]     out_len     Output size of packed data (in bytes)
544  * @param[in]      in_len      Input buffer size (in bytes)
545  * @param[in]      format      Parameters format
546  *
547  * @return  Status of the packing operation
548  *****************************************************************************************
549  */
550 uint8_t co_util_pack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format);
551 
552 /**
553  ****************************************************************************************
554  * @brief Unpack parameters from an unpacked buffer to a C structure
555  *
556  * This function unpacks parameters according to a specific format. It takes care of the
557  * endianess, padding, required by the compiler.
558  *
559  * By default input format is LSB but it can be changed with first character of format string
560  *     - <  : LSB input format
561  *     - >  : MSB input format
562  *
563  * Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built
564  * up from Format Characters, which specify the type of data being packed/unpacked.
565  *     - B  : byte - 8bits value
566  *     - H  : word - 16bits value
567  *     - L  : long - 32-bits value
568  *     - D  : 24 bits value
569  *     - XXB: table of several bytes, where XX is the byte number, in decimal
570  *     - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess
571  *     - nB : table size over 1 byte, followed by the table of bytes
572  *     - NB : table size over 2 bytes, followed by the table of bytes
573  *
574  * Example:   "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table
575  *
576  * Note: the output buffer provided must be large enough to contain the unpacked data.
577  * Note2: if a NULL output buffer is provided, the function does not copy the unpacked parameters. It still parses the
578  *  format string and input buffer to return the number of unpacked bytes. Can be used to compute the expected unpacked
579  *  buffer size.
580  *
581  * @param[out]    out         Unpacked parameters buffer
582  * @param[in]     in          Packed parameters buffer
583  * @param[inout]  out_len     Input: buffer size / Output: size of unpacked data (in bytes)
584  * @param[in]     in_len      Size of the packed data (in bytes)
585  * @param[in]     format      Parameters format
586  *
587  * @return  Status of the unpacking operation
588  *****************************************************************************************
589  */
590 uint8_t co_util_unpack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format);
591 
592 
593 #if (BLE_EMB_PRESENT)
594 
595 /**
596  *****************************************************************************************
597  * @brief Get BLE packet duration in us according to PHY and packet size
598  *
599  * @param[in] len PDU size in octets
600  * @param[in] rate PHY Rate (@see enum lld_phy)
601  *
602  * @return packet duration in us.
603  *****************************************************************************************
604  */
605 uint16_t co_ble_pkt_dur_in_us(uint8_t len, uint8_t rate);
606 #endif // (BLE_EMB_PRESENT)
607 
608 #endif // _BLE_COMMON_UTILS_H
609