From ee29c25b29eaa4fac4e897442634b69ecc8d8125 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 28 Mar 2024 14:32:49 +1100 Subject: Fork ESP-IDF's bluetooth component i want better sbc encoding, and no cla will stop me --- lib/bt/esp_ble_mesh/common/include/mesh/atomic.h | 305 ++++ lib/bt/esp_ble_mesh/common/include/mesh/buf.h | 1758 ++++++++++++++++++++ .../esp_ble_mesh/common/include/mesh/byteorder.h | 599 +++++++ lib/bt/esp_ble_mesh/common/include/mesh/common.h | 62 + lib/bt/esp_ble_mesh/common/include/mesh/compiler.h | 80 + lib/bt/esp_ble_mesh/common/include/mesh/config.h | 61 + lib/bt/esp_ble_mesh/common/include/mesh/dlist.h | 498 ++++++ lib/bt/esp_ble_mesh/common/include/mesh/ffs.h | 60 + lib/bt/esp_ble_mesh/common/include/mesh/kernel.h | 59 + lib/bt/esp_ble_mesh/common/include/mesh/mutex.h | 54 + lib/bt/esp_ble_mesh/common/include/mesh/slist.h | 467 ++++++ lib/bt/esp_ble_mesh/common/include/mesh/timer.h | 278 ++++ lib/bt/esp_ble_mesh/common/include/mesh/trace.h | 173 ++ lib/bt/esp_ble_mesh/common/include/mesh/types.h | 33 + lib/bt/esp_ble_mesh/common/include/mesh/utils.h | 226 +++ .../esp_ble_mesh/common/include/mesh/utils_loops.h | 1051 ++++++++++++ 16 files changed, 5764 insertions(+) create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/atomic.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/buf.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/byteorder.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/common.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/compiler.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/config.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/dlist.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/ffs.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/kernel.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/mutex.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/slist.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/timer.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/trace.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/types.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/utils.h create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/utils_loops.h (limited to 'lib/bt/esp_ble_mesh/common/include') diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h new file mode 100644 index 00000000..f7283436 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h @@ -0,0 +1,305 @@ +/* atomic operations */ + +/* + * SPDX-FileCopyrightText: 1997-2015 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_ATOMIC_H_ +#define _BLE_MESH_ATOMIC_H_ + +#include "mesh/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef bt_mesh_atomic_t bt_mesh_atomic_val_t; + +/** + * @defgroup atomic_apis Atomic Services APIs + * @ingroup kernel_apis + * @{ + */ + +/** + * + * @brief Atomic increment. + * + * This routine performs an atomic increment by 1 on @a target. + * + * @param target Address of atomic variable. + * + * @return Previous value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target) +{ + return bt_mesh_atomic_add(target, 1); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target); +#endif + +/** + * + * @brief Atomic decrement. + * + * This routine performs an atomic decrement by 1 on @a target. + * + * @param target Address of atomic variable. + * + * @return Previous value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target) +{ + return bt_mesh_atomic_sub(target, 1); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target); +#endif + +/** + * + * @brief Atomic get. + * + * This routine performs an atomic read on @a target. + * + * @param target Address of atomic variable. + * + * @return Value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_get(const bt_mesh_atomic_t *target) +{ + return __atomic_load_n(target, __ATOMIC_SEQ_CST); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_get(const bt_mesh_atomic_t *target); +#endif + +/** + * + * @brief Atomic get-and-set. + * + * This routine atomically sets @a target to @a value and returns + * the previous value of @a target. + * + * @param target Address of atomic variable. + * @param value Value to write to @a target. + * + * @return Previous value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) +{ + /* This builtin, as described by Intel, is not a traditional + * test-and-set operation, but rather an atomic exchange operation. It + * writes value into *ptr, and returns the previous contents of *ptr. + */ + return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value); +#endif + +/** + * + * @brief Atomic bitwise inclusive OR. + * + * This routine atomically sets @a target to the bitwise inclusive OR of + * @a target and @a value. + * + * @param target Address of atomic variable. + * @param value Value to OR. + * + * @return Previous value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_or(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) +{ + return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_or(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value); +#endif + +/** + * + * @brief Atomic bitwise AND. + * + * This routine atomically sets @a target to the bitwise AND of @a target + * and @a value. + * + * @param target Address of atomic variable. + * @param value Value to AND. + * + * @return Previous value of @a target. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) +{ + return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST); +} +#else +extern bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value); +#endif + +/** + * @cond INTERNAL_HIDDEN + */ + +#define BLE_MESH_ATOMIC_BITS (sizeof(bt_mesh_atomic_val_t) * 8) +#define BLE_MESH_ATOMIC_MASK(bit) (1 << ((bit) & (BLE_MESH_ATOMIC_BITS - 1))) +#define BLE_MESH_ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / BLE_MESH_ATOMIC_BITS)) + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @brief Define an array of atomic variables. + * + * This macro defines an array of atomic variables containing at least + * @a num_bits bits. + * + * @note + * If used from file scope, the bits of the array are initialized to zero; + * if used from within a function, the bits are left uninitialized. + * + * @param name Name of array of atomic variables. + * @param num_bits Number of bits needed. + */ +#define BLE_MESH_ATOMIC_DEFINE(name, num_bits) \ + bt_mesh_atomic_t name[1 + ((num_bits) - 1) / BLE_MESH_ATOMIC_BITS] + +/** + * @brief Atomically test a bit. + * + * This routine tests whether bit number @a bit of @a target is set or not. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * + * @return 1 if the bit was set, 0 if it wasn't. + */ +static inline int bt_mesh_atomic_test_bit(const bt_mesh_atomic_t *target, int bit) +{ + bt_mesh_atomic_val_t val = bt_mesh_atomic_get(BLE_MESH_ATOMIC_ELEM(target, bit)); + + return (1 & (val >> (bit & (BLE_MESH_ATOMIC_BITS - 1)))); +} + +/** + * @brief Atomically test and clear a bit. + * + * Atomically clear bit number @a bit of @a target and return its old value. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * + * @return 1 if the bit was set, 0 if it wasn't. + */ +static inline int bt_mesh_atomic_test_and_clear_bit(bt_mesh_atomic_t *target, int bit) +{ + bt_mesh_atomic_val_t mask = BLE_MESH_ATOMIC_MASK(bit); + bt_mesh_atomic_val_t old; + + old = bt_mesh_atomic_and(BLE_MESH_ATOMIC_ELEM(target, bit), ~mask); + + return (old & mask) != 0; +} + +/** + * @brief Atomically set a bit. + * + * Atomically set bit number @a bit of @a target and return its old value. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * + * @return 1 if the bit was set, 0 if it wasn't. + */ +static inline int bt_mesh_atomic_test_and_set_bit(bt_mesh_atomic_t *target, int bit) +{ + bt_mesh_atomic_val_t mask = BLE_MESH_ATOMIC_MASK(bit); + bt_mesh_atomic_val_t old; + + old = bt_mesh_atomic_or(BLE_MESH_ATOMIC_ELEM(target, bit), mask); + + return (old & mask) != 0; +} + +/** + * @brief Atomically clear a bit. + * + * Atomically clear bit number @a bit of @a target. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * + * @return N/A + */ +static inline void bt_mesh_atomic_clear_bit(bt_mesh_atomic_t *target, int bit) +{ + bt_mesh_atomic_val_t mask = BLE_MESH_ATOMIC_MASK(bit); + + (void)bt_mesh_atomic_and(BLE_MESH_ATOMIC_ELEM(target, bit), ~mask); +} + +/** + * @brief Atomically set a bit. + * + * Atomically set bit number @a bit of @a target. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * + * @return N/A + */ +static inline void bt_mesh_atomic_set_bit(bt_mesh_atomic_t *target, int bit) +{ + bt_mesh_atomic_val_t mask = BLE_MESH_ATOMIC_MASK(bit); + + (void)bt_mesh_atomic_or(BLE_MESH_ATOMIC_ELEM(target, bit), mask); +} + +/** + * @brief Atomically set a bit to a given value. + * + * Atomically set bit number @a bit of @a target to value @a val. + * The target may be a single atomic variable or an array of them. + * + * @param target Address of atomic variable or array. + * @param bit Bit number (starting from 0). + * @param val true for 1, false for 0. + * + * @return N/A + */ +static inline void bt_mesh_atomic_set_bit_to(bt_mesh_atomic_t *target, int bit, bool val) +{ + bt_mesh_atomic_val_t mask = BLE_MESH_ATOMIC_MASK(bit); + + if (val) { + (void)bt_mesh_atomic_or(BLE_MESH_ATOMIC_ELEM(target, bit), mask); + } else { + (void)bt_mesh_atomic_and(BLE_MESH_ATOMIC_ELEM(target, bit), ~mask); + } +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_ATOMIC_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/buf.h b/lib/bt/esp_ble_mesh/common/include/mesh/buf.h new file mode 100644 index 00000000..da4200a0 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/buf.h @@ -0,0 +1,1758 @@ +/** @file + * @brief Buffer management. + */ + +/* + * SPDX-FileCopyrightText: 2015 Intel Corporation + * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BLE_MESH_BUF_H_ +#define _BLE_MESH_BUF_H_ + +#include "mesh/config.h" +#include "mesh/types.h" +#include "mesh/slist.h" +#include "mesh/compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Unaligned access */ +#define UNALIGNED_GET(p) \ +__extension__ ({ \ + struct __attribute__((__packed__)) { \ + __typeof__(*(p)) __v; \ + } *__p = (__typeof__(__p)) (p); \ + __p->__v; \ +}) + +#define BLE_MESH_NET_BUF_USER_DATA_SIZE 4 + +/** + * @brief Network buffer library + * @defgroup net_buf Network Buffer Library + * @ingroup networking + * @{ + */ + +/* Alignment needed for various parts of the buffer definition */ +#define __net_buf_align __aligned(sizeof(int)) + +/** + * @def NET_BUF_SIMPLE_DEFINE + * @brief Define a net_buf_simple stack variable. + * + * This is a helper macro which is used to define a net_buf_simple object + * on the stack. + * + * @param _name Name of the net_buf_simple object. + * @param _size Maximum data storage for the buffer. + */ +#define NET_BUF_SIMPLE_DEFINE(_name, _size) \ + uint8_t net_buf_data_##_name[_size]; \ + struct net_buf_simple _name = { \ + .data = net_buf_data_##_name, \ + .len = 0, \ + .size = _size, \ + .__buf = net_buf_data_##_name, \ + } + +/** + * @def NET_BUF_SIMPLE_DEFINE_STATIC + * @brief Define a static net_buf_simple variable. + * + * This is a helper macro which is used to define a static net_buf_simple + * object. + * + * @param _name Name of the net_buf_simple object. + * @param _size Maximum data storage for the buffer. + */ +#define NET_BUF_SIMPLE_DEFINE_STATIC(_name, _size) \ + static uint8_t net_buf_data_##_name[_size]; \ + static struct net_buf_simple _name = { \ + .data = net_buf_data_##_name, \ + .len = 0, \ + .size = _size, \ + .__buf = net_buf_data_##_name, \ + } + +/** + * @brief Simple network buffer representation. + * + * This is a simpler variant of the net_buf object (in fact net_buf uses + * net_buf_simple internally). It doesn't provide any kind of reference + * counting, user data, dynamic allocation, or in general the ability to + * pass through kernel objects such as FIFOs. + * + * The main use of this is for scenarios where the meta-data of the normal + * net_buf isn't needed and causes too much overhead. This could be e.g. + * when the buffer only needs to be allocated on the stack or when the + * access to and lifetime of the buffer is well controlled and constrained. + */ +struct net_buf_simple { + /** Pointer to the start of data in the buffer. */ + uint8_t *data; + + /** Length of the data behind the data pointer. */ + uint16_t len; + + /** Amount of data that this buffer can store. */ + uint16_t size; + + /** Start of the data storage. Not to be accessed directly + * (the data pointer should be used instead). + */ + uint8_t *__buf; +}; + +/** + * @def NET_BUF_SIMPLE + * @brief Define a net_buf_simple stack variable and get a pointer to it. + * + * This is a helper macro which is used to define a net_buf_simple object on + * the stack and the get a pointer to it as follows: + * + * struct net_buf_simple *my_buf = NET_BUF_SIMPLE(10); + * + * After creating the object it needs to be initialized by calling + * net_buf_simple_init(). + * + * @param _size Maximum data storage for the buffer. + * + * @return Pointer to stack-allocated net_buf_simple object. + */ +#define NET_BUF_SIMPLE(_size) \ + ((struct net_buf_simple *)(&(struct { \ + struct net_buf_simple buf; \ + uint8_t data[_size] __net_buf_align; \ + }) { \ + .buf.size = _size, \ + .buf.__buf = NULL, \ + })) + +/** + * @brief Initialize a net_buf_simple object. + * + * This needs to be called after creating a net_buf_simple object using + * the NET_BUF_SIMPLE macro. + * + * @param buf Buffer to initialize. + * @param reserve_head Headroom to reserve. + */ +static inline void net_buf_simple_init(struct net_buf_simple *buf, + size_t reserve_head) +{ + if (!buf->__buf) { + buf->__buf = (uint8_t *)buf + sizeof(*buf); + } + + buf->data = buf->__buf + reserve_head; + buf->len = 0; +} + +/** + * @brief Initialize a net_buf_simple object with data. + * + * Initialized buffer object with external data. + * + * @param buf Buffer to initialize. + * @param data External data pointer + * @param size Amount of data the pointed data buffer if able to fit. + */ +void net_buf_simple_init_with_data(struct net_buf_simple *buf, + void *data, size_t size); + +/** + * @brief Reset buffer + * + * Reset buffer data so it can be reused for other purposes. + * + * @param buf Buffer to reset. + */ +static inline void net_buf_simple_reset(struct net_buf_simple *buf) +{ + buf->len = 0; + buf->data = buf->__buf; +} + +/** + * Clone buffer state, using the same data buffer. + * + * Initializes a buffer to point to the same data as an existing buffer. + * Allows operations on the same data without altering the length and + * offset of the original. + * + * @param original Buffer to clone. + * @param clone The new clone. + */ +void net_buf_simple_clone(const struct net_buf_simple *original, + struct net_buf_simple *clone); + +/** + * @brief Prepare data to be added at the end of the buffer + * + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param len Number of bytes to increment the length with. + * + * @return The original tail of the buffer. + */ +void *net_buf_simple_add(struct net_buf_simple *buf, size_t len); + +/** + * @brief Copy given number of bytes from memory to the end of the buffer + * + * Increments the data length of the buffer to account for more data at the + * end. + * + * @param buf Buffer to update. + * @param mem Location of data to be added. + * @param len Length of data to be added + * + * @return The original tail of the buffer. + */ +void *net_buf_simple_add_mem(struct net_buf_simple *buf, const void *mem, + size_t len); + +/** + * @brief Add (8-bit) byte at the end of the buffer + * + * Increments the data length of the buffer to account for more data at the + * end. + * + * @param buf Buffer to update. + * @param val byte value to be added. + * + * @return Pointer to the value added + */ +uint8_t *net_buf_simple_add_u8(struct net_buf_simple *buf, uint8_t val); + +/** + * @brief Add 16-bit value at the end of the buffer + * + * Adds 16-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 16-bit value to be added. + */ +void net_buf_simple_add_le16(struct net_buf_simple *buf, uint16_t val); + +/** + * @brief Add 16-bit value at the end of the buffer + * + * Adds 16-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 16-bit value to be added. + */ +void net_buf_simple_add_be16(struct net_buf_simple *buf, uint16_t val); + +/** + * @brief Add 24-bit value at the end of the buffer + * + * Adds 24-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 24-bit value to be added. + */ +void net_buf_simple_add_le24(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Add 24-bit value at the end of the buffer + * + * Adds 24-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 24-bit value to be added. + */ +void net_buf_simple_add_be24(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Add 32-bit value at the end of the buffer + * + * Adds 32-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 32-bit value to be added. + */ +void net_buf_simple_add_le32(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Add 32-bit value at the end of the buffer + * + * Adds 32-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 32-bit value to be added. + */ +void net_buf_simple_add_be32(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Add 48-bit value at the end of the buffer + * + * Adds 48-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 48-bit value to be added. + */ +void net_buf_simple_add_le48(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Add 48-bit value at the end of the buffer + * + * Adds 48-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 48-bit value to be added. + */ +void net_buf_simple_add_be48(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Add 64-bit value at the end of the buffer + * + * Adds 64-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 64-bit value to be added. + */ +void net_buf_simple_add_le64(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Add 64-bit value at the end of the buffer + * + * Adds 64-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 64-bit value to be added. + */ +void net_buf_simple_add_be64(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Push data to the beginning of the buffer. + * + * Modifies the data pointer and buffer length to account for more data + * in the beginning of the buffer. + * + * @param buf Buffer to update. + * @param len Number of bytes to add to the beginning. + * + * @return The new beginning of the buffer data. + */ +void *net_buf_simple_push(struct net_buf_simple *buf, size_t len); + +/** + * @brief Push 16-bit value to the beginning of the buffer + * + * Adds 16-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 16-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_le16(struct net_buf_simple *buf, uint16_t val); + +/** + * @brief Push 16-bit value to the beginning of the buffer + * + * Adds 16-bit value in big endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 16-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_be16(struct net_buf_simple *buf, uint16_t val); + +/** + * @brief Push 8-bit value to the beginning of the buffer + * + * Adds 8-bit value the beginning of the buffer. + * + * @param buf Buffer to update. + * @param val 8-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_u8(struct net_buf_simple *buf, uint8_t val); + +/** + * @brief Push 24-bit value to the beginning of the buffer + * + * Adds 24-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 24-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_le24(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Push 24-bit value to the beginning of the buffer + * + * Adds 24-bit value in big endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 24-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_be24(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Push 32-bit value to the beginning of the buffer + * + * Adds 32-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 32-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_le32(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Push 32-bit value to the beginning of the buffer + * + * Adds 32-bit value in big endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 32-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_be32(struct net_buf_simple *buf, uint32_t val); + +/** + * @brief Push 48-bit value to the beginning of the buffer + * + * Adds 48-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 48-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_le48(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Push 48-bit value to the beginning of the buffer + * + * Adds 48-bit value in big endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 48-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_be48(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Push 64-bit value to the beginning of the buffer + * + * Adds 64-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 64-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_le64(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Push 64-bit value to the beginning of the buffer + * + * Adds 64-bit value in big endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 64-bit value to be pushed to the buffer. + */ +void net_buf_simple_push_be64(struct net_buf_simple *buf, uint64_t val); + +/** + * @brief Remove data from the beginning of the buffer. + * + * Removes data from the beginning of the buffer by modifying the data + * pointer and buffer length. + * + * @param buf Buffer to update. + * @param len Number of bytes to remove. + * + * @return New beginning of the buffer data. + */ +void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len); + +/** + * @brief Remove data from the beginning of the buffer. + * + * Removes data from the beginning of the buffer by modifying the data + * pointer and buffer length. + * + * @param buf Buffer to update. + * @param len Number of bytes to remove. + * + * @return Pointer to the old location of the buffer data. + */ +void *net_buf_simple_pull_mem(struct net_buf_simple *buf, size_t len); + +/** + * @brief Remove a 8-bit value from the beginning of the buffer + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 8-bit values. + * + * @param buf A valid pointer on a buffer. + * + * @return The 8-bit removed value + */ +uint8_t net_buf_simple_pull_u8(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 16 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 16-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 16-bit value converted from little endian to host endian. + */ +uint16_t net_buf_simple_pull_le16(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 16 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 16-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 16-bit value converted from big endian to host endian. + */ +uint16_t net_buf_simple_pull_be16(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 24 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 24-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 24-bit value converted from little endian to host endian. + */ +uint32_t net_buf_simple_pull_le24(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 24 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 24-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 24-bit value converted from big endian to host endian. + */ +uint32_t net_buf_simple_pull_be24(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 32 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 32-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 32-bit value converted from little endian to host endian. + */ +uint32_t net_buf_simple_pull_le32(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 32 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 32-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 32-bit value converted from big endian to host endian. + */ +uint32_t net_buf_simple_pull_be32(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 48 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 48-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 48-bit value converted from little endian to host endian. + */ +uint64_t net_buf_simple_pull_le48(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 48 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 48-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 48-bit value converted from big endian to host endian. + */ +uint64_t net_buf_simple_pull_be48(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 64 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 64-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 64-bit value converted from little endian to host endian. + */ +uint64_t net_buf_simple_pull_le64(struct net_buf_simple *buf); + +/** + * @brief Remove and convert 64 bits from the beginning of the buffer. + * + * Same idea as with net_buf_simple_pull(), but a helper for operating + * on 64-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 64-bit value converted from big endian to host endian. + */ +uint64_t net_buf_simple_pull_be64(struct net_buf_simple *buf); + +/** + * @brief Get the tail pointer for a buffer. + * + * Get a pointer to the end of the data in a buffer. + * + * @param buf Buffer. + * + * @return Tail pointer for the buffer. + */ +static inline uint8_t *net_buf_simple_tail(struct net_buf_simple *buf) +{ + return buf->data + buf->len; +} + +/** + * @brief Check buffer headroom. + * + * Check how much free space there is in the beginning of the buffer. + * + * buf A valid pointer on a buffer + * + * @return Number of bytes available in the beginning of the buffer. + */ +size_t net_buf_simple_headroom(struct net_buf_simple *buf); + +/** + * @brief Check buffer tailroom. + * + * Check how much free space there is at the end of the buffer. + * + * @param buf A valid pointer on a buffer + * + * @return Number of bytes available at the end of the buffer. + */ +size_t net_buf_simple_tailroom(struct net_buf_simple *buf); + +/** + * @brief Parsing state of a buffer. + * + * This is used for temporarily storing the parsing state of a buffer + * while giving control of the parsing to a routine which we don't + * control. + */ +struct net_buf_simple_state { + /** Offset of the data pointer from the beginning of the storage */ + uint16_t offset; + /** Length of data */ + uint16_t len; +}; + +/** + * @brief Save the parsing state of a buffer. + * + * Saves the parsing state of a buffer so it can be restored later. + * + * @param buf Buffer from which the state should be saved. + * @param state Storage for the state. + */ +static inline void net_buf_simple_save(struct net_buf_simple *buf, + struct net_buf_simple_state *state) +{ + state->offset = net_buf_simple_headroom(buf); + state->len = buf->len; +} + +/** + * @brief Restore the parsing state of a buffer. + * + * Restores the parsing state of a buffer from a state previously stored + * by net_buf_simple_save(). + * + * @param buf Buffer to which the state should be restored. + * @param state Stored state. + */ +static inline void net_buf_simple_restore(struct net_buf_simple *buf, + struct net_buf_simple_state *state) +{ + buf->data = buf->__buf + state->offset; + buf->len = state->len; +} + +/** + * @brief Initialize buffer with the given headroom. + * + * The buffer is not expected to contain any data when this API is called. + * + * @param buf Buffer to initialize. + * @param reserve How much headroom to reserve. + */ +void net_buf_simple_reserve(struct net_buf_simple *buf, size_t reserve); + +/** + * Flag indicating that the buffer has associated fragments. Only used + * internally by the buffer handling code while the buffer is inside a + * FIFO, meaning this never needs to be explicitly set or unset by the + * net_buf API user. As long as the buffer is outside of a FIFO, i.e. + * in practice always for the user for this API, the buf->frags pointer + * should be used instead. + */ +#define NET_BUF_FRAGS BIT(0) + +/** + * @brief Network buffer representation. + * + * This struct is used to represent network buffers. Such buffers are + * normally defined through the NET_BUF_POOL_*_DEFINE() APIs and allocated + * using the net_buf_alloc() API. + */ +struct net_buf { + union { + /** Allow placing the buffer into sys_slist_t */ + sys_snode_t node; + + /** Fragments associated with this buffer. */ + struct net_buf *frags; + }; + + /** Reference count. */ + uint8_t ref; + + /** Bit-field of buffer flags. */ + uint8_t flags; + + /** Where the buffer should go when freed up. */ + struct net_buf_pool *pool; + + /* Union for convenience access to the net_buf_simple members, also + * preserving the old API. + */ + union { + /* The ABI of this struct must match net_buf_simple */ + struct { + /** Pointer to the start of data in the buffer. */ + uint8_t *data; + + /** Length of the data behind the data pointer. */ + uint16_t len; + + /** Amount of data that this buffer can store. */ + uint16_t size; + + /** Start of the data storage. Not to be accessed + * directly (the data pointer should be used + * instead). + */ + uint8_t *__buf; + }; + + struct net_buf_simple b; + }; + + /** System metadata for this buffer. */ + uint8_t user_data[BLE_MESH_NET_BUF_USER_DATA_SIZE] __net_buf_align; +}; + +struct net_buf_data_cb { + uint8_t *(*alloc)(struct net_buf *buf, size_t *size, int32_t timeout); + uint8_t *(*ref)(struct net_buf *buf, uint8_t *data); + void (*unref)(struct net_buf *buf, uint8_t *data); +}; + +struct net_buf_data_alloc { + const struct net_buf_data_cb *cb; + void *alloc_data; +}; + +struct net_buf_pool { + /** Number of buffers in pool */ + const uint16_t buf_count; + + /** Number of uninitialized buffers */ + uint16_t uninit_count; + +#if CONFIG_BLE_MESH_NET_BUF_POOL_USAGE + /** Amount of available buffers in the pool. */ + int16_t avail_count; + + /** Total size of the pool. */ + const uint16_t pool_size; + + /** Name of the pool. Used when printing pool information. */ + const char *name; +#endif /* CONFIG_BLE_MESH_NET_BUF_POOL_USAGE */ + + /** Optional destroy callback when buffer is freed. */ + void (*const destroy)(struct net_buf *buf); + + /** Data allocation handlers. */ + const struct net_buf_data_alloc *alloc; + + /** Helper to access the start of storage (for net_buf_pool_init) */ + struct net_buf *const __bufs; +}; + +#if CONFIG_BLE_MESH_NET_BUF_POOL_USAGE +#define NET_BUF_POOL_INITIALIZER(_pool, _alloc, _bufs, _count, _destroy) \ + { \ + .buf_count = _count, \ + .uninit_count = _count, \ + .avail_count = _count, \ + .name = STRINGIFY(_pool), \ + .destroy = _destroy, \ + .alloc = _alloc, \ + .__bufs = (struct net_buf *)_bufs, \ + } +#else +#define NET_BUF_POOL_INITIALIZER(_pool, _alloc, _bufs, _count, _destroy) \ + { \ + .buf_count = _count, \ + .uninit_count = _count, \ + .destroy = _destroy, \ + .alloc = _alloc, \ + .__bufs = (struct net_buf *)_bufs, \ + } +#endif /* CONFIG_BLE_MESH_NET_BUF_POOL_USAGE */ + +struct net_buf_pool_fixed { + size_t data_size; + uint8_t *data_pool; +}; + +/** @cond INTERNAL_HIDDEN */ +extern const struct net_buf_data_cb net_buf_fixed_cb; + +/** + * @def NET_BUF_POOL_FIXED_DEFINE + * @brief Define a new pool for buffers based on fixed-size data + * + * Defines a net_buf_pool struct and the necessary memory storage (array of + * structs) for the needed amount of buffers. After this, the buffers can be + * accessed from the pool through net_buf_alloc. The pool is defined as a + * static variable, so if it needs to be exported outside the current module + * this needs to happen with the help of a separate pointer rather than an + * extern declaration. + * + * The data payload of the buffers will be allocated from a byte array + * of fixed sized chunks. This kind of pool does not support blocking on + * the data allocation, so the timeout passed to net_buf_alloc will be + * always treated as K_NO_WAIT when trying to allocate the data. This means + * that allocation failures, i.e. NULL returns, must always be handled + * cleanly. + * + * If provided with a custom destroy callback, this callback is + * responsible for eventually calling net_buf_destroy() to complete the + * process of returning the buffer to the pool. + * + * @param _name Name of the pool variable. + * @param _count Number of buffers in the pool. + * @param _data_size Maximum data payload per buffer. + * @param _destroy Optional destroy callback when buffer is freed. + */ +#define NET_BUF_POOL_FIXED_DEFINE(_name, _count, _data_size, _destroy) \ + static struct net_buf net_buf_##_name[_count]; \ + static uint8_t net_buf_data_##_name[_count][_data_size]; \ + static const struct net_buf_pool_fixed net_buf_fixed_##_name = { \ + .data_size = _data_size, \ + .data_pool = (uint8_t *)net_buf_data_##_name, \ + }; \ + static const struct net_buf_data_alloc net_buf_fixed_alloc_##_name = { \ + .cb = &net_buf_fixed_cb, \ + .alloc_data = (void *)&net_buf_fixed_##_name, \ + }; \ + struct net_buf_pool _name __net_buf_align \ + __in_section(_net_buf_pool, static, _name) = \ + NET_BUF_POOL_INITIALIZER(_name, &net_buf_fixed_alloc_##_name, \ + net_buf_##_name, _count, _destroy) + +/** + * @def NET_BUF_POOL_DEFINE + * @brief Define a new pool for buffers + * + * Defines a net_buf_pool struct and the necessary memory storage (array of + * structs) for the needed amount of buffers. After this,the buffers can be + * accessed from the pool through net_buf_alloc. The pool is defined as a + * static variable, so if it needs to be exported outside the current module + * this needs to happen with the help of a separate pointer rather than an + * extern declaration. + * + * If provided with a custom destroy callback this callback is + * responsible for eventually calling net_buf_destroy() to complete the + * process of returning the buffer to the pool. + * + * @param _name Name of the pool variable. + * @param _count Number of buffers in the pool. + * @param _size Maximum data size for each buffer. + * @param _ud_size Amount of user data space to reserve. + * @param _destroy Optional destroy callback when buffer is freed. + */ +#define NET_BUF_POOL_DEFINE(_name, _count, _size, _ud_size, _destroy) \ + NET_BUF_POOL_FIXED_DEFINE(_name, _count, _size, _destroy) + +/** + * @brief Get a zero-based index for a buffer. + * + * This function will translate a buffer into a zero-based index, + * based on its placement in its buffer pool. This can be useful if you + * want to associate an external array of meta-data contexts with the + * buffers of a pool. + * + * @param buf Network buffer. + * + * @return Zero-based index for the buffer. + */ +int net_buf_id(struct net_buf *buf); + +/** + * @brief Allocate a new fixed buffer from a pool. + * + * @param pool Which pool to allocate the buffer from. + * @param timeout Affects the action taken should the pool be empty. + * If K_NO_WAIT, then return immediately. If K_FOREVER, then + * wait as long as necessary. Otherwise, wait up to the specified + * number of milliseconds before timing out. Note that some types + * of data allocators do not support blocking (such as the HEAP + * type). In this case it's still possible for net_buf_alloc() to + * fail (return NULL) even if it was given K_FOREVER. + * + * @return New buffer or NULL if out of buffers. + */ +#if CONFIG_BLE_MESH_NET_BUF_LOG +struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool, int32_t timeout, + const char *func, int line); +#define net_buf_alloc_fixed(_pool, _timeout) \ + net_buf_alloc_fixed_debug(_pool, _timeout, __func__, __LINE__) +#else +struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool, int32_t timeout); +#endif + +/** + * @def net_buf_alloc + * + * @copydetails net_buf_alloc_fixed + */ +#define net_buf_alloc(pool, timeout) net_buf_alloc_fixed(pool, timeout) + +/** + * @brief Reset buffer + * + * Reset buffer data and flags so it can be reused for other purposes. + * + * @param buf Buffer to reset. + */ +void net_buf_reset(struct net_buf *buf); + +/** + * @def net_buf_reserve + * @brief Initialize buffer with the given headroom. + * + * The buffer is not expected to contain any data when this API is called. + * + * @param buf Buffer to initialize. + * @param reserve How much headroom to reserve. + */ +#define net_buf_reserve(buf, reserve) net_buf_simple_reserve(&(buf)->b, reserve) + +/** + * @brief Put a buffer into a list + * + * Put a buffer to the end of a list. If the buffer contains follow-up + * fragments this function will take care of inserting them as well + * into the list. + * + * @param list Which list to append the buffer to. + * @param buf Buffer. + */ +void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf); + +/** + * @brief Get a buffer from a list. + * + * Get buffer from a list. If the buffer had any fragments, these will + * automatically be recovered from the list as well and be placed to + * the buffer's fragment list. + * + * @param list Which list to take the buffer from. + * + * @return New buffer or NULL if the FIFO is empty. + */ +struct net_buf *net_buf_slist_get(sys_slist_t *list); + +/** + * @brief Decrements the reference count of a buffer. + * + * Decrements the reference count of a buffer and puts it back into the + * pool if the count reaches zero. + * + * @param buf A valid pointer on a buffer + */ +#if CONFIG_BLE_MESH_NET_BUF_LOG +void net_buf_unref_debug(struct net_buf *buf, const char *func, int line); +#define net_buf_unref(_buf) \ + net_buf_unref_debug(_buf, __func__, __LINE__) +#else +void net_buf_unref(struct net_buf *buf); +#endif + +/** + * @brief Increment the reference count of a buffer. + * + * @param buf A valid pointer on a buffer + * + * @return the buffer newly referenced + */ +struct net_buf *net_buf_ref(struct net_buf *buf); + +/** + * @brief Get a pointer to the user data of a buffer. + * + * @param buf A valid pointer on a buffer + * + * @return Pointer to the user data of the buffer. + */ +static inline void *net_buf_user_data(struct net_buf *buf) +{ + return (void *)buf->user_data; +} + +/** + * @def net_buf_add + * @brief Prepare data to be added at the end of the buffer + * + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param len Number of bytes to increment the length with. + * + * @return The original tail of the buffer. + */ +#define net_buf_add(buf, len) net_buf_simple_add(&(buf)->b, len) + +/** + * @def net_buf_add_mem + * @brief Copy bytes from memory to the end of the buffer + * + * Copies the given number of bytes to the end of the buffer. Increments the + * data length of the buffer to account for more data at the end. + * + * @param buf Buffer to update. + * @param mem Location of data to be added. + * @param len Length of data to be added + * + * @return The original tail of the buffer. + */ +#define net_buf_add_mem(buf, mem, len) net_buf_simple_add_mem(&(buf)->b, mem, len) + +/** + * @def net_buf_add_u8 + * @brief Add (8-bit) byte at the end of the buffer + * + * Adds a byte at the end of the buffer. Increments the data length of + * the buffer to account for more data at the end. + * + * @param buf Buffer to update. + * @param val byte value to be added. + * + * @return Pointer to the value added + */ +#define net_buf_add_u8(buf, val) net_buf_simple_add_u8(&(buf)->b, val) + +/** + * @def net_buf_add_le16 + * @brief Add 16-bit value at the end of the buffer + * + * Adds 16-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 16-bit value to be added. + */ +#define net_buf_add_le16(buf, val) net_buf_simple_add_le16(&(buf)->b, val) + +/** + * @def net_buf_add_be16 + * @brief Add 16-bit value at the end of the buffer + * + * Adds 16-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 16-bit value to be added. + */ +#define net_buf_add_be16(buf, val) net_buf_simple_add_be16(&(buf)->b, val) + +/** + * @def net_buf_add_le24 + * @brief Add 24-bit value at the end of the buffer + * + * Adds 24-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 24-bit value to be added. + */ +#define net_buf_add_le24(buf, val) net_buf_simple_add_le24(&(buf)->b, val) + +/** + * @def net_buf_add_be24 + * @brief Add 24-bit value at the end of the buffer + * + * Adds 24-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 24-bit value to be added. + */ +#define net_buf_add_be24(buf, val) net_buf_simple_add_be24(&(buf)->b, val) + +/** + * @def net_buf_add_le32 + * @brief Add 32-bit value at the end of the buffer + * + * Adds 32-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 32-bit value to be added. + */ +#define net_buf_add_le32(buf, val) net_buf_simple_add_le32(&(buf)->b, val) + +/** + * @def net_buf_add_be32 + * @brief Add 32-bit value at the end of the buffer + * + * Adds 32-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 32-bit value to be added. + */ +#define net_buf_add_be32(buf, val) net_buf_simple_add_be32(&(buf)->b, val) + +/** + * @def net_buf_add_le48 + * @brief Add 48-bit value at the end of the buffer + * + * Adds 48-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 48-bit value to be added. + */ +#define net_buf_add_le48(buf, val) net_buf_simple_add_le48(&(buf)->b, val) + +/** + * @def net_buf_add_be48 + * @brief Add 48-bit value at the end of the buffer + * + * Adds 48-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 48-bit value to be added. + */ +#define net_buf_add_be48(buf, val) net_buf_simple_add_be48(&(buf)->b, val) + +/** + * @def net_buf_add_le64 + * @brief Add 64-bit value at the end of the buffer + * + * Adds 64-bit value in little endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 64-bit value to be added. + */ +#define net_buf_add_le64(buf, val) net_buf_simple_add_le64(&(buf)->b, val) + +/** + * @def net_buf_add_be64 + * @brief Add 64-bit value at the end of the buffer + * + * Adds 64-bit value in big endian format at the end of buffer. + * Increments the data length of a buffer to account for more data + * at the end. + * + * @param buf Buffer to update. + * @param val 64-bit value to be added. + */ +#define net_buf_add_be64(buf, val) net_buf_simple_add_be64(&(buf)->b, val) + +/** + * @def net_buf_push + * @brief Push data to the beginning of the buffer. + * + * Modifies the data pointer and buffer length to account for more data + * in the beginning of the buffer. + * + * @param buf Buffer to update. + * @param len Number of bytes to add to the beginning. + * + * @return The new beginning of the buffer data. + */ +#define net_buf_push(buf, len) net_buf_simple_push(&(buf)->b, len) + +/** + * @def net_buf_push_le16 + * @brief Push 16-bit value to the beginning of the buffer + * + * Adds 16-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 16-bit value to be pushed to the buffer. + */ +#define net_buf_push_le16(buf, val) net_buf_simple_push_le16(&(buf)->b, val) + +/** + * @def net_buf_push_be16 + * @brief Push 16-bit value to the beginning of the buffer + * + * Adds 16-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 16-bit value to be pushed to the buffer. + */ +#define net_buf_push_be16(buf, val) net_buf_simple_push_be16(&(buf)->b, val) + +/** + * @def net_buf_push_u8 + * @brief Push 8-bit value to the beginning of the buffer + * + * Adds 8-bit value the beginning of the buffer. + * + * @param buf Buffer to update. + * @param val 8-bit value to be pushed to the buffer. + */ +#define net_buf_push_u8(buf, val) net_buf_simple_push_u8(&(buf)->b, val) + +/** + * @def net_buf_push_le24 + * @brief Push 24-bit value to the beginning of the buffer + * + * Adds 24-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 24-bit value to be pushed to the buffer. + */ +#define net_buf_push_le24(buf, val) net_buf_simple_push_le24(&(buf)->b, val) + +/** + * @def net_buf_push_be24 + * @brief Push 24-bit value to the beginning of the buffer + * + * Adds 24-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 24-bit value to be pushed to the buffer. + */ +#define net_buf_push_be24(buf, val) net_buf_simple_push_be24(&(buf)->b, val) + +/** + * @def net_buf_push_le32 + * @brief Push 32-bit value to the beginning of the buffer + * + * Adds 32-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 32-bit value to be pushed to the buffer. + */ +#define net_buf_push_le32(buf, val) net_buf_simple_push_le32(&(buf)->b, val) + +/** + * @def net_buf_push_be32 + * @brief Push 32-bit value to the beginning of the buffer + * + * Adds 32-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 32-bit value to be pushed to the buffer. + */ +#define net_buf_push_be32(buf, val) net_buf_simple_push_be32(&(buf)->b, val) + +/** + * @def net_buf_push_le48 + * @brief Push 48-bit value to the beginning of the buffer + * + * Adds 48-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 48-bit value to be pushed to the buffer. + */ +#define net_buf_push_le48(buf, val) net_buf_simple_push_le48(&(buf)->b, val) + +/** + * @def net_buf_push_be48 + * @brief Push 48-bit value to the beginning of the buffer + * + * Adds 48-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 48-bit value to be pushed to the buffer. + */ +#define net_buf_push_be48(buf, val) net_buf_simple_push_be48(&(buf)->b, val) + +/** + * @def net_buf_push_le64 + * @brief Push 64-bit value to the beginning of the buffer + * + * Adds 64-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 64-bit value to be pushed to the buffer. + */ +#define net_buf_push_le64(buf, val) net_buf_simple_push_le64(&(buf)->b, val) + +/** + * @def net_buf_push_be64 + * @brief Push 64-bit value to the beginning of the buffer + * + * Adds 64-bit value in little endian format to the beginning of the + * buffer. + * + * @param buf Buffer to update. + * @param val 64-bit value to be pushed to the buffer. + */ +#define net_buf_push_be64(buf, val) net_buf_simple_push_be64(&(buf)->b, val) + +/** + * @def net_buf_pull + * @brief Remove data from the beginning of the buffer. + * + * Removes data from the beginning of the buffer by modifying the data + * pointer and buffer length. + * + * @param buf Buffer to update. + * @param len Number of bytes to remove. + * + * @return New beginning of the buffer data. + */ +#define net_buf_pull(buf, len) net_buf_simple_pull(&(buf)->b, len) + +/** + * @def net_buf_pull_mem + * @brief Remove data from the beginning of the buffer. + * + * Removes data from the beginning of the buffer by modifying the data + * pointer and buffer length. + * + * @param buf Buffer to update. + * @param len Number of bytes to remove. + * + * @return Pointer to the old beginning of the buffer data. + */ +#define net_buf_pull_mem(buf, len) net_buf_simple_pull_mem(&(buf)->b, len) + +/** + * @def net_buf_pull_u8 + * @brief Remove a 8-bit value from the beginning of the buffer + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 8-bit values. + * + * @param buf A valid pointer on a buffer. + * + * @return The 8-bit removed value + */ +#define net_buf_pull_u8(buf) net_buf_simple_pull_u8(&(buf)->b) + +/** + * @def net_buf_pull_le16 + * @brief Remove and convert 16 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 16-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 16-bit value converted from little endian to host endian. + */ +#define net_buf_pull_le16(buf) net_buf_simple_pull_le16(&(buf)->b) + +/** + * @def net_buf_pull_be16 + * @brief Remove and convert 16 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 16-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 16-bit value converted from big endian to host endian. + */ +#define net_buf_pull_be16(buf) net_buf_simple_pull_be16(&(buf)->b) + +/** + * @def net_buf_pull_le24 + * @brief Remove and convert 24 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 24-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 24-bit value converted from little endian to host endian. + */ +#define net_buf_pull_le24(buf) net_buf_simple_pull_le24(&(buf)->b) + +/** + * @def net_buf_pull_be24 + * @brief Remove and convert 24 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 24-bit big endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 24-bit value converted from big endian to host endian. + */ +#define net_buf_pull_be24(buf) net_buf_simple_pull_be24(&(buf)->b) + +/** + * @def net_buf_pull_le32 + * @brief Remove and convert 32 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 32-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 32-bit value converted from little endian to host endian. + */ +#define net_buf_pull_le32(buf) net_buf_simple_pull_le32(&(buf)->b) + +/** + * @def net_buf_pull_be32 + * @brief Remove and convert 32 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 32-bit big endian data. + * + * @param buf A valid pointer on a buffer + * + * @return 32-bit value converted from big endian to host endian. + */ +#define net_buf_pull_be32(buf) net_buf_simple_pull_be32(&(buf)->b) + +/** + * @def net_buf_pull_le48 + * @brief Remove and convert 48 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 48-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 48-bit value converted from little endian to host endian. + */ +#define net_buf_pull_le48(buf) net_buf_simple_pull_le48(&(buf)->b) + +/** + * @def net_buf_pull_be48 + * @brief Remove and convert 48 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 48-bit big endian data. + * + * @param buf A valid pointer on a buffer + * + * @return 48-bit value converted from big endian to host endian. + */ +#define net_buf_pull_be48(buf) net_buf_simple_pull_be48(&(buf)->b) + +/** + * @def net_buf_pull_le64 + * @brief Remove and convert 64 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 64-bit little endian data. + * + * @param buf A valid pointer on a buffer. + * + * @return 64-bit value converted from little endian to host endian. + */ +#define net_buf_pull_le64(buf) net_buf_simple_pull_le64(&(buf)->b) + +/** + * @def net_buf_pull_be64 + * @brief Remove and convert 64 bits from the beginning of the buffer. + * + * Same idea as with net_buf_pull(), but a helper for operating on + * 64-bit big endian data. + * + * @param buf A valid pointer on a buffer + * + * @return 64-bit value converted from big endian to host endian. + */ +#define net_buf_pull_be64(buf) net_buf_simple_pull_be64(&(buf)->b) + +/** + * @def net_buf_tailroom + * @brief Check buffer tailroom. + * + * Check how much free space there is at the end of the buffer. + * + * @param buf A valid pointer on a buffer + * + * @return Number of bytes available at the end of the buffer. + */ +#define net_buf_tailroom(buf) net_buf_simple_tailroom(&(buf)->b) + +/** + * @def net_buf_headroom + * @brief Check buffer headroom. + * + * Check how much free space there is in the beginning of the buffer. + * + * buf A valid pointer on a buffer + * + * @return Number of bytes available in the beginning of the buffer. + */ +#define net_buf_headroom(buf) net_buf_simple_headroom(&(buf)->b) + +/** + * @def net_buf_tail + * @brief Get the tail pointer for a buffer. + * + * Get a pointer to the end of the data in a buffer. + * + * @param buf Buffer. + * + * @return Tail pointer for the buffer. + */ +#define net_buf_tail(buf) net_buf_simple_tail(&(buf)->b) + +/** + * @brief Find the last fragment in the fragment list. + * + * @return Pointer to last fragment in the list. + */ +struct net_buf *net_buf_frag_last(struct net_buf *frags); + +/** + * @brief Insert a new fragment to a chain of bufs. + * + * Insert a new fragment into the buffer fragments list after the parent. + * + * Note: This function takes ownership of the fragment reference so the + * caller is not required to unref. + * + * @param parent Parent buffer/fragment. + * @param frag Fragment to insert. + */ +void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag); + +/** + * @brief Add a new fragment to the end of a chain of bufs. + * + * Append a new fragment into the buffer fragments list. + * + * Note: This function takes ownership of the fragment reference so the + * caller is not required to unref. + * + * @param head Head of the fragment chain. + * @param frag Fragment to add. + * + * @return New head of the fragment chain. Either head (if head + * was non-NULL) or frag (if head was NULL). + */ +struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag); + +/** + * @brief Delete existing fragment from a chain of bufs. + * + * @param parent Parent buffer/fragment, or NULL if there is no parent. + * @param frag Fragment to delete. + * + * @return Pointer to the buffer following the fragment, or NULL if it + * had no further fragments. + */ +#if CONFIG_BLE_MESH_NET_BUF_LOG +struct net_buf *net_buf_frag_del_debug(struct net_buf *parent, + struct net_buf *frag, + const char *func, int line); +#define net_buf_frag_del(_parent, _frag) \ + net_buf_frag_del_debug(_parent, _frag, __func__, __LINE__) +#else +struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag); +#endif + +/** + * @brief Copy bytes from net_buf chain starting at offset to linear buffer + * + * Copy (extract) @a len bytes from @a src net_buf chain, starting from @a + * offset in it, to a linear buffer @a dst. Return number of bytes actually + * copied, which may be less than requested, if net_buf chain doesn't have + * enough data, or destination buffer is too small. + * + * @param dst Destination buffer + * @param dst_len Destination buffer length + * @param src Source net_buf chain + * @param offset Starting offset to copy from + * @param len Number of bytes to copy + * @return number of bytes actually copied + */ +size_t net_buf_linearize(void *dst, size_t dst_len, + struct net_buf *src, size_t offset, size_t len); + +/** + * @typedef net_buf_allocator_cb + * @brief Network buffer allocator callback. + * + * @details The allocator callback is called when net_buf_append_bytes + * needs to allocate a new net_buf. + * + * @param timeout Affects the action taken should the net buf pool be empty. + * If K_NO_WAIT, then return immediately. If K_FOREVER, then + * wait as long as necessary. Otherwise, wait up to the specified + * number of milliseconds before timing out. + * @param user_data The user data given in net_buf_append_bytes call. + * @return pointer to allocated net_buf or NULL on error. + */ +typedef struct net_buf *(*net_buf_allocator_cb)(int32_t timeout, void *user_data); + +/** + * @brief Append data to a list of net_buf + * + * @details Append data to a net_buf. If there is not enough space in the + * net_buf then more net_buf will be added, unless there are no free net_buf + * and timeout occurs. + * + * @param buf Network buffer. + * @param len Total length of input data + * @param value Data to be added + * @param timeout Timeout is passed to the net_buf allocator callback. + * @param allocate_cb When a new net_buf is required, use this callback. + * @param user_data A user data pointer to be supplied to the allocate_cb. + * This pointer is can be anything from a mem_pool or a net_pkt, the + * logic is left up to the allocate_cb function. + * + * @return Length of data actually added. This may be less than input + * length if other timeout than K_FOREVER was used, and there + * were no free fragments in a pool to accommodate all data. + */ +size_t net_buf_append_bytes(struct net_buf *buf, size_t len, + const void *value, int32_t timeout, + net_buf_allocator_cb allocate_cb, void *user_data); + +/** + * @brief Skip N number of bytes in a net_buf + * + * @details Skip N number of bytes starting from fragment's offset. If the total + * length of data is placed in multiple fragments, this function will skip from + * all fragments until it reaches N number of bytes. Any fully skipped buffers + * are removed from the net_buf list. + * + * @param buf Network buffer. + * @param len Total length of data to be skipped. + * + * @return Pointer to the fragment or + * NULL and pos is 0 after successful skip, + * NULL and pos is 0xffff otherwise. + */ +static inline struct net_buf *net_buf_skip(struct net_buf *buf, size_t len) +{ + while (buf && len--) { + net_buf_pull_u8(buf); + if (!buf->len) { + buf = net_buf_frag_del(NULL, buf); + } + } + + return buf; +} + +/** + * @brief Calculate amount of bytes stored in fragments. + * + * Calculates the total amount of data stored in the given buffer and the + * fragments linked to it. + * + * @param buf Buffer to start off with. + * + * @return Number of bytes in the buffer and its fragments. + */ +static inline size_t net_buf_frags_len(struct net_buf *buf) +{ + size_t bytes = 0; + + while (buf) { + bytes += buf->len; + buf = buf->frags; + } + + return bytes; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_BUF_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/byteorder.h b/lib/bt/esp_ble_mesh/common/include/mesh/byteorder.h new file mode 100644 index 00000000..6926b804 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/byteorder.h @@ -0,0 +1,599 @@ +/* + * SPDX-FileCopyrightText: 2015-2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_BYTEORDER_H_ +#define _BLE_MESH_BYTEORDER_H_ + +#include "mesh/types.h" +#include "mesh/trace.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal helpers only used by the sys_* APIs further below */ +#ifndef __bswap_16 +#define __bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) +#endif + +#ifndef __bswap_24 +#define __bswap_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \ + (((x)) & 0xff00) | \ + (((x) & 0xff) << 16))) +#endif + +#ifndef __bswap_32 +#define __bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \ + (((x) >> 8) & 0xff00) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff) << 24))) +#endif + +#ifndef __bswap_48 +#define __bswap_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \ + (((x) >> 24) & 0xff00) | \ + (((x) >> 8) & 0xff0000) | \ + (((x) & 0xff0000) << 8) | \ + (((x) & 0xff00) << 24) | \ + (((x) & 0xff) << 40))) +#endif + +#ifndef __bswap_64 +#define __bswap_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \ + (((x) >> 40) & 0xff00) | \ + (((x) >> 24) & 0xff0000) | \ + (((x) >> 8) & 0xff000000) | \ + (((x) & 0xff000000) << 8) | \ + (((x) & 0xff0000) << 24) | \ + (((x) & 0xff00) << 40) | \ + (((x) & 0xff) << 56))) +#endif + +/** @def sys_le16_to_cpu + * @brief Convert 16-bit integer from little-endian to host endianness. + * + * @param val 16-bit integer in little-endian format. + * + * @return 16-bit integer in host endianness. + */ + +/** @def sys_cpu_to_le16 + * @brief Convert 16-bit integer from host endianness to little-endian. + * + * @param val 16-bit integer in host endianness. + * + * @return 16-bit integer in little-endian format. + */ + +/** @def sys_le24_to_cpu + * @brief Convert 24-bit integer from little-endian to host endianness. + * + * @param val 24-bit integer in little-endian format. + * + * @return 24-bit integer in host endianness. + */ + +/** @def sys_cpu_to_le24 + * @brief Convert 24-bit integer from host endianness to little-endian. + * + * @param val 24-bit integer in host endianness. + * + * @return 24-bit integer in little-endian format. + */ + +/** @def sys_le32_to_cpu + * @brief Convert 32-bit integer from little-endian to host endianness. + * + * @param val 32-bit integer in little-endian format. + * + * @return 32-bit integer in host endianness. + */ + +/** @def sys_cpu_to_le32 + * @brief Convert 32-bit integer from host endianness to little-endian. + * + * @param val 32-bit integer in host endianness. + * + * @return 32-bit integer in little-endian format. + */ + +/** @def sys_le48_to_cpu + * @brief Convert 48-bit integer from little-endian to host endianness. + * + * @param val 48-bit integer in little-endian format. + * + * @return 48-bit integer in host endianness. + */ + +/** @def sys_cpu_to_le48 + * @brief Convert 48-bit integer from host endianness to little-endian. + * + * @param val 48-bit integer in host endianness. + * + * @return 48-bit integer in little-endian format. + */ + +/** @def sys_be16_to_cpu + * @brief Convert 16-bit integer from big-endian to host endianness. + * + * @param val 16-bit integer in big-endian format. + * + * @return 16-bit integer in host endianness. + */ + +/** @def sys_cpu_to_be16 + * @brief Convert 16-bit integer from host endianness to big-endian. + * + * @param val 16-bit integer in host endianness. + * + * @return 16-bit integer in big-endian format. + */ + +/** @def sys_be24_to_cpu + * @brief Convert 24-bit integer from big-endian to host endianness. + * + * @param val 24-bit integer in big-endian format. + * + * @return 24-bit integer in host endianness. + */ + +/** @def sys_cpu_to_be24 + * @brief Convert 24-bit integer from host endianness to big-endian. + * + * @param val 24-bit integer in host endianness. + * + * @return 24-bit integer in big-endian format. + */ + +/** @def sys_be32_to_cpu + * @brief Convert 32-bit integer from big-endian to host endianness. + * + * @param val 32-bit integer in big-endian format. + * + * @return 32-bit integer in host endianness. + */ + +/** @def sys_cpu_to_be32 + * @brief Convert 32-bit integer from host endianness to big-endian. + * + * @param val 32-bit integer in host endianness. + * + * @return 32-bit integer in big-endian format. + */ + +/** @def sys_be48_to_cpu + * @brief Convert 48-bit integer from big-endian to host endianness. + * + * @param val 48-bit integer in big-endian format. + * + * @return 48-bit integer in host endianness. + */ + +/** @def sys_cpu_to_be48 + * @brief Convert 48-bit integer from host endianness to big-endian. + * + * @param val 48-bit integer in host endianness. + * + * @return 48-bit integer in big-endian format. + */ + +#ifndef sys_le16_to_cpu +#define sys_le16_to_cpu(val) (val) +#endif +#ifndef sys_cpu_to_le16 +#define sys_cpu_to_le16(val) (val) +#endif +#ifndef sys_le24_to_cpu +#define sys_le24_to_cpu(val) (val) +#endif +#ifndef sys_cpu_to_le24 +#define sys_cpu_to_le24(val) (val) +#endif +#ifndef sys_le32_to_cpu +#define sys_le32_to_cpu(val) (val) +#endif +#ifndef sys_cpu_to_le32 +#define sys_cpu_to_le32(val) (val) +#endif +#ifndef sys_le48_to_cpu +#define sys_le48_to_cpu(val) (val) +#endif +#ifndef sys_cpu_to_le48 +#define sys_cpu_to_le48(val) (val) +#endif +#ifndef sys_le64_to_cpu +#define sys_le64_to_cpu(val) (val) +#endif +#ifndef sys_cpu_to_le64 +#define sys_cpu_to_le64(val) (val) +#endif +#ifndef sys_be16_to_cpu +#define sys_be16_to_cpu(val) __bswap_16(val) +#endif +#ifndef sys_cpu_to_be16 +#define sys_cpu_to_be16(val) __bswap_16(val) +#endif +#ifndef sys_be24_to_cpu +#define sys_be24_to_cpu(val) __bswap_24(val) +#endif +#ifndef sys_cpu_to_be24 +#define sys_cpu_to_be24(val) __bswap_24(val) +#endif +#ifndef sys_be32_to_cpu +#define sys_be32_to_cpu(val) __bswap_32(val) +#endif +#ifndef sys_cpu_to_be32 +#define sys_cpu_to_be32(val) __bswap_32(val) +#endif +#ifndef sys_be48_to_cpu +#define sys_be48_to_cpu(val) __bswap_48(val) +#endif +#ifndef sys_cpu_to_be48 +#define sys_cpu_to_be48(val) __bswap_48(val) +#endif +#ifndef sys_be64_to_cpu +#define sys_be64_to_cpu(val) __bswap_64(val) +#endif +#ifndef sys_cpu_to_be64 +#define sys_cpu_to_be64(val) __bswap_64(val) +#endif + +/** + * @brief Put a 16-bit integer as big-endian to arbitrary location. + * + * Put a 16-bit integer, originally in host endianness, to a + * potentially unaligned memory location in big-endian format. + * + * @param val 16-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_be16(uint16_t val, uint8_t dst[2]) +{ + dst[0] = val >> 8; + dst[1] = val; +} + +/** + * @brief Put a 24-bit integer as big-endian to arbitrary location. + * + * Put a 24-bit integer, originally in host endianness, to a + * potentially unaligned memory location in big-endian format. + * + * @param val 24-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_be24(uint32_t val, uint8_t dst[3]) +{ + dst[0] = val >> 16; + sys_put_be16(val, &dst[1]); +} + +/** + * @brief Put a 32-bit integer as big-endian to arbitrary location. + * + * Put a 32-bit integer, originally in host endianness, to a + * potentially unaligned memory location in big-endian format. + * + * @param val 32-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_be32(uint32_t val, uint8_t dst[4]) +{ + sys_put_be16(val >> 16, dst); + sys_put_be16(val, &dst[2]); +} + +/** + * @brief Put a 48-bit integer as big-endian to arbitrary location. + * + * Put a 48-bit integer, originally in host endianness, to a + * potentially unaligned memory location in big-endian format. + * + * @param val 48-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_be48(uint64_t val, uint8_t dst[6]) +{ + sys_put_be16(val >> 32, dst); + sys_put_be32(val, &dst[2]); +} + +/** + * @brief Put a 64-bit integer as big-endian to arbitrary location. + * + * Put a 64-bit integer, originally in host endianness, to a + * potentially unaligned memory location in big-endian format. + * + * @param val 64-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_be64(uint64_t val, uint8_t dst[8]) +{ + sys_put_be32(val >> 32, dst); + sys_put_be32(val, &dst[4]); +} + +/** + * @brief Put a 16-bit integer as little-endian to arbitrary location. + * + * Put a 16-bit integer, originally in host endianness, to a + * potentially unaligned memory location in little-endian format. + * + * @param val 16-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_le16(uint16_t val, uint8_t dst[2]) +{ + dst[0] = val; + dst[1] = val >> 8; +} + +/** + * @brief Put a 24-bit integer as little-endian to arbitrary location. + * + * Put a 24-bit integer, originally in host endianness, to a + * potentially unaligned memory location in little-endian format. + * + * @param val 24-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_le24(uint32_t val, uint8_t dst[3]) +{ + sys_put_le16(val, dst); + dst[2] = val >> 16; +} + +/** + * @brief Put a 32-bit integer as little-endian to arbitrary location. + * + * Put a 32-bit integer, originally in host endianness, to a + * potentially unaligned memory location in little-endian format. + * + * @param val 32-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_le32(uint32_t val, uint8_t dst[4]) +{ + sys_put_le16(val, dst); + sys_put_le16(val >> 16, &dst[2]); +} + +/** + * @brief Put a 48-bit integer as little-endian to arbitrary location. + * + * Put a 48-bit integer, originally in host endianness, to a + * potentially unaligned memory location in little-endian format. + * + * @param val 48-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_le48(uint64_t val, uint8_t dst[6]) +{ + sys_put_le32(val, dst); + sys_put_le16(val >> 32, &dst[4]); +} + +/** + * @brief Put a 64-bit integer as little-endian to arbitrary location. + * + * Put a 64-bit integer, originally in host endianness, to a + * potentially unaligned memory location in little-endian format. + * + * @param val 64-bit integer in host endianness. + * @param dst Destination memory address to store the result. + */ +static inline void sys_put_le64(uint64_t val, uint8_t dst[8]) +{ + sys_put_le32(val, dst); + sys_put_le32(val >> 32, &dst[4]); +} + +/** + * @brief Get a 16-bit integer stored in big-endian format. + * + * Get a 16-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 16-bit integer to get. + * + * @return 16-bit integer in host endianness. + */ +static inline uint16_t sys_get_be16(const uint8_t src[2]) +{ + return ((uint16_t)src[0] << 8) | src[1]; +} + +/** + * @brief Get a 24-bit integer stored in big-endian format. + * + * Get a 24-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 24-bit integer to get. + * + * @return 24-bit integer in host endianness. + */ +static inline uint32_t sys_get_be24(const uint8_t src[3]) +{ + return ((uint32_t)src[0] << 16) | sys_get_be16(&src[1]); +} + +/** + * @brief Get a 32-bit integer stored in big-endian format. + * + * Get a 32-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 32-bit integer to get. + * + * @return 32-bit integer in host endianness. + */ +static inline uint32_t sys_get_be32(const uint8_t src[4]) +{ + return ((uint32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]); +} + +/** + * @brief Get a 48-bit integer stored in big-endian format. + * + * Get a 48-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 48-bit integer to get. + * + * @return 48-bit integer in host endianness. + */ +static inline uint64_t sys_get_be48(const uint8_t src[6]) +{ + return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be16(&src[4]); +} + +/** + * @brief Get a 64-bit integer stored in big-endian format. + * + * Get a 64-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 64-bit integer to get. + * + * @return 64-bit integer in host endianness. + */ +static inline uint64_t sys_get_be64(const uint8_t src[8]) +{ + return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be32(&src[4]); +} + +/** + * @brief Get a 16-bit integer stored in little-endian format. + * + * Get a 16-bit integer, stored in little-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the little-endian 16-bit integer to get. + * + * @return 16-bit integer in host endianness. + */ +static inline uint16_t sys_get_le16(const uint8_t src[2]) +{ + return ((uint16_t)src[1] << 8) | src[0]; +} + +/** + * @brief Get a 24-bit integer stored in big-endian format. + * + * Get a 24-bit integer, stored in big-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the big-endian 24-bit integer to get. + * + * @return 24-bit integer in host endianness. + */ +static inline uint32_t sys_get_le24(const uint8_t src[3]) +{ + return ((uint32_t)src[2] << 16) | sys_get_le16(&src[0]); +} + +/** + * @brief Get a 32-bit integer stored in little-endian format. + * + * Get a 32-bit integer, stored in little-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the little-endian 32-bit integer to get. + * + * @return 32-bit integer in host endianness. + */ +static inline uint32_t sys_get_le32(const uint8_t src[4]) +{ + return ((uint32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]); +} + +/** + * @brief Get a 48-bit integer stored in little-endian format. + * + * Get a 48-bit integer, stored in little-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the little-endian 48-bit integer to get. + * + * @return 48-bit integer in host endianness. + */ +static inline uint64_t sys_get_le48(const uint8_t src[6]) +{ + return ((uint64_t)sys_get_le32(&src[2]) << 32) | sys_get_le16(&src[0]); +} + +/** + * @brief Get a 64-bit integer stored in little-endian format. + * + * Get a 64-bit integer, stored in little-endian format in a potentially + * unaligned memory location, and convert it to the host endianness. + * + * @param src Location of the little-endian 64-bit integer to get. + * + * @return 64-bit integer in host endianness. + */ +static inline uint64_t sys_get_le64(const uint8_t src[8]) +{ + return ((uint64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]); +} + +/** + * @brief Swap one buffer content into another + * + * Copy the content of src buffer into dst buffer in reversed order, + * i.e.: src[n] will be put in dst[end-n] + * Where n is an index and 'end' the last index in both arrays. + * The 2 memory pointers must be pointing to different areas, and have + * a minimum size of given length. + * + * @param dst A valid pointer on a memory area where to copy the data in + * @param src A valid pointer on a memory area where to copy the data from + * @param length Size of both dst and src memory areas + */ +static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) +{ + uint8_t *pdst = (uint8_t *)dst; + const uint8_t *psrc = (const uint8_t *)src; + + __ASSERT(((psrc < pdst && (psrc + length) <= pdst) || + (psrc > pdst && (pdst + length) <= psrc)), + "Source and destination buffers must not overlap"); + + psrc += length - 1; + + for (; length > 0; length--) { + *pdst++ = *psrc--; + } +} + +/** + * @brief Swap buffer content + * + * In-place memory swap, where final content will be reversed. + * I.e.: buf[n] will be put in buf[end-n] + * Where n is an index and 'end' the last index of buf. + * + * @param buf A valid pointer on a memory area to swap + * @param length Size of buf memory area + */ +static inline void sys_mem_swap(void *buf, size_t length) +{ + size_t i; + + for (i = 0; i < (length / 2); i++) { + uint8_t tmp = ((uint8_t *)buf)[i]; + + ((uint8_t *)buf)[i] = ((uint8_t *)buf)[length - 1 - i]; + ((uint8_t *)buf)[length - 1 - i] = tmp; + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_BYTEORDER_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/common.h b/lib/bt/esp_ble_mesh/common/include/mesh/common.h new file mode 100644 index 00000000..a1cfa673 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/common.h @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief Bluetooth Mesh Model Common APIs. + */ + +#ifndef _BLE_MESH_COMMON_H_ +#define _BLE_MESH_COMMON_H_ + +#include +#include + +#include "esp_attr.h" +#include "esp_heap_caps.h" + +#include "mesh/byteorder.h" +#include "mesh/ffs.h" +#include "mesh/trace.h" +#include "mesh/mutex.h" +#include "mesh/access.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void *bt_mesh_malloc(size_t size); + +void *bt_mesh_calloc(size_t size); + +void bt_mesh_free(void *ptr); + +/** + * @brief This function allocates memory to store outgoing message. + * + * @param[in] size: Length of memory allocated to store message value + * + * @return NULL-fail, pointer of a net_buf_simple structure-success + */ +struct net_buf_simple *bt_mesh_alloc_buf(uint16_t size); + +/** + * @brief This function releases the memory allocated for the outgoing message. + * + * @param[in] buf: Pointer to the net_buf_simple structure to be freed + * + * @return none + */ +void bt_mesh_free_buf(struct net_buf_simple *buf); + +int bt_mesh_rand(void *buf, size_t len); + +uint32_t bt_mesh_get_rand(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_COMMON_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/compiler.h b/lib/bt/esp_ble_mesh/common/include/mesh/compiler.h new file mode 100644 index 00000000..c73e8dfb --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/compiler.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2010-2014,2017 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_COMPILER_H_ +#define _BLE_MESH_COMPILER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ___in_section(a, b, c) + +#define __in_section(a, b, c) ___in_section(a, b, c) + +#define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__) + +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#ifndef __used +#define __used __attribute__((__used__)) +#endif + +#ifndef ARG_UNUSED +#define ARG_UNUSED(x) (void)(x) +#endif + +#ifndef popcount +#define popcount(x) __builtin_popcount(x) +#endif + +#ifndef ALWAYS_INLINE +#define ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + + +/* + * This is meant to be used in conjunction with __in_section() and similar + * where scattered structure instances are concatened together by the linker + * and walked by the code at run time just like a contiguous array of such + * structures. + * + * Assemblers and linkers may insert alignment padding by default whose + * size is larger than the natural alignment for those structures when + * gathering various section segments together, messing up the array walk. + * To prevent this, we need to provide an explicit alignment not to rely + * on the default that might just work by luck. + * + * Alignment statements in linker scripts are not sufficient as + * the assembler may add padding by itself to each segment when switching + * between sections within the same file even if it merges many such segments + * into a single section in the end. + */ +#ifndef Z_DECL_ALIGN +#define Z_DECL_ALIGN(type) __aligned(__alignof(type)) type +#endif + +/* + * Convenience helper combining __in_section() and Z_DECL_ALIGN(). + * The section name is the struct type prepended with an underscore. + * The subsection is "static" and the subsubsection is the variable name. + */ +#ifndef Z_STRUCT_SECTION_ITERABLE +#define Z_STRUCT_SECTION_ITERABLE(struct_type, name) \ + Z_DECL_ALIGN(struct struct_type) name +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_COMPILER_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/config.h b/lib/bt/esp_ble_mesh/common/include/mesh/config.h new file mode 100644 index 00000000..ab06eda8 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/config.h @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_CONFIG_H_ +#define _BLE_MESH_CONFIG_H_ + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CONFIG_BLE_MESH_PBA_SAME_TIME +#define CONFIG_BLE_MESH_PBA_SAME_TIME 0 +#endif + +#ifndef CONFIG_BLE_MESH_PBG_SAME_TIME +#define CONFIG_BLE_MESH_PBG_SAME_TIME 0 +#endif + +#define CONFIG_BLE_MESH_PRIVATE_BEACON (CONFIG_BLE_MESH_PRB_SRV || \ + CONFIG_BLE_MESH_PRB_CLI) + +#define CONFIG_BLE_MESH_GENERIC_CLIENT (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI || \ + CONFIG_BLE_MESH_GENERIC_LEVEL_CLI || \ + CONFIG_BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI || \ + CONFIG_BLE_MESH_GENERIC_POWER_ONOFF_CLI || \ + CONFIG_BLE_MESH_GENERIC_POWER_LEVEL_CLI || \ + CONFIG_BLE_MESH_GENERIC_BATTERY_CLI || \ + CONFIG_BLE_MESH_GENERIC_LOCATION_CLI || \ + CONFIG_BLE_MESH_GENERIC_PROPERTY_CLI) + +#define CONFIG_BLE_MESH_TIME_SCENE_CLIENT (CONFIG_BLE_MESH_TIME_CLI || \ + CONFIG_BLE_MESH_SCENE_CLI || \ + CONFIG_BLE_MESH_SCHEDULER_CLI) + +#define CONFIG_BLE_MESH_LIGHTING_CLIENT (CONFIG_BLE_MESH_LIGHT_LIGHTNESS_CLI || \ + CONFIG_BLE_MESH_LIGHT_CTL_CLI || \ + CONFIG_BLE_MESH_LIGHT_HSL_CLI || \ + CONFIG_BLE_MESH_LIGHT_XYL_CLI || \ + CONFIG_BLE_MESH_LIGHT_LC_CLI) + +#define CONFIG_BLE_MESH_SERVER_MODEL (CONFIG_BLE_MESH_GENERIC_SERVER || \ + CONFIG_BLE_MESH_SENSOR_SERVER || \ + CONFIG_BLE_MESH_TIME_SCENE_SERVER || \ + CONFIG_BLE_MESH_LIGHTING_SERVER) + +#define CONFIG_BLE_MESH_BLE_COEX_SUPPORT (CONFIG_BLE_MESH_SUPPORT_BLE_ADV || \ + CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) + +#define CONFIG_BLE_MESH_PROXY_SOLIC (CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX) + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_CONFIG_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/dlist.h b/lib/bt/esp_ble_mesh/common/include/mesh/dlist.h new file mode 100644 index 00000000..01e35f40 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/dlist.h @@ -0,0 +1,498 @@ +/* + * SPDX-FileCopyrightText: 2013-2015 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Doubly-linked list implementation + * + * Doubly-linked list implementation using inline macros/functions. + * This API is not thread safe, and thus if a list is used across threads, + * calls to functions must be protected with synchronization primitives. + * + * The lists are expected to be initialized such that both the head and tail + * pointers point to the list itself. Initializing the lists in such a fashion + * simplifies the adding and removing of nodes to/from the list. + */ + +#ifndef _BLE_MESH_DLIST_H_ +#define _BLE_MESH_DLIST_H_ + +#include +#include "mesh/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct _dnode { + union { + struct _dnode *head; /* ptr to head of list (sys_dlist_t) */ + struct _dnode *next; /* ptr to next node (sys_dnode_t) */ + }; + union { + struct _dnode *tail; /* ptr to tail of list (sys_dlist_t) */ + struct _dnode *prev; /* ptr to previous node (sys_dnode_t) */ + }; +}; + +typedef struct _dnode sys_dlist_t; +typedef struct _dnode sys_dnode_t; + +/** + * @brief Provide the primitive to iterate on a list + * Note: the loop is unsafe and thus __dn should not be removed + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_DLIST_FOR_EACH_NODE(l, n) { + * + * } + * + * This and other SYS_DLIST_*() macros are not thread safe. + * + * @param __dl A pointer on a sys_dlist_t to iterate on + * @param __dn A sys_dnode_t pointer to peek each node of the list + */ +#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn) \ + for (__dn = sys_dlist_peek_head(__dl); __dn; \ + __dn = sys_dlist_peek_next(__dl, __dn)) + +/** + * @brief Provide the primitive to iterate on a list, from a node in the list + * Note: the loop is unsafe and thus __dn should not be removed + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_DLIST_ITERATE_FROM_NODE(l, n) { + * + * } + * + * Like SYS_DLIST_FOR_EACH_NODE(), but __dn already contains a node in the list + * where to start searching for the next entry from. If NULL, it starts from + * the head. + * + * This and other SYS_DLIST_*() macros are not thread safe. + * + * @param __dl A pointer on a sys_dlist_t to iterate on + * @param __dn A sys_dnode_t pointer to peek each node of the list; + * it contains the starting node, or NULL to start from the head + */ +#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \ + for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \ + : sys_dlist_peek_head(__dl); \ + __dn; \ + __dn = sys_dlist_peek_next(__dl, __dn)) + +/** + * @brief Provide the primitive to safely iterate on a list + * Note: __dn can be removed, it will not break the loop. + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_DLIST_FOR_EACH_NODE_SAFE(l, n, s) { + * + * } + * + * This and other SYS_DLIST_*() macros are not thread safe. + * + * @param __dl A pointer on a sys_dlist_t to iterate on + * @param __dn A sys_dnode_t pointer to peek each node of the list + * @param __dns A sys_dnode_t pointer for the loop to run safely + */ +#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns) \ + for (__dn = sys_dlist_peek_head(__dl), \ + __dns = sys_dlist_peek_next(__dl, __dn); \ + __dn; __dn = __dns, \ + __dns = sys_dlist_peek_next(__dl, __dn)) + +/* + * @brief Provide the primitive to resolve the container of a list node + * Note: it is safe to use with NULL pointer nodes + * + * @param __dn A pointer on a sys_dnode_t to get its container + * @param __cn Container struct type pointer + * @param __n The field name of sys_dnode_t within the container struct + */ +#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \ + (__dn ? CONTAINER_OF(__dn, __typeof__(*__cn), __n) : NULL) +/* + * @brief Provide the primitive to peek container of the list head + * + * @param __dl A pointer on a sys_dlist_t to peek + * @param __cn Container struct type pointer + * @param __n The field name of sys_dnode_t within the container struct + */ +#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \ + SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n) + +/* + * @brief Provide the primitive to peek the next container + * + * @param __dl A pointer on a sys_dlist_t to peek + * @param __cn Container struct type pointer + * @param __n The field name of sys_dnode_t within the container struct + */ +#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \ + ((__cn) ? SYS_DLIST_CONTAINER(sys_dlist_peek_next(__dl, &(__cn->__n)), \ + __cn, __n) : NULL) + +/** + * @brief Provide the primitive to iterate on a list under a container + * Note: the loop is unsafe and thus __cn should not be detached + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_DLIST_FOR_EACH_CONTAINER(l, c, n) { + * + * } + * + * @param __dl A pointer on a sys_dlist_t to iterate on + * @param __cn A pointer to peek each entry of the list + * @param __n The field name of sys_dnode_t within the container struct + */ +#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \ + for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); __cn; \ + __cn = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n)) + +/** + * @brief Provide the primitive to safely iterate on a list under a container + * Note: __cn can be detached, it will not break the loop. + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_DLIST_FOR_EACH_CONTAINER_SAFE(l, c, cn, n) { + * + * } + * + * @param __dl A pointer on a sys_dlist_t to iterate on + * @param __cn A pointer to peek each entry of the list + * @param __cns A pointer for the loop to run safely + * @param __n The field name of sys_dnode_t within the container struct + */ +#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \ + for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \ + __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); __cn; \ + __cn = __cns, \ + __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n)) + +/** + * @brief initialize list + * + * @param list the doubly-linked list + * + * @return N/A + */ + +static inline void sys_dlist_init(sys_dlist_t *list) +{ + list->head = (sys_dnode_t *)list; + list->tail = (sys_dnode_t *)list; +} + +#define SYS_DLIST_STATIC_INIT(ptr_to_list) {{(ptr_to_list)}, {(ptr_to_list)}} + +/** + * @brief check if a node is the list's head + * + * @param list the doubly-linked list to operate on + * @param node the node to check + * + * @return 1 if node is the head, 0 otherwise + */ + +static inline int sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node) +{ + return list->head == node; +} + +/** + * @brief check if a node is the list's tail + * + * @param list the doubly-linked list to operate on + * @param node the node to check + * + * @return 1 if node is the tail, 0 otherwise + */ + +static inline int sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node) +{ + return list->tail == node; +} + +/** + * @brief check if the list is empty + * + * @param list the doubly-linked list to operate on + * + * @return 1 if empty, 0 otherwise + */ + +static inline int sys_dlist_is_empty(sys_dlist_t *list) +{ + return list->head == list; +} + +/** + * @brief check if more than one node present + * + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * + * @return 1 if multiple nodes, 0 otherwise + */ + +static inline int sys_dlist_has_multiple_nodes(sys_dlist_t *list) +{ + return list->head != list->tail; +} + +/** + * @brief get a reference to the head item in the list + * + * @param list the doubly-linked list to operate on + * + * @return a pointer to the head element, NULL if list is empty + */ + +static inline sys_dnode_t *sys_dlist_peek_head(sys_dlist_t *list) +{ + return sys_dlist_is_empty(list) ? NULL : list->head; +} + +/** + * @brief get a reference to the head item in the list + * + * The list must be known to be non-empty. + * + * @param list the doubly-linked list to operate on + * + * @return a pointer to the head element + */ + +static inline sys_dnode_t *sys_dlist_peek_head_not_empty(sys_dlist_t *list) +{ + return list->head; +} + +/** + * @brief get a reference to the next item in the list, node is not NULL + * + * Faster than sys_dlist_peek_next() if node is known not to be NULL. + * + * @param list the doubly-linked list to operate on + * @param node the node from which to get the next element in the list + * + * @return a pointer to the next element from a node, NULL if node is the tail + */ + +static inline sys_dnode_t *sys_dlist_peek_next_no_check(sys_dlist_t *list, + sys_dnode_t *node) +{ + return (node == list->tail) ? NULL : node->next; +} + +/** + * @brief get a reference to the next item in the list + * + * @param list the doubly-linked list to operate on + * @param node the node from which to get the next element in the list + * + * @return a pointer to the next element from a node, NULL if node is the tail + * or NULL (when node comes from reading the head of an empty list). + */ + +static inline sys_dnode_t *sys_dlist_peek_next(sys_dlist_t *list, + sys_dnode_t *node) +{ + return node ? sys_dlist_peek_next_no_check(list, node) : NULL; +} + +/** + * @brief get a reference to the tail item in the list + * + * @param list the doubly-linked list to operate on + * + * @return a pointer to the tail element, NULL if list is empty + */ + +static inline sys_dnode_t *sys_dlist_peek_tail(sys_dlist_t *list) +{ + return sys_dlist_is_empty(list) ? NULL : list->tail; +} + +/** + * @brief add node to tail of list + * + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * @param node the element to append + * + * @return N/A + */ + +static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node) +{ + node->next = list; + node->prev = list->tail; + + list->tail->next = node; + list->tail = node; +} + +/** + * @brief add node to head of list + * + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * @param node the element to append + * + * @return N/A + */ + +static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node) +{ + node->next = list->head; + node->prev = list; + + list->head->prev = node; + list->head = node; +} + +/** + * @brief insert node after a node + * + * Insert a node after a specified node in a list. + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * @param insert_point the insert point in the list: if NULL, insert at head + * @param node the element to append + * + * @return N/A + */ + +static inline void sys_dlist_insert_after(sys_dlist_t *list, + sys_dnode_t *insert_point, + sys_dnode_t *node) +{ + if (!insert_point) { + sys_dlist_prepend(list, node); + } else { + node->next = insert_point->next; + node->prev = insert_point; + insert_point->next->prev = node; + insert_point->next = node; + } +} + +/** + * @brief insert node before a node + * + * Insert a node before a specified node in a list. + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * @param insert_point the insert point in the list: if NULL, insert at tail + * @param node the element to insert + * + * @return N/A + */ + +static inline void sys_dlist_insert_before(sys_dlist_t *list, + sys_dnode_t *insert_point, + sys_dnode_t *node) +{ + if (!insert_point) { + sys_dlist_append(list, node); + } else { + node->prev = insert_point->prev; + node->next = insert_point; + insert_point->prev->next = node; + insert_point->prev = node; + } +} + +/** + * @brief insert node at position + * + * Insert a node in a location depending on a external condition. The cond() + * function checks if the node is to be inserted _before_ the current node + * against which it is checked. + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * @param node the element to insert + * @param cond a function that determines if the current node is the correct + * insert point + * @param data parameter to cond() + * + * @return N/A + */ + +static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node, + int (*cond)(sys_dnode_t *, void *), void *data) +{ + if (sys_dlist_is_empty(list)) { + sys_dlist_append(list, node); + } else { + sys_dnode_t *pos = sys_dlist_peek_head(list); + + while (pos && !cond(pos, data)) { + pos = sys_dlist_peek_next(list, pos); + } + sys_dlist_insert_before(list, pos, node); + } +} + +/** + * @brief remove a specific node from a list + * + * The list is implicit from the node. The node must be part of a list. + * This and other sys_dlist_*() functions are not thread safe. + * + * @param node the node to remove + * + * @return N/A + */ + +static inline void sys_dlist_remove(sys_dnode_t *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; +} + +/** + * @brief get the first node in a list + * + * This and other sys_dlist_*() functions are not thread safe. + * + * @param list the doubly-linked list to operate on + * + * @return the first node in the list, NULL if list is empty + */ + +static inline sys_dnode_t *sys_dlist_get(sys_dlist_t *list) +{ + sys_dnode_t *node; + + if (sys_dlist_is_empty(list)) { + return NULL; + } + + node = list->head; + sys_dlist_remove(node); + return node; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_DLIST_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/ffs.h b/lib/bt/esp_ble_mesh/common/include/mesh/ffs.h new file mode 100644 index 00000000..7f512548 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/ffs.h @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2015 Wind River Systems, Inc. + * SPDX-FileCopyrightText: 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_FFS_H_ +#define _BLE_MESH_FFS_H_ + +#include "mesh/types.h" +#include "mesh/compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @brief find most significant bit set in a 32-bit word + * + * This routine finds the first bit set starting from the most significant bit + * in the argument passed in and returns the index of that bit. Bits are + * numbered starting at 1 from the least significant bit. A return value of + * zero indicates that the value passed is zero. + * + * @return most significant bit set, 0 if @a op is 0 + */ + +static ALWAYS_INLINE unsigned int find_msb_set(uint32_t op) +{ + if (op == 0) { + return 0; + } + + return 32 - __builtin_clz(op); +} + +/** + * + * @brief find least significant bit set in a 32-bit word + * + * This routine finds the first bit set starting from the least significant bit + * in the argument passed in and returns the index of that bit. Bits are + * numbered starting at 1 from the least significant bit. A return value of + * zero indicates that the value passed is zero. + * + * @return least significant bit set, 0 if @a op is 0 + */ + +static ALWAYS_INLINE unsigned int find_lsb_set(uint32_t op) +{ + return __builtin_ffs(op); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_FFS_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/kernel.h b/lib/bt/esp_ble_mesh/common/include/mesh/kernel.h new file mode 100644 index 00000000..025b269a --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/kernel.h @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2016 Wind River Systems, Inc. + * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_KERNEL_H_ +#define _BLE_MESH_KERNEL_H_ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +#include "mesh/config.h" +#include "mesh/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_BT_BLUEDROID_ENABLED +#ifdef CONFIG_BT_BLUEDROID_PINNED_TO_CORE +#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY) +#else +#define BLE_MESH_ADV_TASK_CORE (0) +#endif +#endif + +#ifdef CONFIG_BT_NIMBLE_ENABLED +#ifdef CONFIG_BT_NIMBLE_PINNED_TO_CORE +#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) +#else +#define BLE_MESH_ADV_TASK_CORE (0) +#endif +#endif + +#define BLE_MESH_ADV_TASK_STACK_SIZE 3072 +#define BLE_MESH_ADV_TASK_NAME "mesh_adv_task" +#define BLE_MESH_ADV_TASK_PRIO (configMAX_PRIORITIES - 5) + +/** + * @brief Put the current thread to sleep. + * + * This routine puts the current thread to sleep for @a duration + * milliseconds. + * + * @param duration Number of milliseconds to sleep. + * + * @return N/A + */ +void k_sleep(int32_t duration); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_KERNEL_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h b/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h new file mode 100644 index 00000000..ee897500 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_MUTEX_H_ +#define _BLE_MESH_MUTEX_H_ + +#include "mesh/kernel.h" +#include "mesh/slist.h" +#include "mesh/atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + SemaphoreHandle_t mutex; +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + StaticQueue_t *buffer; +#endif +} bt_mesh_mutex_t; + +void bt_mesh_mutex_create(bt_mesh_mutex_t *mutex); +void bt_mesh_mutex_free(bt_mesh_mutex_t *mutex); +void bt_mesh_mutex_lock(bt_mesh_mutex_t *mutex); +void bt_mesh_mutex_unlock(bt_mesh_mutex_t *mutex); + +void bt_mesh_r_mutex_create(bt_mesh_mutex_t *mutex); +void bt_mesh_r_mutex_free(bt_mesh_mutex_t *mutex); +void bt_mesh_r_mutex_lock(bt_mesh_mutex_t *mutex); +void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex); + +void bt_mesh_alarm_lock(void); +void bt_mesh_alarm_unlock(void); + +void bt_mesh_list_lock(void); +void bt_mesh_list_unlock(void); + +void bt_mesh_buf_lock(void); +void bt_mesh_buf_unlock(void); + +void bt_mesh_atomic_lock(void); +void bt_mesh_atomic_unlock(void); + +void bt_mesh_mutex_init(void); +void bt_mesh_mutex_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_MUTEX_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/slist.h b/lib/bt/esp_ble_mesh/common/include/mesh/slist.h new file mode 100644 index 00000000..6050522d --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/slist.h @@ -0,0 +1,467 @@ +/* + * SPDX-FileCopyrightText: 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * + * @brief Single-linked list implementation + * + * Single-linked list implementation using inline macros/functions. + * This API is not thread safe, and thus if a list is used across threads, + * calls to functions must be protected with synchronization primitives. + */ + +#ifndef _BLE_MESH_SLIST_H_ +#define _BLE_MESH_SLIST_H_ + +#include +#include +#include "mesh/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _snode { + struct _snode *next; +}; + +typedef struct _snode sys_snode_t; + +struct _slist { + sys_snode_t *head; + sys_snode_t *tail; +}; + +typedef struct _slist sys_slist_t; + +/** + * @brief Provide the primitive to iterate on a list + * Note: the loop is unsafe and thus __sn should not be removed + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_NODE(l, n) { + * + * } + * + * This and other SYS_SLIST_*() macros are not thread safe. + * + * @param __sl A pointer on a sys_slist_t to iterate on + * @param __sn A sys_snode_t pointer to peek each node of the list + */ +#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn) \ + for (__sn = sys_slist_peek_head(__sl); __sn; \ + __sn = sys_slist_peek_next(__sn)) + +/** + * @brief Provide the primitive to iterate on a list, from a node in the list + * Note: the loop is unsafe and thus __sn should not be removed + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_ITERATE_FROM_NODE(l, n) { + * + * } + * + * Like SYS_SLIST_FOR_EACH_NODE(), but __dn already contains a node in the list + * where to start searching for the next entry from. If NULL, it starts from + * the head. + * + * This and other SYS_SLIST_*() macros are not thread safe. + * + * @param __sl A pointer on a sys_slist_t to iterate on + * @param __sn A sys_snode_t pointer to peek each node of the list + * it contains the starting node, or NULL to start from the head + */ +#define SYS_SLIST_ITERATE_FROM_NODE(__sl, __sn) \ + for (__sn = __sn ? sys_slist_peek_next_no_check(__sn) \ + : sys_slist_peek_head(__sl); \ + __sn; \ + __sn = sys_slist_peek_next(__sn)) + +/** + * @brief Provide the primitive to safely iterate on a list + * Note: __sn can be removed, it will not break the loop. + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_NODE_SAFE(l, n, s) { + * + * } + * + * This and other SYS_SLIST_*() macros are not thread safe. + * + * @param __sl A pointer on a sys_slist_t to iterate on + * @param __sn A sys_snode_t pointer to peek each node of the list + * @param __sns A sys_snode_t pointer for the loop to run safely + */ +#define SYS_SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \ + for (__sn = sys_slist_peek_head(__sl), \ + __sns = sys_slist_peek_next(__sn); \ + __sn; __sn = __sns, \ + __sns = sys_slist_peek_next(__sn)) + +/* + * @brief Provide the primitive to resolve the container of a list node + * Note: it is safe to use with NULL pointer nodes + * + * @param __ln A pointer on a sys_node_t to get its container + * @param __cn Container struct type pointer + * @param __n The field name of sys_node_t within the container struct + */ +#define SYS_SLIST_CONTAINER(__ln, __cn, __n) \ + ((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL) +/* + * @brief Provide the primitive to peek container of the list head + * + * @param __sl A pointer on a sys_slist_t to peek + * @param __cn Container struct type pointer + * @param __n The field name of sys_node_t within the container struct + */ +#define SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \ + SYS_SLIST_CONTAINER(sys_slist_peek_head(__sl), __cn, __n) + +/* + * @brief Provide the primitive to peek container of the list tail + * + * @param __sl A pointer on a sys_slist_t to peek + * @param __cn Container struct type pointer + * @param __n The field name of sys_node_t within the container struct + */ +#define SYS_SLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \ + SYS_SLIST_CONTAINER(sys_slist_peek_tail(__sl), __cn, __n) + +/* + * @brief Provide the primitive to peek the next container + * + * @param __cn Container struct type pointer + * @param __n The field name of sys_node_t within the container struct + */ + +#define SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n) \ + ((__cn) ? SYS_SLIST_CONTAINER(sys_slist_peek_next(&((__cn)->__n)), \ + __cn, __n) : NULL) + +/** + * @brief Provide the primitive to iterate on a list under a container + * Note: the loop is unsafe and thus __cn should not be detached + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_CONTAINER(l, c, n) { + * + * } + * + * @param __sl A pointer on a sys_slist_t to iterate on + * @param __cn A pointer to peek each entry of the list + * @param __n The field name of sys_node_t within the container struct + */ +#define SYS_SLIST_FOR_EACH_CONTAINER(__sl, __cn, __n) \ + for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n); __cn; \ + __cn = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n)) + +/** + * @brief Provide the primitive to safely iterate on a list under a container + * Note: __cn can be detached, it will not break the loop. + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_NODE_SAFE(l, c, cn, n) { + * + * } + * + * @param __sl A pointer on a sys_slist_t to iterate on + * @param __cn A pointer to peek each entry of the list + * @param __cns A pointer for the loop to run safely + * @param __n The field name of sys_node_t within the container struct + */ +#define SYS_SLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n) \ + for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n), \ + __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n); __cn; \ + __cn = __cns, __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n)) + +/** + * @brief Initialize a list + * + * @param list A pointer on the list to initialize + */ +static inline void sys_slist_init(sys_slist_t *list) +{ + list->head = NULL; + list->tail = NULL; +} + +#define SYS_SLIST_STATIC_INIT(ptr_to_list) {NULL, NULL} + +/** + * @brief Test if the given list is empty + * + * @param list A pointer on the list to test + * + * @return a boolean, true if it's empty, false otherwise + */ +static inline bool sys_slist_is_empty(sys_slist_t *list) +{ + return (!list->head); +} + +/** + * @brief Peek the first node from the list + * + * @param list A point on the list to peek the first node from + * + * @return A pointer on the first node of the list (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_head(sys_slist_t *list) +{ + return list->head; +} + +/** + * @brief Peek the last node from the list + * + * @param list A point on the list to peek the last node from + * + * @return A pointer on the last node of the list (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_tail(sys_slist_t *list) +{ + return list->tail; +} + +/** + * @brief Peek the next node from current node, node is not NULL + * + * Faster then sys_slist_peek_next() if node is known not to be NULL. + * + * @param node A pointer on the node where to peek the next node + * + * @return a pointer on the next node (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_next_no_check(sys_snode_t *node) +{ + return node->next; +} + +/** + * @brief Peek the next node from current node + * + * @param node A pointer on the node where to peek the next node + * + * @return a pointer on the next node (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_next(sys_snode_t *node) +{ + return node ? sys_slist_peek_next_no_check(node) : NULL; +} + +/** + * @brief Prepend a node to the given list + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to prepend + */ +static inline void sys_slist_prepend(sys_slist_t *list, + sys_snode_t *node) +{ + node->next = list->head; + list->head = node; + + if (!list->tail) { + list->tail = list->head; + } +} + +/** + * @brief Append a node to the given list + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to append + */ +static inline void sys_slist_append(sys_slist_t *list, + sys_snode_t *node) +{ + node->next = NULL; + + if (!list->tail) { + list->tail = node; + list->head = node; + } else { + list->tail->next = node; + list->tail = node; + } +} + +/** + * @brief Append a list to the given list + * + * Append a singly-linked, NULL-terminated list consisting of nodes containing + * the pointer to the next node as the first element of a node, to @a list. + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param head A pointer to the first element of the list to append + * @param tail A pointer to the last element of the list to append + */ +static inline void sys_slist_append_list(sys_slist_t *list, + void *head, void *tail) +{ + if (!list->tail) { + list->head = (sys_snode_t *)head; + list->tail = (sys_snode_t *)tail; + } else { + list->tail->next = (sys_snode_t *)head; + list->tail = (sys_snode_t *)tail; + } +} + +/** + * @brief merge two slists, appending the second one to the first + * + * When the operation is completed, the appending list is empty. + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param list_to_append A pointer to the list to append. + */ +static inline void sys_slist_merge_slist(sys_slist_t *list, + sys_slist_t *list_to_append) +{ + sys_slist_append_list(list, list_to_append->head, + list_to_append->tail); + sys_slist_init(list_to_append); +} + +/** + * @brief Insert a node to the given list + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param prev A pointer on the previous node + * @param node A pointer on the node to insert + */ +static inline void sys_slist_insert(sys_slist_t *list, + sys_snode_t *prev, + sys_snode_t *node) +{ + if (!prev) { + sys_slist_prepend(list, node); + } else if (!prev->next) { + sys_slist_append(list, node); + } else { + node->next = prev->next; + prev->next = node; + } +} + +/** + * @brief Fetch and remove the first node of the given list + * + * List must be known to be non-empty. + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * + * @return A pointer to the first node of the list + */ +static inline sys_snode_t *sys_slist_get_not_empty(sys_slist_t *list) +{ + sys_snode_t *node = list->head; + + list->head = node->next; + if (list->tail == node) { + list->tail = list->head; + } + + return node; +} + +/** + * @brief Fetch and remove the first node of the given list + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * + * @return A pointer to the first node of the list (or NULL if empty) + */ +static inline sys_snode_t *sys_slist_get(sys_slist_t *list) +{ + return sys_slist_is_empty(list) ? NULL : sys_slist_get_not_empty(list); +} + +/** + * @brief Remove a node + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param prev_node A pointer on the previous node + * (can be NULL, which means the node is the list's head) + * @param node A pointer on the node to remove + */ +static inline void sys_slist_remove(sys_slist_t *list, + sys_snode_t *prev_node, + sys_snode_t *node) +{ + if (!prev_node) { + list->head = node->next; + + /* Was node also the tail? */ + if (list->tail == node) { + list->tail = list->head; + } + } else { + prev_node->next = node->next; + + /* Was node the tail? */ + if (list->tail == node) { + list->tail = prev_node; + } + } + + node->next = NULL; +} + +/** + * @brief Find and remove a node from a list + * + * This and other sys_slist_*() functions are not thread safe. + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to remove from the list + * + * @return true if node was removed + */ +static inline bool sys_slist_find_and_remove(sys_slist_t *list, + sys_snode_t *node) +{ + sys_snode_t *prev = NULL; + sys_snode_t *test; + + SYS_SLIST_FOR_EACH_NODE(list, test) { + if (test == node) { + sys_slist_remove(list, prev, node); + return true; + } + + prev = test; + } + + return false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_SLIST_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/timer.h b/lib/bt/esp_ble_mesh/common/include/mesh/timer.h new file mode 100644 index 00000000..e1296aa8 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/timer.h @@ -0,0 +1,278 @@ +/* + * SPDX-FileCopyrightText: 2016 Wind River Systems, Inc. + * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_TIMER_H_ +#define _BLE_MESH_TIMER_H_ + +#include "mesh/types.h" +#include "mesh/slist.h" +#include "mesh/atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* number of nsec per usec */ +#define NSEC_PER_USEC 1000 + +/* number of microseconds per millisecond */ +#define USEC_PER_MSEC 1000 + +/* number of milliseconds per second */ +#define MSEC_PER_SEC 1000 + +/* number of microseconds per second */ +#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) + +/* number of nanoseconds per second */ +#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) + +/* timeout is not in use */ +#define _INACTIVE (-1) + +struct k_work; + +/** + * @typedef k_work_handler_t + * @brief Work item handler function type. + * + * A work item's handler function is executed by a workqueue's thread + * when the work item is processed by the workqueue. + * + * @param work Address of the work item. + * + * @return N/A + */ +typedef void (*k_work_handler_t)(struct k_work *work); + +struct k_work { + k_work_handler_t handler; + int index; + void *user_data; +}; + +#define _K_WORK_INITIALIZER(work_handler) \ +{ \ + .handler = work_handler, \ + .user_data = NULL, \ +} + +/** + * @brief Generate null timeout delay. + * + * This macro generates a timeout delay that that instructs a kernel API + * not to wait if the requested operation cannot be performed immediately. + * + * @return Timeout delay value. + */ +#define K_NO_WAIT 0 + +/** + * @brief Generate timeout delay from milliseconds. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait up to @a ms milliseconds to perform the requested operation. + * + * @param ms Duration in milliseconds. + * + * @return Timeout delay value. + */ +#define K_MSEC(ms) (ms) + +/** + * @brief Generate timeout delay from seconds. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait up to @a s seconds to perform the requested operation. + * + * @param s Duration in seconds. + * + * @return Timeout delay value. + */ +#define K_SECONDS(s) K_MSEC((s) * MSEC_PER_SEC) + +/** + * @brief Generate timeout delay from minutes. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait up to @a m minutes to perform the requested operation. + * + * @param m Duration in minutes. + * + * @return Timeout delay value. + */ +#define K_MINUTES(m) K_SECONDS((m) * 60) + +/** + * @brief Generate timeout delay from hours. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait up to @a h hours to perform the requested operation. + * + * @param h Duration in hours. + * + * @return Timeout delay value. + */ +#define K_HOURS(h) K_MINUTES((h) * 60) + +/** + * @brief Generate timeout delay from days. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait up to @a d days to perform the requested operation. + * + * @param d Duration in days. + * + * @return Timeout delay value. + */ +#define K_DAYS(d) K_HOURS((d) * 24) + +/** + * @brief Generate infinite timeout delay. + * + * This macro generates a timeout delay that that instructs a kernel API + * to wait as long as necessary to perform the requested operation. + * + * @return Timeout delay value. + */ +#define K_FOREVER (-1) + +/** + * @brief Get system uptime (32-bit version). + * + * This routine returns the lower 32-bits of the elapsed time since the system + * booted, in milliseconds. + * + * This routine can be more efficient than k_uptime_get(), as it reduces the + * need for interrupt locking and 64-bit math. However, the 32-bit result + * cannot hold a system uptime time larger than approximately 50 days, so the + * caller must handle possible rollovers. + * + * @return Current uptime. + */ +uint32_t k_uptime_get_32(void); + +struct k_delayed_work { + struct k_work work; +}; + +/** + * @brief Submit a delayed work item to the system workqueue. + * + * This routine schedules work item @a work to be processed by the system + * workqueue after a delay of @a delay milliseconds. The routine initiates + * an asynchronous countdown for the work item and then returns to the caller. + * Only when the countdown completes is the work item actually submitted to + * the workqueue and becomes pending. + * + * Submitting a previously submitted delayed work item that is still + * counting down cancels the existing submission and restarts the countdown + * using the new delay. If the work item is currently pending on the + * workqueue's queue because the countdown has completed it is too late to + * resubmit the item, and resubmission fails without impacting the work item. + * If the work item has already been processed, or is currently being processed, + * its work is considered complete and the work item can be resubmitted. + * + * @warning + * Work items submitted to the system workqueue should avoid using handlers + * that block or yield since this may prevent the system workqueue from + * processing other work items in a timely manner. + * + * @note Can be called by ISRs. + * + * @param work Address of delayed work item. + * @param delay Delay before submitting the work item (in milliseconds). + * + * @retval 0 Work item countdown started. + * @retval -EINPROGRESS Work item is already pending. + * @retval -EINVAL Work item is being processed or has completed its work. + * @retval -EADDRINUSE Work item is pending on a different workqueue. + */ +int k_delayed_work_submit(struct k_delayed_work *work, int32_t delay); + +int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period); + +/** + * @brief Get time remaining before a delayed work gets scheduled. + * + * This routine computes the (approximate) time remaining before a + * delayed work gets executed. If the delayed work is not waiting to be + * scheduled, it returns zero. + * + * @param work Delayed work item. + * + * @return Remaining time (in milliseconds). + */ +int32_t k_delayed_work_remaining_get(struct k_delayed_work *work); + +/** + * @brief Submit a work item to the system workqueue. + * + * This routine submits work item @a work to be processed by the system + * workqueue. If the work item is already pending in the workqueue's queue + * as a result of an earlier submission, this routine has no effect on the + * work item. If the work item has already been processed, or is currently + * being processed, its work is considered complete and the work item can be + * resubmitted. + * + * @warning + * Work items submitted to the system workqueue should avoid using handlers + * that block or yield since this may prevent the system workqueue from + * processing other work items in a timely manner. + * + * @note Can be called by ISRs. + * + * @param work Address of work item. + * + * @return N/A + */ +static inline void k_work_submit(struct k_work *work) +{ + if (work && work->handler) { + work->handler(work); + } +} + +/** + * @brief Initialize a work item. + * + * This routine initializes a workqueue work item, prior to its first use. + * + * @param work Address of work item. + * @param handler Function to invoke each time work item is processed. + * + * @return N/A + */ +static inline void k_work_init(struct k_work *work, k_work_handler_t handler) +{ + work->handler = handler; +} + +int k_delayed_work_cancel(struct k_delayed_work *work); + +int k_delayed_work_free(struct k_delayed_work *work); + +int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler); + +/** + * @brief Get system uptime. + * + * This routine returns the elapsed time since the system booted, + * in milliseconds. + * + * @return Current uptime. + */ +int64_t k_uptime_get(void); + +void bt_mesh_timer_init(void); +void bt_mesh_timer_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_TIMER_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/trace.h b/lib/bt/esp_ble_mesh/common/include/mesh/trace.h new file mode 100644 index 00000000..48f604f1 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/trace.h @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA + * SPDX-FileCopyrightText: 2015-2016 Intel Corporation + * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_TRACE_H_ +#define _BLE_MESH_TRACE_H_ + +#include +#include "esp_log.h" +#include "mesh/utils.h" +#include "esp_rom_sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Define common tracing for all */ +#ifndef BLE_MESH_LOG_LEVEL_ERROR +#define BLE_MESH_LOG_LEVEL_ERROR 1 +#endif /* BLE_MESH_LOG_LEVEL_ERROR */ + +#ifndef BLE_MESH_LOG_LEVEL_WARN +#define BLE_MESH_LOG_LEVEL_WARN 2 +#endif /* BLE_MESH_LOG_LEVEL_WARN */ + +#ifndef BLE_MESH_LOG_LEVEL_INFO +#define BLE_MESH_LOG_LEVEL_INFO 3 +#endif /* BLE_MESH_LOG_LEVEL_INFO */ + +#ifndef BLE_MESH_LOG_LEVEL_DEBUG +#define BLE_MESH_LOG_LEVEL_DEBUG 4 +#endif /* BLE_MESH_LOG_LEVEL_DEBUG */ + +#ifndef BLE_MESH_LOG_LEVEL_VERBOSE +#define BLE_MESH_LOG_LEVEL_VERBOSE 5 +#endif /*BLE_MESH_LOG_LEVEL_VERBOSE */ + +#ifdef CONFIG_BLE_MESH_STACK_TRACE_LEVEL +#define BLE_MESH_LOG_LEVEL CONFIG_BLE_MESH_STACK_TRACE_LEVEL +#else +#define BLE_MESH_LOG_LEVEL BLE_MESH_LOG_LEVEL_WARN +#endif + +#ifdef CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL +#define BLE_MESH_NET_BUF_LOG_LEVEL CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL +#else +#define BLE_MESH_NET_BUF_LOG_LEVEL BLE_MESH_LOG_LEVEL_WARN +#endif + +#define BLE_MESH_TRACE_TAG "BLE_MESH" + +#if (LOG_LOCAL_LEVEL >= 4) +#define BLE_MESH_LOG_LOCAL_LEVEL_MAPPING (LOG_LOCAL_LEVEL + 1) +#else +#define BLE_MESH_LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL +#endif + +#define BLE_MESH_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_LOG_LEVEL, BLE_MESH_LOG_LOCAL_LEVEL_MAPPING) >= BLE_MESH_LOG_LEVEL_##LEVEL) + +#define BLE_MESH_PRINT_E(tag, format, ...) {esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BLE_MESH_PRINT_W(tag, format, ...) {esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BLE_MESH_PRINT_I(tag, format, ...) {esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BLE_MESH_PRINT_D(tag, format, ...) {esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BLE_MESH_PRINT_V(tag, format, ...) {esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define printk esp_rom_printf + +#define _STRINGIFY(x) #x +#define STRINGIFY(s) _STRINGIFY(s) + +#ifndef __ASSERT +#define __ASSERT(test, str) assert(test) +#endif + +#ifndef __ASSERT_NO_MSG +#define __ASSERT_NO_MSG(x) assert(x) +#endif + +#if !CONFIG_BLE_MESH_NO_LOG +#define BT_ERR(fmt, args...) do {if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_ERROR) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, ERROR)) BLE_MESH_PRINT_E(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define BT_WARN(fmt, args...) do {if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_WARN) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, WARN)) BLE_MESH_PRINT_W(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define BT_INFO(fmt, args...) do {if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_INFO) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, INFO)) BLE_MESH_PRINT_I(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define BT_DBG(fmt, args...) do {if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_DEBUG) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, DEBUG)) BLE_MESH_PRINT_D(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#else +#define BT_ERR(fmt, args...) +#define BT_WARN(fmt, args...) +#define BT_INFO(fmt, args...) +#define BT_DBG(fmt, args...) +#endif + +#if (CONFIG_BLE_MESH_NET_BUF_LOG && !CONFIG_BLE_MESH_NO_LOG) +#define NET_BUF_ERR(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_ERROR) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, ERROR)) BLE_MESH_PRINT_E(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_WARN(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_WARN) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, WARN)) BLE_MESH_PRINT_W(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_INFO(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_INFO) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, INFO)) BLE_MESH_PRINT_I(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_DBG(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_DEBUG) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, DEBUG)) BLE_MESH_PRINT_D(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_ASSERT(cond) __ASSERT_NO_MSG(cond) +#else +#define NET_BUF_ERR(fmt, args...) +#define NET_BUF_WARN(fmt, args...) +#define NET_BUF_INFO(fmt, args...) +#define NET_BUF_DBG(fmt, args...) +#define NET_BUF_ASSERT(cond) +#endif + +#if (CONFIG_BLE_MESH_NET_BUF_SIMPLE_LOG && !CONFIG_BLE_MESH_NO_LOG) +#define NET_BUF_SIMPLE_ERR(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_ERROR) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, ERROR)) BLE_MESH_PRINT_E(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_SIMPLE_WARN(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_WARN) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, WARN)) BLE_MESH_PRINT_W(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_SIMPLE_INFO(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_INFO) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, INFO)) BLE_MESH_PRINT_I(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_SIMPLE_DBG(fmt, args...) do {if ((BLE_MESH_NET_BUF_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_DEBUG) && BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH_NET_BUF, DEBUG)) BLE_MESH_PRINT_D(BLE_MESH_TRACE_TAG, fmt, ## args);} while(0) +#define NET_BUF_SIMPLE_ASSERT(cond) __ASSERT_NO_MSG(cond) +#else +#define NET_BUF_SIMPLE_ERR(fmt, args...) +#define NET_BUF_SIMPLE_WARN(fmt, args...) +#define NET_BUF_SIMPLE_INFO(fmt, args...) +#define NET_BUF_SIMPLE_DBG(fmt, args...) +#define NET_BUF_SIMPLE_ASSERT(cond) +#endif + +#if CONFIG_BLE_MESH_BQB_TEST_LOG +/** + * For example, the test case "MESH/NODE/TNPT/BV-01-C" + * could use BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_TNPT, "msg %s", msg) + * to print some message. + */ +enum BLE_MESH_BQB_TEST_LOG_LEVEL { + BLE_MESH_BQB_TEST_LOG_LEVEL_OUTPUT_ALL = 0, /* Output all BQB related test log */ + BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE = BIT(0), + BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_PVNR = BIT(1), + BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_CFGCL = BIT(2), + BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_SR = BIT(3), + BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_CL = BIT(4), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_PBADV = BIT(5), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_MPS = BIT(6), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_PROV = BIT(7), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_BCN = BIT(8), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_NET = BIT(9), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_RLY = BIT(10), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_TNPT = BIT(11), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_IVU = BIT(12), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_KR = BIT(13), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_FRND_FN = BIT(14), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_FRND_LPN = BIT(15), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_PROX = BIT(16), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_MPXS = BIT(17), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_CFG = BIT(18), + BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_HM = BIT(19), +}; + +#define BLE_MESH_BQB_TEST_LOG_LEVEL_OUTPUT_NONE 0x000FFFFF + +#endif /* CONFIG_BLE_MESH_BQB_TEST_LOG */ + +#if (CONFIG_BLE_MESH_BQB_TEST_LOG && !CONFIG_BLE_MESH_NO_LOG) +extern bool bt_mesh_bqb_test_flag_check(uint32_t flag_mask); +extern int bt_mesh_bqb_test_flag_set(uint32_t value); +#define BT_BQB(flag_mask, fmt, args...) \ + do { \ + if (bt_mesh_bqb_test_flag_check(flag_mask)) \ + BLE_MESH_PRINT_I("BLE_MESH_BQB", fmt, ## args); \ + } while (0) +#else +#define BT_BQB(flag_mask, fmt, args...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_TRACE_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/types.h b/lib/bt/esp_ble_mesh/common/include/mesh/types.h new file mode 100644 index 00000000..eba8c1a2 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/types.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2017 Linaro Limited + * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_TYPES_H_ +#define _BLE_MESH_TYPES_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int bt_mesh_atomic_t; + +#ifndef PRIu64 +#define PRIu64 "llu" +#endif + +#ifndef PRIx64 +#define PRIx64 "llx" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_TYPES_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/utils.h b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h new file mode 100644 index 00000000..98243483 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h @@ -0,0 +1,226 @@ +/* + * SPDX-FileCopyrightText: 2011-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Misc utilities + * + * Misc utilities usable by the kernel and application code. + */ + +#ifndef _BLE_MESH_UTILS_H_ +#define _BLE_MESH_UTILS_H_ + +#include +#include "esp_bit_defs.h" +#include "mesh/types.h" +#include "utils_loops.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper to pass a int as a pointer or vice-versa. + * Those are available for 32 bits architectures: + */ +#ifndef POINTER_TO_UINT +#define POINTER_TO_UINT(x) ((uint32_t) (x)) +#endif +#ifndef UINT_TO_POINTER +#define UINT_TO_POINTER(x) ((void *) (x)) +#endif +#ifndef POINTER_TO_INT +#define POINTER_TO_INT(x) ((int32_t) (x)) +#endif +#ifndef INT_TO_POINTER +#define INT_TO_POINTER(x) ((void *) (x)) +#endif + +/* Evaluates to 0 if cond is true-ish; compile error otherwise */ +#ifndef ZERO_OR_COMPILE_ERROR +#define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1) +#endif + +/* Evaluates to 0 if array is an array; compile error if not array (e.g. + * pointer) + */ +#ifndef IS_ARRAY +#define IS_ARRAY(array) \ + ZERO_OR_COMPILE_ERROR( \ + !__builtin_types_compatible_p(__typeof__(array), \ + __typeof__(&(array)[0]))) +#endif + +/* Evaluates to number of elements in an array; compile error if not + * an array (e.g. pointer) + */ +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + +/* Evaluates to 1 if ptr is part of array, 0 otherwise; compile error if + * "array" argument is not an array (e.g. "ptr" and "array" mixed up) + */ +#ifndef PART_OF_ARRAY +#define PART_OF_ARRAY(array, ptr) \ + ((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)])) +#endif + +#ifndef CONTAINER_OF +#define CONTAINER_OF(ptr, type, field) \ + ((type *)(((char *)(ptr)) - offsetof(type, field))) +#endif + +/* round "x" up/down to next multiple of "align" (which must be a power of 2) */ +#ifndef ROUND_UP +#define ROUND_UP(x, align) \ + (((unsigned long)(x) + ((unsigned long)align - 1)) & \ + ~((unsigned long)align - 1)) +#endif + +#ifndef ROUND_DOWN +#define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1)) +#endif + +/* round up/down to the next word boundary */ +#ifndef WB_UP +#define WB_UP(x) ROUND_UP(x, sizeof(void *)) +#endif + +#ifndef WB_DN +#define WB_DN(x) ROUND_DOWN(x, sizeof(void *)) +#endif + +#ifndef ceiling_fraction +#define ceiling_fraction(numerator, divider) \ + (((numerator) + ((divider) - 1)) / (divider)) +#endif + +#ifndef CHECKIF +#define CHECKIF(expr) if (expr) +#endif + +/** @brief Return larger value of two provided expressions. + * + * @note Arguments are evaluated twice. See Z_MAX for GCC only, single + * evaluation version. + */ +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/** @brief Return smaller value of two provided expressions. + * + * @note Arguments are evaluated twice. See Z_MIN for GCC only, single + * evaluation version. + */ +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef BIT +#define BIT(n) (1UL << (n)) +#endif + +#ifndef BIT_MASK +#define BIT_MASK(n) (BIT(n) - 1) +#endif + +/** + * @brief Check for macro definition in compiler-visible expressions + * + * This trick was pioneered in Linux as the config_enabled() macro. + * The madness has the effect of taking a macro value that may be + * defined to "1" (e.g. CONFIG_MYFEATURE), or may not be defined at + * all and turning it into a literal expression that can be used at + * "runtime". That is, it works similarly to + * "defined(CONFIG_MYFEATURE)" does except that it is an expansion + * that can exist in a standard expression and be seen by the compiler + * and optimizer. Thus much ifdef usage can be replaced with cleaner + * expressions like: + * + * if (IS_ENABLED(CONFIG_MYFEATURE)) + * myfeature_enable(); + * + * INTERNAL + * First pass just to expand any existing macros, we need the macro + * value to be e.g. a literal "1" at expansion time in the next macro, + * not "(1)", etc... Standard recursive expansion does not work. + */ +#define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro) + +/* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro + * is "1", or just "_XXXX" if it's undefined. + * ENABLED: Z_IS_ENABLED2(_XXXX1) + * DISABLED Z_IS_ENABLED2(_XXXX) + */ +#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro) + +/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string + * with a trailing comma), so it has the effect of making this a + * two-argument tuple to the preprocessor only in the case where the + * value is defined to "1" + * ENABLED: _YYYY, <--- note comma! + * DISABLED: _XXXX + */ +#define _XXXX1 _YYYY, + +/* Then we append an extra argument to fool the gcc preprocessor into + * accepting it as a varargs macro. + * arg1 arg2 arg3 + * ENABLED: Z_IS_ENABLED3(_YYYY, 1, 0) + * DISABLED Z_IS_ENABLED3(_XXXX 1, 0) + */ +#define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args true, false) + +/* And our second argument is thus now cooked to be 1 in the case + * where the value is defined to 1, and 0 if not: + */ +#define Z_IS_ENABLED3(ignore_this, val, ...) val + +/* Used to remove brackets from around a single argument. */ +#define __DEBRACKET(...) __VA_ARGS__ + +#define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__) +#define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__ + +/** + * @brief Generates a sequence of code with configurable separator. + * + * Example: + * + * #define FOO(i, _) MY_PWM ## i + * { LISTIFY(PWM_COUNT, FOO, (,)) } + * + * The above two lines expand to: + * + * { MY_PWM0 , MY_PWM1 } + * + * @param LEN The length of the sequence. Must be an integer literal less + * than 255. + * @param F A macro function that accepts at least two arguments: + * F(i, ...). @p F is called repeatedly in the expansion. + * Its first argument @p i is the index in the sequence, and + * the variable list of arguments passed to LISTIFY are passed + * through to @p F. + * + * @param sep Separator (e.g. comma or semicolon). Must be in parentheses; + * this is required to enable providing a comma as separator. + * + * @note Calling LISTIFY with undefined arguments has undefined + * behavior. + */ +#define LISTIFY(LEN, F, sep, ...) UTIL_CAT(Z_UTIL_LISTIFY_, LEN)(F, sep, __VA_ARGS__) + +const char *bt_hex(const void *buf, size_t len); + +void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_UTILS_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/utils_loops.h b/lib/bt/esp_ble_mesh/common/include/mesh/utils_loops.h new file mode 100644 index 00000000..e454f1e0 --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/utils_loops.h @@ -0,0 +1,1051 @@ +/* + * SPDX-FileCopyrightText: 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Internals for looping macros + * + * Repetitive or obscure helper macros needed by mesh_util.h. + */ + +#ifndef _BLE_MESH_UTIL_LOOPS_H_ +#define _BLE_MESH_UTIL_LOOPS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Set of UTIL_LISTIFY particles */ +#define Z_UTIL_LISTIFY_0(F, sep, ...) + +#define Z_UTIL_LISTIFY_1(F, sep, ...) \ + F(0, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_2(F, sep, ...) \ + Z_UTIL_LISTIFY_1(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(1, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_3(F, sep, ...) \ + Z_UTIL_LISTIFY_2(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(2, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_4(F, sep, ...) \ + Z_UTIL_LISTIFY_3(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(3, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_5(F, sep, ...) \ + Z_UTIL_LISTIFY_4(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(4, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_6(F, sep, ...) \ + Z_UTIL_LISTIFY_5(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(5, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_7(F, sep, ...) \ + Z_UTIL_LISTIFY_6(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(6, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_8(F, sep, ...) \ + Z_UTIL_LISTIFY_7(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(7, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_9(F, sep, ...) \ + Z_UTIL_LISTIFY_8(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(8, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_10(F, sep, ...) \ + Z_UTIL_LISTIFY_9(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(9, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_11(F, sep, ...) \ + Z_UTIL_LISTIFY_10(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(10, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_12(F, sep, ...) \ + Z_UTIL_LISTIFY_11(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(11, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_13(F, sep, ...) \ + Z_UTIL_LISTIFY_12(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(12, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_14(F, sep, ...) \ + Z_UTIL_LISTIFY_13(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(13, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_15(F, sep, ...) \ + Z_UTIL_LISTIFY_14(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(14, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_16(F, sep, ...) \ + Z_UTIL_LISTIFY_15(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(15, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_17(F, sep, ...) \ + Z_UTIL_LISTIFY_16(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(16, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_18(F, sep, ...) \ + Z_UTIL_LISTIFY_17(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(17, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_19(F, sep, ...) \ + Z_UTIL_LISTIFY_18(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(18, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_20(F, sep, ...) \ + Z_UTIL_LISTIFY_19(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(19, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_21(F, sep, ...) \ + Z_UTIL_LISTIFY_20(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(20, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_22(F, sep, ...) \ + Z_UTIL_LISTIFY_21(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(21, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_23(F, sep, ...) \ + Z_UTIL_LISTIFY_22(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(22, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_24(F, sep, ...) \ + Z_UTIL_LISTIFY_23(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(23, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_25(F, sep, ...) \ + Z_UTIL_LISTIFY_24(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(24, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_26(F, sep, ...) \ + Z_UTIL_LISTIFY_25(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(25, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_27(F, sep, ...) \ + Z_UTIL_LISTIFY_26(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(26, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_28(F, sep, ...) \ + Z_UTIL_LISTIFY_27(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(27, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_29(F, sep, ...) \ + Z_UTIL_LISTIFY_28(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(28, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_30(F, sep, ...) \ + Z_UTIL_LISTIFY_29(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(29, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_31(F, sep, ...) \ + Z_UTIL_LISTIFY_30(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(30, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_32(F, sep, ...) \ + Z_UTIL_LISTIFY_31(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(31, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_33(F, sep, ...) \ + Z_UTIL_LISTIFY_32(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(32, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_34(F, sep, ...) \ + Z_UTIL_LISTIFY_33(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(33, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_35(F, sep, ...) \ + Z_UTIL_LISTIFY_34(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(34, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_36(F, sep, ...) \ + Z_UTIL_LISTIFY_35(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(35, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_37(F, sep, ...) \ + Z_UTIL_LISTIFY_36(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(36, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_38(F, sep, ...) \ + Z_UTIL_LISTIFY_37(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(37, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_39(F, sep, ...) \ + Z_UTIL_LISTIFY_38(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(38, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_40(F, sep, ...) \ + Z_UTIL_LISTIFY_39(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(39, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_41(F, sep, ...) \ + Z_UTIL_LISTIFY_40(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(40, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_42(F, sep, ...) \ + Z_UTIL_LISTIFY_41(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(41, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_43(F, sep, ...) \ + Z_UTIL_LISTIFY_42(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(42, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_44(F, sep, ...) \ + Z_UTIL_LISTIFY_43(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(43, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_45(F, sep, ...) \ + Z_UTIL_LISTIFY_44(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(44, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_46(F, sep, ...) \ + Z_UTIL_LISTIFY_45(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(45, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_47(F, sep, ...) \ + Z_UTIL_LISTIFY_46(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(46, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_48(F, sep, ...) \ + Z_UTIL_LISTIFY_47(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(47, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_49(F, sep, ...) \ + Z_UTIL_LISTIFY_48(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(48, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_50(F, sep, ...) \ + Z_UTIL_LISTIFY_49(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(49, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_51(F, sep, ...) \ + Z_UTIL_LISTIFY_50(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(50, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_52(F, sep, ...) \ + Z_UTIL_LISTIFY_51(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(51, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_53(F, sep, ...) \ + Z_UTIL_LISTIFY_52(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(52, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_54(F, sep, ...) \ + Z_UTIL_LISTIFY_53(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(53, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_55(F, sep, ...) \ + Z_UTIL_LISTIFY_54(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(54, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_56(F, sep, ...) \ + Z_UTIL_LISTIFY_55(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(55, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_57(F, sep, ...) \ + Z_UTIL_LISTIFY_56(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(56, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_58(F, sep, ...) \ + Z_UTIL_LISTIFY_57(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(57, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_59(F, sep, ...) \ + Z_UTIL_LISTIFY_58(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(58, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_60(F, sep, ...) \ + Z_UTIL_LISTIFY_59(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(59, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_61(F, sep, ...) \ + Z_UTIL_LISTIFY_60(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(60, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_62(F, sep, ...) \ + Z_UTIL_LISTIFY_61(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(61, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_63(F, sep, ...) \ + Z_UTIL_LISTIFY_62(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(62, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_64(F, sep, ...) \ + Z_UTIL_LISTIFY_63(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(63, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_65(F, sep, ...) \ + Z_UTIL_LISTIFY_64(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(64, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_66(F, sep, ...) \ + Z_UTIL_LISTIFY_65(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(65, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_67(F, sep, ...) \ + Z_UTIL_LISTIFY_66(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(66, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_68(F, sep, ...) \ + Z_UTIL_LISTIFY_67(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(67, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_69(F, sep, ...) \ + Z_UTIL_LISTIFY_68(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(68, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_70(F, sep, ...) \ + Z_UTIL_LISTIFY_69(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(69, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_71(F, sep, ...) \ + Z_UTIL_LISTIFY_70(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(70, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_72(F, sep, ...) \ + Z_UTIL_LISTIFY_71(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(71, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_73(F, sep, ...) \ + Z_UTIL_LISTIFY_72(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(72, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_74(F, sep, ...) \ + Z_UTIL_LISTIFY_73(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(73, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_75(F, sep, ...) \ + Z_UTIL_LISTIFY_74(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(74, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_76(F, sep, ...) \ + Z_UTIL_LISTIFY_75(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(75, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_77(F, sep, ...) \ + Z_UTIL_LISTIFY_76(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(76, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_78(F, sep, ...) \ + Z_UTIL_LISTIFY_77(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(77, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_79(F, sep, ...) \ + Z_UTIL_LISTIFY_78(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(78, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_80(F, sep, ...) \ + Z_UTIL_LISTIFY_79(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(79, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_81(F, sep, ...) \ + Z_UTIL_LISTIFY_80(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(80, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_82(F, sep, ...) \ + Z_UTIL_LISTIFY_81(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(81, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_83(F, sep, ...) \ + Z_UTIL_LISTIFY_82(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(82, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_84(F, sep, ...) \ + Z_UTIL_LISTIFY_83(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(83, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_85(F, sep, ...) \ + Z_UTIL_LISTIFY_84(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(84, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_86(F, sep, ...) \ + Z_UTIL_LISTIFY_85(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(85, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_87(F, sep, ...) \ + Z_UTIL_LISTIFY_86(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(86, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_88(F, sep, ...) \ + Z_UTIL_LISTIFY_87(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(87, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_89(F, sep, ...) \ + Z_UTIL_LISTIFY_88(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(88, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_90(F, sep, ...) \ + Z_UTIL_LISTIFY_89(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(89, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_91(F, sep, ...) \ + Z_UTIL_LISTIFY_90(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(90, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_92(F, sep, ...) \ + Z_UTIL_LISTIFY_91(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(91, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_93(F, sep, ...) \ + Z_UTIL_LISTIFY_92(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(92, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_94(F, sep, ...) \ + Z_UTIL_LISTIFY_93(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(93, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_95(F, sep, ...) \ + Z_UTIL_LISTIFY_94(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(94, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_96(F, sep, ...) \ + Z_UTIL_LISTIFY_95(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(95, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_97(F, sep, ...) \ + Z_UTIL_LISTIFY_96(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(96, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_98(F, sep, ...) \ + Z_UTIL_LISTIFY_97(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(97, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_99(F, sep, ...) \ + Z_UTIL_LISTIFY_98(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(98, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_100(F, sep, ...) \ + Z_UTIL_LISTIFY_99(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(99, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_101(F, sep, ...) \ + Z_UTIL_LISTIFY_100(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(100, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_102(F, sep, ...) \ + Z_UTIL_LISTIFY_101(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(101, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_103(F, sep, ...) \ + Z_UTIL_LISTIFY_102(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(102, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_104(F, sep, ...) \ + Z_UTIL_LISTIFY_103(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(103, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_105(F, sep, ...) \ + Z_UTIL_LISTIFY_104(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(104, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_106(F, sep, ...) \ + Z_UTIL_LISTIFY_105(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(105, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_107(F, sep, ...) \ + Z_UTIL_LISTIFY_106(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(106, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_108(F, sep, ...) \ + Z_UTIL_LISTIFY_107(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(107, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_109(F, sep, ...) \ + Z_UTIL_LISTIFY_108(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(108, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_110(F, sep, ...) \ + Z_UTIL_LISTIFY_109(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(109, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_111(F, sep, ...) \ + Z_UTIL_LISTIFY_110(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(110, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_112(F, sep, ...) \ + Z_UTIL_LISTIFY_111(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(111, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_113(F, sep, ...) \ + Z_UTIL_LISTIFY_112(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(112, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_114(F, sep, ...) \ + Z_UTIL_LISTIFY_113(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(113, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_115(F, sep, ...) \ + Z_UTIL_LISTIFY_114(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(114, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_116(F, sep, ...) \ + Z_UTIL_LISTIFY_115(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(115, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_117(F, sep, ...) \ + Z_UTIL_LISTIFY_116(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(116, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_118(F, sep, ...) \ + Z_UTIL_LISTIFY_117(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(117, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_119(F, sep, ...) \ + Z_UTIL_LISTIFY_118(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(118, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_120(F, sep, ...) \ + Z_UTIL_LISTIFY_119(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(119, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_121(F, sep, ...) \ + Z_UTIL_LISTIFY_120(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(120, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_122(F, sep, ...) \ + Z_UTIL_LISTIFY_121(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(121, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_123(F, sep, ...) \ + Z_UTIL_LISTIFY_122(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(122, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_124(F, sep, ...) \ + Z_UTIL_LISTIFY_123(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(123, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_125(F, sep, ...) \ + Z_UTIL_LISTIFY_124(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(124, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_126(F, sep, ...) \ + Z_UTIL_LISTIFY_125(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(125, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_127(F, sep, ...) \ + Z_UTIL_LISTIFY_126(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(126, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_128(F, sep, ...) \ + Z_UTIL_LISTIFY_127(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(127, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_129(F, sep, ...) \ + Z_UTIL_LISTIFY_128(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(128, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_130(F, sep, ...) \ + Z_UTIL_LISTIFY_129(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(129, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_131(F, sep, ...) \ + Z_UTIL_LISTIFY_130(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(130, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_132(F, sep, ...) \ + Z_UTIL_LISTIFY_131(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(131, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_133(F, sep, ...) \ + Z_UTIL_LISTIFY_132(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(132, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_134(F, sep, ...) \ + Z_UTIL_LISTIFY_133(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(133, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_135(F, sep, ...) \ + Z_UTIL_LISTIFY_134(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(134, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_136(F, sep, ...) \ + Z_UTIL_LISTIFY_135(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(135, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_137(F, sep, ...) \ + Z_UTIL_LISTIFY_136(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(136, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_138(F, sep, ...) \ + Z_UTIL_LISTIFY_137(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(137, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_139(F, sep, ...) \ + Z_UTIL_LISTIFY_138(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(138, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_140(F, sep, ...) \ + Z_UTIL_LISTIFY_139(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(139, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_141(F, sep, ...) \ + Z_UTIL_LISTIFY_140(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(140, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_142(F, sep, ...) \ + Z_UTIL_LISTIFY_141(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(141, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_143(F, sep, ...) \ + Z_UTIL_LISTIFY_142(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(142, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_144(F, sep, ...) \ + Z_UTIL_LISTIFY_143(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(143, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_145(F, sep, ...) \ + Z_UTIL_LISTIFY_144(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(144, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_146(F, sep, ...) \ + Z_UTIL_LISTIFY_145(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(145, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_147(F, sep, ...) \ + Z_UTIL_LISTIFY_146(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(146, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_148(F, sep, ...) \ + Z_UTIL_LISTIFY_147(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(147, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_149(F, sep, ...) \ + Z_UTIL_LISTIFY_148(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(148, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_150(F, sep, ...) \ + Z_UTIL_LISTIFY_149(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(149, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_151(F, sep, ...) \ + Z_UTIL_LISTIFY_150(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(150, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_152(F, sep, ...) \ + Z_UTIL_LISTIFY_151(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(151, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_153(F, sep, ...) \ + Z_UTIL_LISTIFY_152(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(152, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_154(F, sep, ...) \ + Z_UTIL_LISTIFY_153(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(153, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_155(F, sep, ...) \ + Z_UTIL_LISTIFY_154(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(154, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_156(F, sep, ...) \ + Z_UTIL_LISTIFY_155(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(155, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_157(F, sep, ...) \ + Z_UTIL_LISTIFY_156(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(156, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_158(F, sep, ...) \ + Z_UTIL_LISTIFY_157(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(157, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_159(F, sep, ...) \ + Z_UTIL_LISTIFY_158(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(158, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_160(F, sep, ...) \ + Z_UTIL_LISTIFY_159(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(159, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_161(F, sep, ...) \ + Z_UTIL_LISTIFY_160(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(160, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_162(F, sep, ...) \ + Z_UTIL_LISTIFY_161(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(161, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_163(F, sep, ...) \ + Z_UTIL_LISTIFY_162(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(162, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_164(F, sep, ...) \ + Z_UTIL_LISTIFY_163(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(163, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_165(F, sep, ...) \ + Z_UTIL_LISTIFY_164(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(164, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_166(F, sep, ...) \ + Z_UTIL_LISTIFY_165(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(165, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_167(F, sep, ...) \ + Z_UTIL_LISTIFY_166(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(166, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_168(F, sep, ...) \ + Z_UTIL_LISTIFY_167(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(167, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_169(F, sep, ...) \ + Z_UTIL_LISTIFY_168(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(168, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_170(F, sep, ...) \ + Z_UTIL_LISTIFY_169(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(169, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_171(F, sep, ...) \ + Z_UTIL_LISTIFY_170(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(170, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_172(F, sep, ...) \ + Z_UTIL_LISTIFY_171(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(171, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_173(F, sep, ...) \ + Z_UTIL_LISTIFY_172(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(172, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_174(F, sep, ...) \ + Z_UTIL_LISTIFY_173(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(173, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_175(F, sep, ...) \ + Z_UTIL_LISTIFY_174(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(174, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_176(F, sep, ...) \ + Z_UTIL_LISTIFY_175(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(175, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_177(F, sep, ...) \ + Z_UTIL_LISTIFY_176(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(176, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_178(F, sep, ...) \ + Z_UTIL_LISTIFY_177(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(177, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_179(F, sep, ...) \ + Z_UTIL_LISTIFY_178(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(178, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_180(F, sep, ...) \ + Z_UTIL_LISTIFY_179(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(179, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_181(F, sep, ...) \ + Z_UTIL_LISTIFY_180(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(180, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_182(F, sep, ...) \ + Z_UTIL_LISTIFY_181(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(181, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_183(F, sep, ...) \ + Z_UTIL_LISTIFY_182(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(182, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_184(F, sep, ...) \ + Z_UTIL_LISTIFY_183(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(183, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_185(F, sep, ...) \ + Z_UTIL_LISTIFY_184(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(184, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_186(F, sep, ...) \ + Z_UTIL_LISTIFY_185(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(185, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_187(F, sep, ...) \ + Z_UTIL_LISTIFY_186(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(186, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_188(F, sep, ...) \ + Z_UTIL_LISTIFY_187(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(187, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_189(F, sep, ...) \ + Z_UTIL_LISTIFY_188(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(188, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_190(F, sep, ...) \ + Z_UTIL_LISTIFY_189(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(189, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_191(F, sep, ...) \ + Z_UTIL_LISTIFY_190(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(190, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_192(F, sep, ...) \ + Z_UTIL_LISTIFY_191(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(191, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_193(F, sep, ...) \ + Z_UTIL_LISTIFY_192(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(192, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_194(F, sep, ...) \ + Z_UTIL_LISTIFY_193(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(193, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_195(F, sep, ...) \ + Z_UTIL_LISTIFY_194(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(194, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_196(F, sep, ...) \ + Z_UTIL_LISTIFY_195(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(195, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_197(F, sep, ...) \ + Z_UTIL_LISTIFY_196(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(196, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_198(F, sep, ...) \ + Z_UTIL_LISTIFY_197(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(197, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_199(F, sep, ...) \ + Z_UTIL_LISTIFY_198(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(198, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_200(F, sep, ...) \ + Z_UTIL_LISTIFY_199(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(199, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_201(F, sep, ...) \ + Z_UTIL_LISTIFY_200(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(200, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_202(F, sep, ...) \ + Z_UTIL_LISTIFY_201(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(201, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_203(F, sep, ...) \ + Z_UTIL_LISTIFY_202(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(202, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_204(F, sep, ...) \ + Z_UTIL_LISTIFY_203(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(203, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_205(F, sep, ...) \ + Z_UTIL_LISTIFY_204(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(204, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_206(F, sep, ...) \ + Z_UTIL_LISTIFY_205(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(205, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_207(F, sep, ...) \ + Z_UTIL_LISTIFY_206(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(206, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_208(F, sep, ...) \ + Z_UTIL_LISTIFY_207(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(207, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_209(F, sep, ...) \ + Z_UTIL_LISTIFY_208(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(208, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_210(F, sep, ...) \ + Z_UTIL_LISTIFY_209(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(209, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_211(F, sep, ...) \ + Z_UTIL_LISTIFY_210(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(210, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_212(F, sep, ...) \ + Z_UTIL_LISTIFY_211(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(211, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_213(F, sep, ...) \ + Z_UTIL_LISTIFY_212(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(212, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_214(F, sep, ...) \ + Z_UTIL_LISTIFY_213(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(213, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_215(F, sep, ...) \ + Z_UTIL_LISTIFY_214(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(214, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_216(F, sep, ...) \ + Z_UTIL_LISTIFY_215(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(215, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_217(F, sep, ...) \ + Z_UTIL_LISTIFY_216(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(216, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_218(F, sep, ...) \ + Z_UTIL_LISTIFY_217(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(217, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_219(F, sep, ...) \ + Z_UTIL_LISTIFY_218(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(218, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_220(F, sep, ...) \ + Z_UTIL_LISTIFY_219(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(219, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_221(F, sep, ...) \ + Z_UTIL_LISTIFY_220(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(220, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_222(F, sep, ...) \ + Z_UTIL_LISTIFY_221(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(221, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_223(F, sep, ...) \ + Z_UTIL_LISTIFY_222(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(222, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_224(F, sep, ...) \ + Z_UTIL_LISTIFY_223(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(223, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_225(F, sep, ...) \ + Z_UTIL_LISTIFY_224(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(224, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_226(F, sep, ...) \ + Z_UTIL_LISTIFY_225(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(225, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_227(F, sep, ...) \ + Z_UTIL_LISTIFY_226(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(226, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_228(F, sep, ...) \ + Z_UTIL_LISTIFY_227(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(227, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_229(F, sep, ...) \ + Z_UTIL_LISTIFY_228(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(228, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_230(F, sep, ...) \ + Z_UTIL_LISTIFY_229(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(229, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_231(F, sep, ...) \ + Z_UTIL_LISTIFY_230(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(230, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_232(F, sep, ...) \ + Z_UTIL_LISTIFY_231(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(231, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_233(F, sep, ...) \ + Z_UTIL_LISTIFY_232(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(232, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_234(F, sep, ...) \ + Z_UTIL_LISTIFY_233(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(233, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_235(F, sep, ...) \ + Z_UTIL_LISTIFY_234(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(234, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_236(F, sep, ...) \ + Z_UTIL_LISTIFY_235(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(235, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_237(F, sep, ...) \ + Z_UTIL_LISTIFY_236(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(236, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_238(F, sep, ...) \ + Z_UTIL_LISTIFY_237(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(237, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_239(F, sep, ...) \ + Z_UTIL_LISTIFY_238(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(238, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_240(F, sep, ...) \ + Z_UTIL_LISTIFY_239(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(239, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_241(F, sep, ...) \ + Z_UTIL_LISTIFY_240(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(240, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_242(F, sep, ...) \ + Z_UTIL_LISTIFY_241(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(241, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_243(F, sep, ...) \ + Z_UTIL_LISTIFY_242(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(242, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_244(F, sep, ...) \ + Z_UTIL_LISTIFY_243(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(243, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_245(F, sep, ...) \ + Z_UTIL_LISTIFY_244(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(244, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_246(F, sep, ...) \ + Z_UTIL_LISTIFY_245(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(245, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_247(F, sep, ...) \ + Z_UTIL_LISTIFY_246(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(246, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_248(F, sep, ...) \ + Z_UTIL_LISTIFY_247(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(247, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_249(F, sep, ...) \ + Z_UTIL_LISTIFY_248(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(248, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_250(F, sep, ...) \ + Z_UTIL_LISTIFY_249(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(249, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_251(F, sep, ...) \ + Z_UTIL_LISTIFY_250(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(250, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_252(F, sep, ...) \ + Z_UTIL_LISTIFY_251(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(251, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_253(F, sep, ...) \ + Z_UTIL_LISTIFY_252(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(252, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_254(F, sep, ...) \ + Z_UTIL_LISTIFY_253(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(253, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_255(F, sep, ...) \ + Z_UTIL_LISTIFY_254(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(254, __VA_ARGS__) + +#define Z_UTIL_LISTIFY_256(F, sep, ...) \ + Z_UTIL_LISTIFY_255(F, sep, __VA_ARGS__) __DEBRACKET sep \ + F(255, __VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_UTIL_LOOPS_H_ */ -- cgit v1.2.3