summaryrefslogtreecommitdiff
path: root/lib/bt/porting/nimble/include
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-03-28 14:32:49 +1100
committerjacqueline <me@jacqueline.id.au>2024-03-28 14:32:49 +1100
commitee29c25b29eaa4fac4e897442634b69ecc8d8125 (patch)
tree8c5f1a140463f20f104316fa3492984e191154e9 /lib/bt/porting/nimble/include
parent239e6d89507a24c849385f4bfa93ac4ad58e5de5 (diff)
downloadtangara-fw-ee29c25b29eaa4fac4e897442634b69ecc8d8125.tar.gz
Fork ESP-IDF's bluetooth component
i want better sbc encoding, and no cla will stop me
Diffstat (limited to 'lib/bt/porting/nimble/include')
-rw-r--r--lib/bt/porting/nimble/include/nimble/ble.h319
-rw-r--r--lib/bt/porting/nimble/include/nimble/ble_hci_trans.h328
-rw-r--r--lib/bt/porting/nimble/include/nimble/nimble_npl.h180
-rw-r--r--lib/bt/porting/nimble/include/nimble/nimble_opt.h34
-rw-r--r--lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h128
-rw-r--r--lib/bt/porting/nimble/include/nimble/nimble_port.h78
-rw-r--r--lib/bt/porting/nimble/include/os/endian.h296
-rw-r--r--lib/bt/porting/nimble/include/os/os.h66
-rw-r--r--lib/bt/porting/nimble/include/os/os_error.h69
-rw-r--r--lib/bt/porting/nimble/include/os/os_mbuf.h1145
-rw-r--r--lib/bt/porting/nimble/include/os/os_mempool.h407
-rw-r--r--lib/bt/porting/nimble/include/os/queue.h218
-rw-r--r--lib/bt/porting/nimble/include/os/util.h45
13 files changed, 3313 insertions, 0 deletions
diff --git a/lib/bt/porting/nimble/include/nimble/ble.h b/lib/bt/porting/nimble/include/nimble/ble.h
new file mode 100644
index 00000000..f037d356
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/ble.h
@@ -0,0 +1,319 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_
+#define H_BLE_
+
+#include <inttypes.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The number of advertising instances */
+#define BLE_ADV_INSTANCES (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1)
+
+/* BLE encryption block definitions */
+#define BLE_ENC_BLOCK_SIZE (16)
+
+/* 4 byte header + 251 byte payload. */
+#define BLE_ACL_MAX_PKT_SIZE 255
+
+struct ble_encryption_block
+{
+ uint8_t key[BLE_ENC_BLOCK_SIZE];
+ uint8_t plain_text[BLE_ENC_BLOCK_SIZE];
+ uint8_t cipher_text[BLE_ENC_BLOCK_SIZE];
+};
+
+/*
+ * BLE MBUF structure:
+ *
+ * The BLE mbuf structure is as follows. Note that this structure applies to
+ * the packet header mbuf (not mbufs that are part of a "packet chain"):
+ * struct os_mbuf (16)
+ * struct os_mbuf_pkthdr (8)
+ * struct ble_mbuf_hdr (8)
+ * Data buffer (payload size, in bytes)
+ *
+ * The BLE mbuf header contains the following:
+ * flags: bitfield with the following values
+ * 0x01: Set if there was a match on the whitelist
+ * 0x02: Set if a connect request was transmitted upon receiving pdu
+ * 0x04: Set the first time we transmit the PDU (used to detect retry).
+ * channel: The logical BLE channel PHY channel # (0 - 39)
+ * crcok: flag denoting CRC check passed (1) or failed (0).
+ * rssi: RSSI, in dBm.
+ */
+struct ble_mbuf_hdr_rxinfo
+{
+ uint16_t flags;
+ uint8_t channel;
+ uint8_t handle;
+ int8_t rssi;
+ /* XXX: we could just use single phy_mode field */
+ int8_t phy;
+ uint8_t phy_mode;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ int8_t rpa_index;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+ void *user_data;
+#endif
+};
+
+/*
+ * Flag definitions for rxinfo
+ *
+ * Note: it's ok to have symbols with the same values as long as they cannot be
+ * set for the same PDU (e.g. one use by scanner, other one used by
+ * connection)
+ */
+#define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000)
+#define BLE_MBUF_HDR_F_IGNORED (0x8000)
+#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000)
+#define BLE_MBUF_HDR_F_INITA_RESOLVED (0x2000)
+#define BLE_MBUF_HDR_F_TARGETA_RESOLVED (0x2000)
+#define BLE_MBUF_HDR_F_EXT_ADV_SEC (0x1000)
+#define BLE_MBUF_HDR_F_EXT_ADV (0x0800)
+#define BLE_MBUF_HDR_F_RESOLVED (0x0400)
+#define BLE_MBUF_HDR_F_AUX_PTR_WAIT (0x0200)
+#define BLE_MBUF_HDR_F_AUX_INVALID (0x0100)
+#define BLE_MBUF_HDR_F_CRC_OK (0x0080)
+#define BLE_MBUF_HDR_F_DEVMATCH (0x0040)
+#define BLE_MBUF_HDR_F_MIC_FAILURE (0x0020)
+#define BLE_MBUF_HDR_F_SCAN_RSP_TXD (0x0010)
+#define BLE_MBUF_HDR_F_SCAN_RSP_RXD (0x0008)
+#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x0007)
+
+/* Transmit info. NOTE: no flags defined */
+struct ble_mbuf_hdr_txinfo
+{
+ uint8_t flags;
+ uint8_t reserve0;
+ uint8_t pyld_len;
+ uint8_t hdr_byte;
+ uint16_t offset;
+};
+
+struct ble_mbuf_hdr
+{
+ union {
+ struct ble_mbuf_hdr_rxinfo rxinfo;
+ struct ble_mbuf_hdr_txinfo txinfo;
+ };
+ uint32_t beg_cputime;
+ uint32_t rem_usecs;
+};
+
+#define BLE_MBUF_HDR_IGNORED(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_IGNORED))
+
+#define BLE_MBUF_HDR_SCAN_REQ_TXD(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD))
+
+#define BLE_MBUF_HDR_EXT_ADV_SEC(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV_SEC))
+
+#define BLE_MBUF_HDR_EXT_ADV(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV))
+
+#define BLE_MBUF_HDR_DEVMATCH(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH))
+
+#define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD))
+
+#define BLE_MBUF_HDR_AUX_INVALID(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID))
+
+#define BLE_MBUF_HDR_WAIT_AUX(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT))
+
+#define BLE_MBUF_HDR_CRC_OK(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_CRC_OK))
+
+#define BLE_MBUF_HDR_MIC_FAILURE(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_MIC_FAILURE))
+
+#define BLE_MBUF_HDR_RESOLVED(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED))
+
+#define BLE_MBUF_HDR_INITA_RESOLVED(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_INITA_RESOLVED))
+
+#define BLE_MBUF_HDR_TARGETA_RESOLVED(hdr) \
+ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED))
+
+#define BLE_MBUF_HDR_RX_STATE(hdr) \
+ ((uint8_t)((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK))
+
+#define BLE_MBUF_HDR_PTR(om) \
+ (struct ble_mbuf_hdr *)((uint8_t *)om + sizeof(struct os_mbuf) + \
+ sizeof(struct os_mbuf_pkthdr))
+
+/* BLE mbuf overhead per packet header mbuf */
+#define BLE_MBUF_PKTHDR_OVERHEAD \
+ (sizeof(struct os_mbuf_pkthdr) + sizeof(struct ble_mbuf_hdr))
+
+#define BLE_MBUF_MEMBLOCK_OVERHEAD \
+ (sizeof(struct os_mbuf) + BLE_MBUF_PKTHDR_OVERHEAD)
+
+/* Length of host user header. Only contains the peer's connection handle. */
+#define BLE_MBUF_HS_HDR_LEN (2)
+
+#define BLE_DEV_ADDR_LEN (6)
+extern uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
+extern uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
+
+/* BLE Error Codes (Core v4.2 Vol 2 part D) */
+enum ble_error_codes
+{
+ /* An "error" code of 0x0 means success */
+ BLE_ERR_SUCCESS = 0x00,
+ BLE_ERR_UNKNOWN_HCI_CMD = 0x01,
+ BLE_ERR_UNK_CONN_ID = 0x02,
+ BLE_ERR_HW_FAIL = 0x03,
+ BLE_ERR_PAGE_TMO = 0x04,
+ BLE_ERR_AUTH_FAIL = 0x05,
+ BLE_ERR_PINKEY_MISSING = 0x06,
+ BLE_ERR_MEM_CAPACITY = 0x07,
+ BLE_ERR_CONN_SPVN_TMO = 0x08,
+ BLE_ERR_CONN_LIMIT = 0x09,
+ BLE_ERR_SYNCH_CONN_LIMIT = 0x0a,
+ BLE_ERR_ACL_CONN_EXISTS = 0x0b,
+ BLE_ERR_CMD_DISALLOWED = 0x0c,
+ BLE_ERR_CONN_REJ_RESOURCES = 0x0d,
+ BLE_ERR_CONN_REJ_SECURITY = 0x0e,
+ BLE_ERR_CONN_REJ_BD_ADDR = 0x0f,
+ BLE_ERR_CONN_ACCEPT_TMO = 0x10,
+ BLE_ERR_UNSUPPORTED = 0x11,
+ BLE_ERR_INV_HCI_CMD_PARMS = 0x12,
+ BLE_ERR_REM_USER_CONN_TERM = 0x13,
+ BLE_ERR_RD_CONN_TERM_RESRCS = 0x14,
+ BLE_ERR_RD_CONN_TERM_PWROFF = 0x15,
+ BLE_ERR_CONN_TERM_LOCAL = 0x16,
+ BLE_ERR_REPEATED_ATTEMPTS = 0x17,
+ BLE_ERR_NO_PAIRING = 0x18,
+ BLE_ERR_UNK_LMP = 0x19,
+ BLE_ERR_UNSUPP_REM_FEATURE = 0x1a,
+ BLE_ERR_SCO_OFFSET = 0x1b,
+ BLE_ERR_SCO_ITVL = 0x1c,
+ BLE_ERR_SCO_AIR_MODE = 0x1d,
+ BLE_ERR_INV_LMP_LL_PARM = 0x1e,
+ BLE_ERR_UNSPECIFIED = 0x1f,
+ BLE_ERR_UNSUPP_LMP_LL_PARM = 0x20,
+ BLE_ERR_NO_ROLE_CHANGE = 0x21,
+ BLE_ERR_LMP_LL_RSP_TMO = 0x22,
+ BLE_ERR_LMP_COLLISION = 0x23,
+ BLE_ERR_LMP_PDU = 0x24,
+ BLE_ERR_ENCRYPTION_MODE = 0x25,
+ BLE_ERR_LINK_KEY_CHANGE = 0x26,
+ BLE_ERR_UNSUPP_QOS = 0x27,
+ BLE_ERR_INSTANT_PASSED = 0x28,
+ BLE_ERR_UNIT_KEY_PAIRING = 0x29,
+ BLE_ERR_DIFF_TRANS_COLL = 0x2a,
+ /* BLE_ERR_RESERVED = 0x2b */
+ BLE_ERR_QOS_PARM = 0x2c,
+ BLE_ERR_QOS_REJECTED = 0x2d,
+ BLE_ERR_CHAN_CLASS = 0x2e,
+ BLE_ERR_INSUFFICIENT_SEC = 0x2f,
+ BLE_ERR_PARM_OUT_OF_RANGE = 0x30,
+ /* BLE_ERR_RESERVED = 0x31 */
+ BLE_ERR_PENDING_ROLE_SW = 0x32,
+ /* BLE_ERR_RESERVED = 0x33 */
+ BLE_ERR_RESERVED_SLOT = 0x34,
+ BLE_ERR_ROLE_SW_FAIL = 0x35,
+ BLE_ERR_INQ_RSP_TOO_BIG = 0x36,
+ BLE_ERR_SEC_SIMPLE_PAIR = 0x37,
+ BLE_ERR_HOST_BUSY_PAIR = 0x38,
+ BLE_ERR_CONN_REJ_CHANNEL = 0x39,
+ BLE_ERR_CTLR_BUSY = 0x3a,
+ BLE_ERR_CONN_PARMS = 0x3b,
+ BLE_ERR_DIR_ADV_TMO = 0x3c,
+ BLE_ERR_CONN_TERM_MIC = 0x3d,
+ BLE_ERR_CONN_ESTABLISHMENT = 0x3e,
+ BLE_ERR_MAC_CONN_FAIL = 0x3f,
+ BLE_ERR_COARSE_CLK_ADJ = 0x40,
+ BLE_ERR_TYPE0_SUBMAP_NDEF = 0x41,
+ BLE_ERR_UNK_ADV_INDENT = 0x42,
+ BLE_ERR_LIMIT_REACHED = 0x43,
+ BLE_ERR_OPERATION_CANCELLED = 0x44,
+ BLE_ERR_PACKET_TOO_LONG = 0x45,
+ BLE_ERR_MAX = 0xff
+};
+
+/* HW error codes */
+#define BLE_HW_ERR_DO_NOT_USE (0) /* XXX: reserve this one for now */
+#define BLE_HW_ERR_HCI_SYNC_LOSS (1)
+
+/* Own Bluetooth Device address type */
+#define BLE_OWN_ADDR_PUBLIC (0x00)
+#define BLE_OWN_ADDR_RANDOM (0x01)
+#define BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT (0x02)
+#define BLE_OWN_ADDR_RPA_RANDOM_DEFAULT (0x03)
+
+/* Bluetooth Device address type */
+#define BLE_ADDR_PUBLIC (0x00)
+#define BLE_ADDR_RANDOM (0x01)
+#define BLE_ADDR_PUBLIC_ID (0x02)
+#define BLE_ADDR_RANDOM_ID (0x03)
+
+#define BLE_ADDR_ANY (&(ble_addr_t) { 0, {0, 0, 0, 0, 0, 0} })
+
+#define BLE_ADDR_IS_RPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
+ ((addr)->val[5] & 0xc0) == 0x40)
+#define BLE_ADDR_IS_NRPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
+ ((addr)->val[5] & 0xc0) == 0x00)
+#define BLE_ADDR_IS_STATIC(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
+ ((addr)->val[5] & 0xc0) == 0xc0)
+
+typedef struct {
+ uint8_t type;
+ uint8_t val[6];
+} ble_addr_t;
+
+
+static inline int ble_addr_cmp(const ble_addr_t *a, const ble_addr_t *b)
+{
+ int type_diff;
+
+ type_diff = a->type - b->type;
+ if (type_diff != 0) {
+ return type_diff;
+ }
+
+ return memcmp(a->val, b->val, sizeof(a->val));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_ */
diff --git a/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h b/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h
new file mode 100644
index 00000000..5bbf9224
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h
@@ -0,0 +1,328 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_HCI_TRANSPORT_
+#define H_HCI_TRANSPORT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include "os/os_mempool.h"
+
+#define BLE_HCI_TRANS_CMD_SZ 260
+/*** Type of buffers for holding commands and events. */
+/**
+ * Controller-to-host event buffers. Events have one of two priorities:
+ * o Low-priority (BLE_HCI_TRANS_BUF_EVT_LO)
+ * o High-priority (BLE_HCI_TRANS_BUF_EVT_HI)
+ *
+ * Low-priority event buffers are only used for advertising reports. If there
+ * are no free low-priority event buffers, then an incoming advertising report
+ * will get dropped.
+ *
+ * High-priority event buffers are for everything except advertising reports.
+ * If there are no free high-priority event buffers, a request to allocate one
+ * will try to allocate a low-priority buffer instead.
+ *
+ * If you want all events to be given equal treatment, then you should allocate
+ * low-priority events only.
+ *
+ * Event priorities solve the problem of critical events getting dropped due to
+ * a flood of advertising reports. This solution is likely temporary: when
+ * HCI flow control is added, event priorities may become obsolete.
+ *
+ * Not all transports distinguish between low and high priority events. If the
+ * transport does not have separate settings for low and high buffer counts,
+ * then it treats all events with equal priority.
+ */
+#define BLE_HCI_TRANS_BUF_EVT_LO 1
+#define BLE_HCI_TRANS_BUF_EVT_HI 2
+
+/* Host-to-controller command. */
+#define BLE_HCI_TRANS_BUF_CMD 3
+
+/** Callback function types; executed when HCI packets are received. */
+typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
+typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
+
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD)
+#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI)
+#define ble_transport_free ble_hci_trans_buf_free
+
+struct ble_hci_trans_funcs_t {
+ int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om);
+ int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd);
+ int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om);
+ int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev);
+ int(*_ble_hci_trans_reset)(void);
+ int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb, void *arg);
+};
+
+extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr;
+
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd The HCI event to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
+#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd The HCI command to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type The type of buffer to allocate; one of the
+ * BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return The allocated buffer on success;
+ * NULL on buffer exhaustion.
+ */
+extern uint8_t *r_ble_hci_trans_buf_alloc(int type);
+#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc
+
+/**
+ * Frees the specified flat buffer. The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf The buffer to free.
+ */
+extern void r_ble_hci_trans_buf_free(uint8_t *buf);
+#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free
+
+/**
+ * Configures a callback to get executed whenever an ACL data packet is freed.
+ * The function is called immediately before the free occurs.
+ *
+ * @param cb The callback to configure.
+ * @param arg An optional argument to pass to the callback.
+ *
+ * @return 0 on success;
+ * BLE_ERR_UNSUPPORTED if the transport does not
+ * support this operation.
+ */
+extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
+#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb
+
+/**
+ * Configures the HCI transport to operate with a controller. The transport
+ * will execute specified callbacks upon receiving HCI packets from the host.
+ *
+ * @param cmd_cb The callback to execute upon receiving an HCI
+ * command.
+ * @param cmd_arg Optional argument to pass to the command
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+ void *cmd_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb,
+ void *acl_arg);
+#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll
+
+/**
+ * Configures the HCI transport to operate with a host. The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb The callback to execute upon receiving an HCI
+ * event.
+ * @param evt_arg Optional argument to pass to the event
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
+ void *evt_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb,
+ void *acl_arg);
+#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs
+
+/**
+ * Resets the HCI module to a clean state. Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_reset(void);
+#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset
+
+void esp_ble_hci_trans_init(uint8_t);
+
+#else
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd The HCI event to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd The HCI command to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type The type of buffer to allocate; one of the
+ * BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return The allocated buffer on success;
+ * NULL on buffer exhaustion.
+ */
+int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type The type of buffer to allocate; one of the
+ * BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return The allocated buffer on success;
+ * NULL on buffer exhaustion.
+ */
+uint8_t *esp_ble_hci_trans_buf_alloc(int type);
+
+/**
+ * Frees the specified flat buffer. The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf The buffer to free.
+ */
+void esp_ble_hci_trans_buf_free(uint8_t *buf);
+
+/**
+ * Configures the HCI transport to operate with a host. The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb The callback to execute upon receiving an HCI
+ * event.
+ * @param evt_arg Optional argument to pass to the event
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
+ void *evt_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb,
+ void *acl_arg);
+
+/**
+ * Resets the HCI module to a clean state. Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_reset(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_HCI_TRANSPORT_ */
diff --git a/lib/bt/porting/nimble/include/nimble/nimble_npl.h b/lib/bt/porting/nimble/include/nimble/nimble_npl.h
new file mode 100644
index 00000000..c11a2972
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/nimble_npl.h
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _NIMBLE_NPL_H_
+#define _NIMBLE_NPL_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ble_npl_event;
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+enum ble_npl_error {
+ BLE_NPL_OK = 0,
+ BLE_NPL_ENOMEM = 1,
+ BLE_NPL_EINVAL = 2,
+ BLE_NPL_INVALID_PARAM = 3,
+ BLE_NPL_MEM_NOT_ALIGNED = 4,
+ BLE_NPL_BAD_MUTEX = 5,
+ BLE_NPL_TIMEOUT = 6,
+ BLE_NPL_ERR_IN_ISR = 7,
+ BLE_NPL_ERR_PRIV = 8,
+ BLE_NPL_OS_NOT_STARTED = 9,
+ BLE_NPL_ENOENT = 10,
+ BLE_NPL_EBUSY = 11,
+ BLE_NPL_ERROR = 12,
+};
+
+typedef enum ble_npl_error ble_npl_error_t;
+
+/* Include OS-specific definitions */
+#include "nimble/nimble_npl_os.h"
+
+/*
+ * Generic
+ */
+
+bool ble_npl_os_started(void);
+
+void *ble_npl_get_current_task_id(void);
+
+/*
+ * Event queue
+ */
+
+void ble_npl_eventq_init(struct ble_npl_eventq *evq);
+
+void ble_npl_eventq_deinit(struct ble_npl_eventq *evq);
+
+struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq,
+ ble_npl_time_t tmo);
+
+void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev);
+
+void ble_npl_eventq_remove(struct ble_npl_eventq *evq,
+ struct ble_npl_event *ev);
+
+void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+ void *arg);
+
+bool ble_npl_event_is_queued(struct ble_npl_event *ev);
+
+void *ble_npl_event_get_arg(struct ble_npl_event *ev);
+
+void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg);
+
+bool ble_npl_eventq_is_empty(struct ble_npl_eventq *evq);
+
+void ble_npl_event_run(struct ble_npl_event *ev);
+
+/*
+ * Mutexes
+ */
+
+ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu);
+
+ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu,
+ ble_npl_time_t timeout);
+
+ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu);
+
+ble_npl_error_t ble_npl_mutex_deinit(struct ble_npl_mutex *mu);
+
+/*
+ * Semaphores
+ */
+
+ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
+
+ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem,
+ ble_npl_time_t timeout);
+
+ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
+
+ble_npl_error_t ble_npl_sem_deinit(struct ble_npl_sem *sem);
+
+uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
+
+/*
+ * Callouts
+ */
+
+int ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+ ble_npl_event_fn *ev_cb, void *ev_arg);
+
+ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *co,
+ ble_npl_time_t ticks);
+
+void ble_npl_callout_stop(struct ble_npl_callout *co);
+
+bool ble_npl_callout_is_active(struct ble_npl_callout *co);
+
+ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co);
+
+ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
+ ble_npl_time_t time);
+
+void ble_npl_callout_set_arg(struct ble_npl_callout *co,
+ void *arg);
+/*
+ * Time functions
+ */
+
+ble_npl_time_t ble_npl_time_get(void);
+
+ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks);
+
+ble_npl_error_t ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms);
+
+ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms);
+
+uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks);
+
+void ble_npl_time_delay(ble_npl_time_t ticks);
+
+/*
+ * Hardware-specific
+ *
+ * These symbols should be most likely defined by application since they are
+ * specific to hardware, not to OS.
+ */
+
+#if NIMBLE_CFG_CONTROLLER
+
+void ble_npl_hw_set_isr(int irqn, uint32_t addr);
+
+#endif
+
+uint32_t ble_npl_hw_enter_critical(void);
+
+void ble_npl_hw_exit_critical(uint32_t ctx);
+
+bool ble_npl_hw_is_in_critical(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NIMBLE_NPL_H_ */
diff --git a/lib/bt/porting/nimble/include/nimble/nimble_opt.h b/lib/bt/porting/nimble/include/nimble/nimble_opt.h
new file mode 100644
index 00000000..f0e988b2
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/nimble_opt.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_NIMBLE_OPT_
+#define H_NIMBLE_OPT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Include automatically-generated settings. */
+#include "nimble/nimble_opt_auto.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h b/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h
new file mode 100644
index 00000000..daf21533
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h
@@ -0,0 +1,128 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_NIMBLE_OPT_AUTO_
+#define H_NIMBLE_OPT_AUTO_
+
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***
+ * Automatic options.
+ *
+ * These settings are generated automatically from the user-specified syscfg
+ * settings.
+ */
+
+#undef NIMBLE_BLE_ADVERTISE
+#define NIMBLE_BLE_ADVERTISE \
+ (MYNEWT_VAL(BLE_ROLE_BROADCASTER) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
+
+#undef NIMBLE_BLE_SCAN
+#define NIMBLE_BLE_SCAN \
+ (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER))
+
+#undef NIMBLE_BLE_CONNECT
+#define NIMBLE_BLE_CONNECT \
+ (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
+
+
+/** Supported client ATT commands. */
+
+#undef NIMBLE_BLE_ATT_CLT_FIND_INFO
+#define NIMBLE_BLE_ATT_CLT_FIND_INFO \
+ (MYNEWT_VAL(BLE_GATT_DISC_ALL_DSCS))
+
+#undef NIMBLE_BLE_ATT_CLT_FIND_TYPE
+#define NIMBLE_BLE_ATT_CLT_FIND_TYPE \
+ (MYNEWT_VAL(BLE_GATT_DISC_SVC_UUID))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_TYPE
+#define NIMBLE_BLE_ATT_CLT_READ_TYPE \
+ (MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS) || \
+ MYNEWT_VAL(BLE_GATT_DISC_ALL_CHRS) || \
+ MYNEWT_VAL(BLE_GATT_DISC_CHRS_UUID) || \
+ MYNEWT_VAL(BLE_GATT_READ_UUID))
+
+#undef NIMBLE_BLE_ATT_CLT_READ
+#define NIMBLE_BLE_ATT_CLT_READ \
+ (MYNEWT_VAL(BLE_GATT_READ) || \
+ MYNEWT_VAL(BLE_GATT_READ_LONG) || \
+ MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_BLOB
+#define NIMBLE_BLE_ATT_CLT_READ_BLOB \
+ (MYNEWT_VAL(BLE_GATT_READ_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_MULT
+#define NIMBLE_BLE_ATT_CLT_READ_MULT \
+ (MYNEWT_VAL(BLE_GATT_READ_MULT))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE
+#define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE \
+ (MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS))
+
+#undef NIMBLE_BLE_ATT_CLT_WRITE
+#define NIMBLE_BLE_ATT_CLT_WRITE \
+ (MYNEWT_VAL(BLE_GATT_WRITE))
+
+#undef NIMBLE_BLE_ATT_CLT_SIGNED_WRITE
+#define NIMBLE_BLE_ATT_CLT_SIGNED_WRITE \
+ (MYNEWT_VAL(BLE_GATT_SIGNED_WRITE))
+
+#undef NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP
+#define NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP \
+ (MYNEWT_VAL(BLE_GATT_WRITE_NO_RSP))
+
+#undef NIMBLE_BLE_ATT_CLT_PREP_WRITE
+#define NIMBLE_BLE_ATT_CLT_PREP_WRITE \
+ (MYNEWT_VAL(BLE_GATT_WRITE_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_EXEC_WRITE
+#define NIMBLE_BLE_ATT_CLT_EXEC_WRITE \
+ (MYNEWT_VAL(BLE_GATT_WRITE_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_NOTIFY
+#define NIMBLE_BLE_ATT_CLT_NOTIFY \
+ (MYNEWT_VAL(BLE_GATT_NOTIFY))
+
+#undef NIMBLE_BLE_ATT_CLT_INDICATE
+#define NIMBLE_BLE_ATT_CLT_INDICATE \
+ (MYNEWT_VAL(BLE_GATT_INDICATE))
+
+/** Security manager settings. */
+
+#undef NIMBLE_BLE_SM
+#define NIMBLE_BLE_SM (MYNEWT_VAL(BLE_SM_LEGACY) || MYNEWT_VAL(BLE_SM_SC))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/bt/porting/nimble/include/nimble/nimble_port.h b/lib/bt/porting/nimble/include/nimble/nimble_port.h
new file mode 100644
index 00000000..f4a98543
--- /dev/null
+++ b/lib/bt/porting/nimble/include/nimble/nimble_port.h
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _NIMBLE_PORT_H
+#define _NIMBLE_PORT_H
+
+#include "esp_err.h"
+#include "nimble/nimble_npl.h"
+
+#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
+
+#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
+
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @brief nimble_port_init - Initialize controller and NimBLE host stack
+*
+* @return esp_err_t - ESP_OK ( if success)
+* Error code in case of failure
+*/
+esp_err_t nimble_port_init(void);
+
+/**
+* @brief nimble_port_deinit - Deinitialize controller and NimBLE host stack
+*
+* @return esp_err_t - ESP_OK ( if success)
+* Error code in case of failure
+*/
+esp_err_t nimble_port_deinit(void);
+
+void nimble_port_run(void);
+int nimble_port_stop(void);
+
+/**
+ * @brief esp_nimble_init - Initialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_init(void);
+
+/**
+ * @brief esp_nimble_deinit - Deinitialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_deinit(void);
+
+struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NIMBLE_PORT_H */
diff --git a/lib/bt/porting/nimble/include/os/endian.h b/lib/bt/porting/nimble/include/os/endian.h
new file mode 100644
index 00000000..2e06a8b5
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/endian.h
@@ -0,0 +1,296 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_ENDIAN_
+#define H_ENDIAN_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal helpers */
+#ifndef os_bswap_64
+#define os_bswap_64(x) ((uint64_t) \
+ ((((x) & 0xff00000000000000ull) >> 56) | \
+ (((x) & 0x00ff000000000000ull) >> 40) | \
+ (((x) & 0x0000ff0000000000ull) >> 24) | \
+ (((x) & 0x000000ff00000000ull) >> 8) | \
+ (((x) & 0x00000000ff000000ull) << 8) | \
+ (((x) & 0x0000000000ff0000ull) << 24) | \
+ (((x) & 0x000000000000ff00ull) << 40) | \
+ (((x) & 0x00000000000000ffull) << 56)))
+#endif
+
+#ifndef os_bswap_32
+#define os_bswap_32(x) ((uint32_t) \
+ ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x000000ff) << 24)))
+#endif
+
+#ifndef os_bswap_16
+#define os_bswap_16(x) ((uint16_t) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8)))
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+
+#ifndef ntohll
+#define ntohll(x) ((uint64_t)(x))
+#endif
+
+#ifndef htonll
+#define htonll(x) ((uint64_t)(x))
+#endif
+
+#ifndef ntohl
+#define ntohl(x) ((uint32_t)(x))
+#endif
+
+#ifndef htonl
+#define htonl(x) ((uint32_t)(x))
+#endif
+
+#ifndef ntohs
+#define ntohs(x) ((uint16_t)(x))
+#endif
+
+#ifndef htons
+#define htons(x) ((uint16_t)(x))
+#endif
+
+#ifndef htobe16
+#define htobe16(x) ((uint16_t)(x))
+#endif
+
+#ifndef htole16
+#define htole16(x) os_bswap_16 (x)
+#endif
+
+#ifndef be16toh
+#define be16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef le16toh
+#define le16toh(x) os_bswap_16 (x)
+#endif
+
+#ifndef htobe32
+#define htobe32(x) ((uint32_t)(x))
+#endif
+
+#ifndef htole32
+#define htole32(x) os_bswap_32 (x)
+#endif
+
+#ifndef be32toh
+#define be32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef le32toh
+#define le32toh(x) os_bswap_32 (x)
+#endif
+
+#ifndef htobe64
+#define htobe64(x) ((uint64_t)(x))
+#endif
+
+#ifndef htole64
+#define htole64(x) os_bswap_64 (x)
+#endif
+
+#ifndef be64toh
+#define be64toh(x) ((uint64_t)(x))
+#endif
+
+#ifndef le64toh
+#define le64toh(x) os_bswap_64 (x)
+#endif
+
+#else
+
+#ifndef ntohll
+#define ntohll(x) os_bswap_64(x)
+#endif
+
+#ifndef htonll
+#define htonll ntohll
+#endif
+
+/* These are not used in NimBLE and ESP-IDF uses them from LwIP */
+#if 0
+#ifndef ntohl
+#define ntohl(x) os_bswap_32(x)
+#endif
+
+#ifndef htonl
+#define htonl ntohl
+#endif
+
+#ifndef htons
+#define htons(x) os_bswap_16(x)
+#endif
+
+#ifndef ntohs
+#define ntohs htons
+#endif
+#endif
+
+#ifndef htobe16
+#define htobe16(x) os_bswap_16(x)
+#endif
+
+#ifndef htole16
+#define htole16(x) ((uint16_t)(x))
+#endif
+
+#ifndef be16toh
+#define be16toh(x) os_bswap_16(x)
+#endif
+
+#ifndef le16toh
+#define le16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef htobe32
+#define htobe32(x) os_bswap_32(x)
+#endif
+
+#ifndef htole32
+#define htole32(x) ((uint32_t)(x))
+#endif
+
+#ifndef be32toh
+#define be32toh(x) os_bswap_32(x)
+#endif
+
+#ifndef le32toh
+#define le32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef htobe64
+#define htobe64(x) os_bswap_64(x)
+#endif
+
+#ifndef htole64
+#define htole64(x) ((uint64_t)(x))
+#endif
+
+#ifndef be64toh
+#define be64toh(x) os_bswap_64(x)
+#endif
+
+#ifndef le64toh
+#define le64toh(x) ((uint64_t)(x))
+#endif
+
+#endif
+
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+void r_put_le16(void *buf, uint16_t x);
+#define put_le16 r_put_le16
+
+void r_put_le24(void *buf, uint32_t x);
+#define put_le24 r_put_le24
+
+void r_put_le32(void *buf, uint32_t x);
+#define put_le32 r_put_le32
+
+void r_put_le64(void *buf, uint64_t x);
+#define put_le64 r_put_le64
+
+uint16_t r_get_le16(const void *buf);
+#define get_le16 r_get_le16
+
+uint32_t r_get_le24(const void *buf);
+#define get_le24 r_get_le24
+
+uint32_t r_get_le32(const void *buf);
+#define get_le32 r_get_le32
+
+uint64_t r_get_le64(const void *buf);
+#define get_le64 r_get_le64
+
+void r_put_be16(void *buf, uint16_t x);
+#define put_be16 r_put_be16
+
+void r_put_be24(void *buf, uint32_t x);
+#define put_be24 r_put_be24
+
+void r_put_be32(void *buf, uint32_t x);
+#define put_be32 r_put_be32
+
+void r_put_be64(void *buf, uint64_t x);
+#define put_be64 r_put_be64
+
+uint16_t r_get_be16(const void *buf);
+#define get_be16 r_get_be16
+
+uint32_t r_get_be24(const void *buf);
+#define get_be24 r_get_be24
+
+uint32_t r_get_be32(const void *buf);
+#define get_be32 r_get_be32
+
+uint64_t r_get_be64(const void *buf);
+#define get_be64 r_get_be64
+
+void r_swap_in_place(void *buf, int len);
+#define swap_in_place r_swap_in_place
+
+void r_swap_buf(uint8_t *dst, const uint8_t *src, int len);
+#define swap_buf r_swap_buf
+
+
+#else
+void put_le16(void *buf, uint16_t x);
+void put_le24(void *buf, uint32_t x);
+void put_le32(void *buf, uint32_t x);
+void put_le64(void *buf, uint64_t x);
+uint16_t get_le16(const void *buf);
+uint32_t get_le24(const void *buf);
+uint32_t get_le32(const void *buf);
+uint64_t get_le64(const void *buf);
+void put_be16(void *buf, uint16_t x);
+void put_be24(void *buf, uint32_t x);
+void put_be32(void *buf, uint32_t x);
+void put_be64(void *buf, uint64_t x);
+uint16_t get_be16(const void *buf);
+uint32_t get_be24(const void *buf);
+uint32_t get_be32(const void *buf);
+uint64_t get_be64(const void *buf);
+void swap_in_place(void *buf, int len);
+void swap_buf(uint8_t *dst, const uint8_t *src, int len);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/bt/porting/nimble/include/os/os.h b/lib/bt/porting/nimble/include/os/os.h
new file mode 100644
index 00000000..56fdf52d
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/os.h
@@ -0,0 +1,66 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_H
+#define _OS_H
+
+#include <assert.h>
+#include "esp_assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined __cplusplus && !defined static_assert
+#define static_assert _Static_assert
+#endif
+
+#include "nimble/nimble_npl.h"
+
+#define OS_ALIGN(__n, __a) ( \
+ (((__n) & ((__a) - 1)) == 0) ? \
+ (__n) : \
+ ((__n) + ((__a) - ((__n) & ((__a) - 1)))) \
+ )
+#define OS_ALIGNMENT (BLE_NPL_OS_ALIGNMENT)
+
+typedef uint32_t os_sr_t;
+#define OS_ENTER_CRITICAL(_sr) (_sr = ble_npl_hw_enter_critical())
+#define OS_EXIT_CRITICAL(_sr) (ble_npl_hw_exit_critical(_sr))
+#define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical())
+
+/* Mynewt components (not abstracted in NPL) */
+#include "os/endian.h"
+#include "os/queue.h"
+#include "os/os_error.h"
+#include "os/os_mbuf.h"
+#include "os/os_mempool.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_H */
diff --git a/lib/bt/porting/nimble/include/os/os_error.h b/lib/bt/porting/nimble/include/os/os_error.h
new file mode 100644
index 00000000..2e736e39
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/os_error.h
@@ -0,0 +1,69 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_ERROR_
+#define H_OS_ERROR_
+
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* OS error enumerations */
+enum os_error {
+ OS_OK = 0,
+ OS_ENOMEM = 1,
+ OS_EINVAL = 2,
+ OS_INVALID_PARM = 3,
+ OS_MEM_NOT_ALIGNED = 4,
+ OS_BAD_MUTEX = 5,
+ OS_TIMEOUT = 6,
+ OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */
+ OS_ERR_PRIV = 8, /* Privileged access error */
+ OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */
+ OS_ENOENT = 10, /* No such thing */
+ OS_EBUSY = 11, /* Resource busy */
+ OS_ERROR = 12, /* Generic Error */
+};
+
+typedef enum os_error os_error_t;
+
+/**
+ * @brief Converts an OS error code (`OS_[...]`) to an equivalent system error
+ * code (`SYS_E[...]`).
+ *
+ * @param os_error The OS error code to convert.
+ *
+ * @return The equivalent system error code.
+ */
+int os_error_to_sys(os_error_t os_error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/bt/porting/nimble/include/os/os_mbuf.h b/lib/bt/porting/nimble/include/os/os_mbuf.h
new file mode 100644
index 00000000..e6fd6b90
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/os_mbuf.h
@@ -0,0 +1,1145 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ * @defgroup OSMbuf Chained Memory Buffers
+ * @{
+ */
+
+
+#ifndef _OS_MBUF_H
+#define _OS_MBUF_H
+
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A mbuf pool from which to allocate mbufs. This contains a pointer to the os
+ * mempool to allocate mbufs out of, the total number of elements in the pool,
+ * and the amount of "user" data in a non-packet header mbuf. The total pool
+ * size, in bytes, should be:
+ * os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
+ */
+struct os_mbuf_pool {
+ /**
+ * Total length of the databuf in each mbuf. This is the size of the
+ * mempool block, minus the mbuf header
+ */
+ uint16_t omp_databuf_len;
+ /**
+ * The memory pool which to allocate mbufs out of
+ */
+ struct os_mempool *omp_pool;
+
+ STAILQ_ENTRY(os_mbuf_pool) omp_next;
+};
+
+
+/**
+ * A packet header structure that preceeds the mbuf packet headers.
+ */
+struct os_mbuf_pkthdr {
+ /**
+ * Overall length of the packet.
+ */
+ uint16_t omp_len;
+ /**
+ * Flags
+ */
+ uint16_t omp_flags;
+
+ STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
+};
+
+/**
+ * Chained memory buffer.
+ */
+struct os_mbuf {
+ /**
+ * Current pointer to data in the structure
+ */
+ uint8_t *om_data;
+ /**
+ * Flags associated with this buffer, see OS_MBUF_F_* defintions
+ */
+ uint8_t om_flags;
+ /**
+ * Length of packet header
+ */
+ uint8_t om_pkthdr_len;
+ /**
+ * Length of data in this buffer
+ */
+ uint16_t om_len;
+
+ /**
+ * The mbuf pool this mbuf was allocated out of
+ */
+ struct os_mbuf_pool *om_omp;
+
+ SLIST_ENTRY(os_mbuf) om_next;
+
+ /**
+ * Pointer to the beginning of the data, after this buffer
+ */
+ uint8_t om_databuf[0];
+};
+
+/**
+ * Structure representing a queue of mbufs.
+ */
+struct os_mqueue {
+ STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
+ /** Event to post when new buffers are available on the queue. */
+ struct ble_npl_event mq_ev;
+};
+
+/*
+ * Given a flag number, provide the mask for it
+ *
+ * @param __n The number of the flag in the mask
+ */
+#define OS_MBUF_F_MASK(__n) (1 << (__n))
+
+/*
+ * Checks whether a given mbuf is a packet header mbuf
+ *
+ * @param __om The mbuf to check
+ */
+#define OS_MBUF_IS_PKTHDR(__om) \
+ ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
+
+/** Get a packet header pointer given an mbuf pointer */
+#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \
+ (void *)((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
+
+/** Given a mbuf packet header pointer, return a pointer to the mbuf */
+#define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \
+ (struct os_mbuf *)(void *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
+
+/**
+ * Gets the length of an entire mbuf chain. The specified mbuf must have a
+ * packet header.
+ */
+#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
+
+/**
+ * Access the data of a mbuf, and cast it to type
+ *
+ * @param __om The mbuf to access, and cast
+ * @param __type The type to cast it to
+ */
+#define OS_MBUF_DATA(__om, __type) \
+ (__type) ((__om)->om_data)
+
+/**
+ * Access the "user header" in the head of an mbuf chain.
+ *
+ * @param om Pointer to the head of an mbuf chain.
+ */
+#define OS_MBUF_USRHDR(om) \
+ (void *)((uint8_t *)om + sizeof (struct os_mbuf) + \
+ sizeof (struct os_mbuf_pkthdr))
+
+/**
+ * Retrieves the length of the user header in an mbuf.
+ *
+ * @param om Pointer to the mbuf to query.
+ */
+#define OS_MBUF_USRHDR_LEN(om) \
+ ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
+
+
+/** @cond INTERNAL_HIDDEN */
+
+/*
+ * Called by OS_MBUF_LEADINGSPACE() macro
+ */
+static inline uint16_t
+_os_mbuf_leadingspace(struct os_mbuf *om)
+{
+ uint16_t startoff;
+ uint16_t leadingspace;
+
+ startoff = 0;
+ if (OS_MBUF_IS_PKTHDR(om)) {
+ startoff = om->om_pkthdr_len;
+ }
+
+ leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
+ ((uint8_t *) &om->om_databuf[0] + startoff));
+
+ return (leadingspace);
+}
+
+/** @endcond */
+
+/**
+ * Returns the leading space (space at the beginning) of the mbuf.
+ * Works on both packet header, and regular mbufs, as it accounts
+ * for the additional space allocated to the packet header.
+ *
+ * @param __omp Is the mbuf pool (which contains packet header length.)
+ * @param __om Is the mbuf in that pool to get the leadingspace for
+ *
+ * @return Amount of leading space available in the mbuf
+ */
+#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
+
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Called by OS_MBUF_TRAILINGSPACE() macro. */
+static inline uint16_t
+_os_mbuf_trailingspace(struct os_mbuf *om)
+{
+ struct os_mbuf_pool *omp;
+
+ omp = om->om_omp;
+
+ return (&om->om_databuf[0] + omp->omp_databuf_len) -
+ (om->om_data + om->om_len);
+}
+
+/** @endcond */
+
+/**
+ * Returns the trailing space (space at the end) of the mbuf.
+ * Works on both packet header and regular mbufs.
+ *
+ * @param __omp The mbuf pool for this mbuf
+ * @param __om Is the mbuf in that pool to get trailing space for
+ *
+ * @return The amount of trailing space available in the mbuf
+ */
+#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
+
+
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+/**
+ * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue. Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq The mqueue to initialize
+ * @param ev_cb The callback to associate with the mqeueue
+ * event. Typically, this callback pulls each
+ * packet off the mqueue and processes them.
+ * @param arg The argument to associate with the mqueue event.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
+#define os_mqueue_init r_os_mqueue_init
+
+
+/**
+ * Remove and return a single mbuf from the mbuf queue. Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *r_os_mqueue_get(struct os_mqueue *);
+#define os_mqueue_get r_os_mqueue_get
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq The mbuf queue to append the mbuf to.
+ * @param evq The event queue to post an event to.
+ * @param m The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
+#define os_mqueue_put r_os_mqueue_put
+
+
+/**
+ * MSYS is a system level mbuf registry. Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int r_os_msys_register(struct os_mbuf_pool *);
+#define os_msys_register r_os_msys_register
+
+
+/**
+ * Allocate a mbuf from msys. Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace);
+#define os_msys_get r_os_msys_get
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void r_os_msys_reset(void);
+#define os_msys_reset r_os_msys_reset
+
+
+/**
+ * Allocate a packet header structure from the MSYS pool. See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+#define os_msys_get_pkthdr r_os_msys_get_pkthdr
+/**
+ * Count the number of blocks in all the mbuf pools that are allocated.
+ *
+ * @return total number of blocks allocated in Msys
+ */
+int r_os_msys_count(void);
+#define os_msys_count r_os_msys_count
+
+
+/**
+ * Return the number of free blocks in Msys
+ *
+ * @return Number of free blocks available in Msys
+ */
+int r_os_msys_num_free(void);
+#define os_msys_num_free r_os_msys_num_free
+
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp The mbuf pool to initialize
+ * @param mp The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+ uint16_t, uint16_t);
+#define os_mbuf_pool_init r_os_mbuf_pool_init
+/**
+ * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ * section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+#define os_mbuf_get r_os_mbuf_get
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+ uint8_t pkthdr_len);
+#define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr
+/**
+ * Duplicate a chain of mbufs. Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m);
+#define os_mbuf_dup r_os_mbuf_dup
+/**
+ * Locates the specified absolute offset within an mbuf chain. The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om The start of the mbuf chain to seek within.
+ * @param off The absolute address to find.
+ * @param out_off On success, this points to the relative offset
+ * within the returned mbuf.
+ *
+ * @return The mbuf containing the specified offset on
+ * success.
+ * NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off,
+ uint16_t *out_off);
+#define os_mbuf_off r_os_mbuf_off
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return 0 on success;
+ * -1 if the mbuf does not contain enough data.
+ */
+int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+#define os_mbuf_copydata r_os_mbuf_copydata
+
+
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain. If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om The mbuf to measure.
+ *
+ * @return The length, in bytes, of the provided mbuf
+ * chain.
+ */
+uint16_t r_os_mbuf_len(const struct os_mbuf *om);
+#define os_mbuf_len r_os_mbuf_len
+
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+#define os_mbuf_append r_os_mbuf_append
+
+
+/**
+ * Reads data from one mbuf and appends it to another. On error, the specified
+ * data range may be partially appended. Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst The mbuf to append to.
+ * @param src The mbuf to copy data from.
+ * @param src_off The absolute offset within the source mbuf
+ * chain to read from.
+ * @param len The number of bytes to append.
+ *
+ * @return 0 on success;
+ * OS_EINVAL if the specified range extends beyond
+ * the end of the source mbuf chain.
+ */
+int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+ uint16_t src_off, uint16_t len);
+#define os_mbuf_appendfrom r_os_mbuf_appendfrom
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int r_os_mbuf_free(struct os_mbuf *mb);
+#define os_mbuf_free r_os_mbuf_free
+
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int r_os_mbuf_free_chain(struct os_mbuf *om);
+#define os_mbuf_free_chain r_os_mbuf_free_chain
+
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf. If positive, trims
+ * from the head of the mbuf, if negative, trims from the
+ * tail of the mbuf.
+ */
+void r_os_mbuf_adj(struct os_mbuf *mp, int req_len);
+#define os_mbuf_adj r_os_mbuf_adj
+
+
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om The start of the mbuf chain to compare.
+ * @param off The offset within the mbuf chain to start the
+ * comparison.
+ * @param data The flat buffer to compare.
+ * @param len The length of the flat buffer.
+ *
+ * @return 0 if both memory regions are identical;
+ * A memcmp return code if there is a mismatch;
+ * INT_MAX if the mbuf is too short.
+ */
+int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+#define os_mbuf_cmpf r_os_mbuf_cmpf
+
+
+/**
+ * Compares the contents of two mbuf chains. The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter. Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1 The first mbuf chain to compare.
+ * @param offset1 The absolute offset within om1 at which to
+ * start the comparison.
+ * @param om2 The second mbuf chain to compare.
+ * @param offset2 The absolute offset within om2 at which to
+ * start the comparison.
+ * @param len The number of bytes to compare.
+ *
+ * @return 0 if both mbuf segments are identical;
+ * A memcmp() return code if the segment contents
+ * differ;
+ * INT_MAX if a specified range extends beyond the
+ * end of its corresponding mbuf chain.
+ */
+int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+ const struct os_mbuf *om2, uint16_t offset2,
+ uint16_t len);
+#define os_mbuf_cmpm r_os_mbuf_cmpm
+/**
+ * Increases the length of an mbuf chain by adding data to the front. If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary. If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The head of the mbuf chain.
+ * @param len The number of bytes to prepend.
+ *
+ * @return The new head of the chain on success;
+ * NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len);
+#define os_mbuf_prepend r_os_mbuf_prepend
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous. If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om The mbuf chain to prepend to.
+ * @param len The number of bytes to prepend and pullup.
+ *
+ * @return The modified mbuf on success;
+ * NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset. If the mbuf is too small for the source data,
+ * it is extended as necessary. If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The mbuf chain to copy into.
+ * @param off The offset within the chain to copy to.
+ * @param src The source buffer to copy from.
+ * @param len The number of bytes to copy.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+#define os_mbuf_copyinto r_os_mbuf_copyinto
+
+
+/**
+ * Attaches a second mbuf chain onto the end of the first. If the first chain
+ * contains a packet header, the header's length is updated. If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first The mbuf chain being attached to.
+ * @param second The mbuf chain that gets attached.
+ */
+void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+#define os_mbuf_concat r_os_mbuf_concat
+
+
+
+/**
+ * Increases the length of an mbuf chain by the specified amount. If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain. It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om The head of the chain to extend.
+ * @param len The number of bytes to extend by.
+ *
+ * @return A pointer to the new data on success;
+ * NULL on failure.
+ */
+void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_extend r_os_mbuf_extend
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.) Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_pullup r_os_mbuf_pullup
+
+/**
+ * Removes and frees empty mbufs from the front of a chain. If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om The mbuf chain to trim.
+ *
+ * @return The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om);
+#define os_mbuf_trim_front r_os_mbuf_trim_front
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset. The contents of the gap are indeterminate. If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om The mbuf chain to widen.
+ * @param off The offset at which to insert the gap.
+ * @param len The size of the gap to insert.
+ *
+ * @return 0 on success; SYS_[...] error code on failure.
+ */
+int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+#define os_mbuf_widen r_os_mbuf_widen
+
+
+
+/**
+ * Creates a single chained mbuf from m1 and m2 utilizing all
+ * the available buffer space in all mbufs in the resulting
+ * chain. In other words, ensures there is no leading space in
+ * any mbuf in the resulting chain and trailing space only in
+ * the last mbuf in the chain. Mbufs from either chain may be
+ * freed if not needed. No mbufs are allocated. Note that mbufs
+ * from m2 are added to the end of m1. If m1 has a packet
+ * header, it is retained and length updated. If m2 has a packet
+ * header it is discarded. If m1 is NULL, NULL is returned and
+ * m2 is left untouched.
+ *
+ * @param m1 Pointer to first mbuf chain to pack
+ * @param m2 Pointer to second mbuf chain to pack
+ *
+ * @return struct os_mbuf* Pointer to resulting mbuf chain
+ */
+struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+#define os_mbuf_pack_chains r_os_mbuf_pack_chains
+
+#else
+/**
+ * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue. Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq The mqueue to initialize
+ * @param ev_cb The callback to associate with the mqeueue
+ * event. Typically, this callback pulls each
+ * packet off the mqueue and processes them.
+ * @param arg The argument to associate with the mqueue event.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
+
+/**
+ * Remove and return a single mbuf from the mbuf queue. Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *os_mqueue_get(struct os_mqueue *);
+
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq The mbuf queue to append the mbuf to.
+ * @param evq The event queue to post an event to.
+ * @param m The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
+
+/**
+ * MSYS is a system level mbuf registry. Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int os_msys_register(struct os_mbuf_pool *);
+
+/**
+ * Allocate a mbuf from msys. Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
+
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void os_msys_reset(void);
+
+/**
+ * Allocate a packet header structure from the MSYS pool. See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+
+/**
+ * Count the number of blocks in all the mbuf pools that are allocated.
+ *
+ * @return total number of blocks allocated in Msys
+ */
+int os_msys_count(void);
+
+/**
+ * Return the number of free blocks in Msys
+ *
+ * @return Number of free blocks available in Msys
+ */
+int os_msys_num_free(void);
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp The mbuf pool to initialize
+ * @param mp The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+ uint16_t, uint16_t);
+
+/**
+ * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ * section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+ uint8_t pkthdr_len);
+
+/**
+ * Duplicate a chain of mbufs. Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
+
+/**
+ * Locates the specified absolute offset within an mbuf chain. The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om The start of the mbuf chain to seek within.
+ * @param off The absolute address to find.
+ * @param out_off On success, this points to the relative offset
+ * within the returned mbuf.
+ *
+ * @return The mbuf containing the specified offset on
+ * success.
+ * NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
+ uint16_t *out_off);
+
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return 0 on success;
+ * -1 if the mbuf does not contain enough data.
+ */
+int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain. If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om The mbuf to measure.
+ *
+ * @return The length, in bytes, of the provided mbuf
+ * chain.
+ */
+uint16_t os_mbuf_len(const struct os_mbuf *om);
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+
+/**
+ * Reads data from one mbuf and appends it to another. On error, the specified
+ * data range may be partially appended. Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst The mbuf to append to.
+ * @param src The mbuf to copy data from.
+ * @param src_off The absolute offset within the source mbuf
+ * chain to read from.
+ * @param len The number of bytes to append.
+ *
+ * @return 0 on success;
+ * OS_EINVAL if the specified range extends beyond
+ * the end of the source mbuf chain.
+ */
+int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+ uint16_t src_off, uint16_t len);
+
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free(struct os_mbuf *mb);
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free_chain(struct os_mbuf *om);
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf. If positive, trims
+ * from the head of the mbuf, if negative, trims from the
+ * tail of the mbuf.
+ */
+void os_mbuf_adj(struct os_mbuf *mp, int req_len);
+
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om The start of the mbuf chain to compare.
+ * @param off The offset within the mbuf chain to start the
+ * comparison.
+ * @param data The flat buffer to compare.
+ * @param len The length of the flat buffer.
+ *
+ * @return 0 if both memory regions are identical;
+ * A memcmp return code if there is a mismatch;
+ * INT_MAX if the mbuf is too short.
+ */
+int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+
+/**
+ * Compares the contents of two mbuf chains. The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter. Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1 The first mbuf chain to compare.
+ * @param offset1 The absolute offset within om1 at which to
+ * start the comparison.
+ * @param om2 The second mbuf chain to compare.
+ * @param offset2 The absolute offset within om2 at which to
+ * start the comparison.
+ * @param len The number of bytes to compare.
+ *
+ * @return 0 if both mbuf segments are identical;
+ * A memcmp() return code if the segment contents
+ * differ;
+ * INT_MAX if a specified range extends beyond the
+ * end of its corresponding mbuf chain.
+ */
+int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+ const struct os_mbuf *om2, uint16_t offset2,
+ uint16_t len);
+
+/**
+ * Increases the length of an mbuf chain by adding data to the front. If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary. If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The head of the mbuf chain.
+ * @param len The number of bytes to prepend.
+ *
+ * @return The new head of the chain on success;
+ * NULL on failure.
+ */
+struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
+
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous. If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om The mbuf chain to prepend to.
+ * @param len The number of bytes to prepend and pullup.
+ *
+ * @return The modified mbuf on success;
+ * NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset. If the mbuf is too small for the source data,
+ * it is extended as necessary. If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The mbuf chain to copy into.
+ * @param off The offset within the chain to copy to.
+ * @param src The source buffer to copy from.
+ * @param len The number of bytes to copy.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+
+/**
+ * Attaches a second mbuf chain onto the end of the first. If the first chain
+ * contains a packet header, the header's length is updated. If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first The mbuf chain being attached to.
+ * @param second The mbuf chain that gets attached.
+ */
+void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+
+
+/**
+ * Increases the length of an mbuf chain by the specified amount. If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain. It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om The head of the chain to extend.
+ * @param len The number of bytes to extend by.
+ *
+ * @return A pointer to the new data on success;
+ * NULL on failure.
+ */
+void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.) Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+
+
+/**
+ * Removes and frees empty mbufs from the front of a chain. If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om The mbuf chain to trim.
+ *
+ * @return The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
+
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset. The contents of the gap are indeterminate. If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om The mbuf chain to widen.
+ * @param off The offset at which to insert the gap.
+ * @param len The size of the gap to insert.
+ *
+ * @return 0 on success; SYS_[...] error code on failure.
+ */
+int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+
+
+/**
+ * Creates a single chained mbuf from m1 and m2 utilizing all
+ * the available buffer space in all mbufs in the resulting
+ * chain. In other words, ensures there is no leading space in
+ * any mbuf in the resulting chain and trailing space only in
+ * the last mbuf in the chain. Mbufs from either chain may be
+ * freed if not needed. No mbufs are allocated. Note that mbufs
+ * from m2 are added to the end of m1. If m1 has a packet
+ * header, it is retained and length updated. If m2 has a packet
+ * header it is discarded. If m1 is NULL, NULL is returned and
+ * m2 is left untouched.
+ *
+ * @param m1 Pointer to first mbuf chain to pack
+ * @param m2 Pointer to second mbuf chain to pack
+ *
+ * @return struct os_mbuf* Pointer to resulting mbuf chain
+ */
+struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_MBUF_H */
+
+
+/**
+ * @} OSMbuf
+ * @} OSKernel
+ */
diff --git a/lib/bt/porting/nimble/include/os/os_mempool.h b/lib/bt/porting/nimble/include/os/os_mempool.h
new file mode 100644
index 00000000..3ef8e6d5
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/os_mempool.h
@@ -0,0 +1,407 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ * @defgroup OSMempool Memory Pools
+ * @{
+ */
+
+
+#ifndef _OS_MEMPOOL_H_
+#define _OS_MEMPOOL_H_
+
+#include <stdbool.h>
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A memory block structure. This simply contains a pointer to the free list
+ * chain and is only used when the block is on the free list. When the block
+ * has been removed from the free list the entire memory block is usable by the
+ * caller.
+ */
+struct os_memblock {
+ SLIST_ENTRY(os_memblock) mb_next;
+};
+
+/* XXX: Change this structure so that we keep the first address in the pool? */
+/* XXX: add memory debug structure and associated code */
+/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
+ SLIST_HEAD(,os_memblock) mp_head; */
+
+/**
+ * Memory pool
+ */
+struct os_mempool {
+ /** Size of the memory blocks, in bytes. */
+ uint32_t mp_block_size;
+ /** The number of memory blocks. */
+ uint16_t mp_num_blocks;
+ /** The number of free blocks left */
+ uint16_t mp_num_free;
+ /** The lowest number of free blocks seen */
+ uint16_t mp_min_free;
+ /** Bitmap of OS_MEMPOOL_F_[...] values. */
+ uint8_t mp_flags;
+ /** Address of memory buffer used by pool */
+ uint32_t mp_membuf_addr;
+ STAILQ_ENTRY(os_mempool) mp_list;
+ SLIST_HEAD(,os_memblock);
+ /** Name for memory block */
+ const char *name;
+};
+
+/**
+ * Indicates an extended mempool. Address can be safely cast to
+ * (struct os_mempool_ext *).
+ */
+#define OS_MEMPOOL_F_EXT 0x01
+
+struct os_mempool_ext;
+
+/**
+ * Block put callback function. If configured, this callback gets executed
+ * whenever a block is freed to the corresponding extended mempool. Note: The
+ * os_memblock_put() function calls this callback instead of freeing the block
+ * itself. Therefore, it is the callback's responsibility to free the block
+ * via a call to os_memblock_put_from_cb().
+ *
+ * @param ome The extended mempool that a block is being
+ * freed back to.
+ * @param data The block being freed.
+ * @param arg Optional argument configured along with the
+ * callback.
+ *
+ * @return Indicates whether the block was successfully
+ * freed. A non-zero value should only be
+ * returned if the block was not successfully
+ * released back to its pool.
+ */
+typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
+ void *arg);
+
+struct os_mempool_ext {
+ struct os_mempool mpe_mp;
+
+ /* Callback that is executed immediately when a block is freed. */
+ os_mempool_put_fn *mpe_put_cb;
+ void *mpe_put_arg;
+};
+
+#define OS_MEMPOOL_INFO_NAME_LEN (32)
+
+/**
+ * Information describing a memory pool, used to return OS information
+ * to the management layer.
+ */
+struct os_mempool_info {
+ /** Size of the memory blocks in the pool */
+ int omi_block_size;
+ /** Number of memory blocks in the pool */
+ int omi_num_blocks;
+ /** Number of free memory blocks */
+ int omi_num_free;
+ /** Minimum number of free memory blocks ever */
+ int omi_min_free;
+ /** Name of the memory pool */
+ char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
+};
+
+/**
+ * Get information about the next system memory pool.
+ *
+ * @param mempool The current memory pool, or NULL if starting iteration.
+ * @param info A pointer to the structure to return memory pool information
+ * into.
+ *
+ * @return The next memory pool in the list to get information about, or NULL
+ * when at the last memory pool.
+ */
+struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
+ struct os_mempool_info *);
+
+#if (OS_ALIGNMENT == 4)
+typedef uint32_t os_membuf_t;
+#elif (OS_ALIGNMENT == 8)
+typedef uint64_t os_membuf_t;
+#elif (OS_ALIGNMENT == 16)
+typedef __uint128_t os_membuf_t;
+#else
+#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`"
+#endif /* OS_ALIGNMENT == * */
+#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
+
+/** Calculates the number of bytes required to initialize a memory pool. */
+#define OS_MEMPOOL_BYTES(n,blksize) \
+ (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
+
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+/**
+ * Initialize a memory pool.
+ *
+ * @param mp Pointer to a pointer to a mempool
+ * @param blocks The number of blocks in the pool
+ * @param blocks_size The size of the block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_init r_os_mempool_init
+/**
+ * Initializes an extended memory pool. Extended attributes (e.g., callbacks)
+ * are not specified when this function is called; they are assigned manually
+ * after initialization.
+ *
+ * @param mpe The extended memory pool to initialize.
+ * @param blocks The number of blocks in the pool.
+ * @param block_size The size of each block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_ext_init r_os_mempool_ext_init
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp The mempool to unregister.
+ *
+ * @return 0 on success;
+ * OS_INVALID_PARM if the mempool is not
+ * registered.
+ */
+os_error_t r_os_mempool_unregister(struct os_mempool *mp);
+#define os_mempool_unregister r_os_mempool_unregister
+
+
+/**
+ * Clears a memory pool.
+ *
+ * @param mp The mempool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_clear(struct os_mempool *mp);
+#define os_mempool_clear r_os_mempool_clear
+
+
+/**
+ * Performs an integrity check of the specified mempool. This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp The mempool to check.
+ *
+ * @return true if the memory pool passes the integrity
+ * check;
+ * false if the memory pool is corrupt.
+ */
+bool r_os_mempool_is_sane(const struct os_mempool *mp);
+#define os_mempool_is_sane r_os_mempool_is_sane
+
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp The mempool to check as parent.
+ * @param block_addr The memory block to check as child.
+ *
+ * @return 0 if the block does not belong to the mempool;
+ * 1 if the block does belong to the mempool.
+ */
+int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+#define os_memblock_from r_os_memblock_from
+
+
+/**
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *r_os_memblock_get(struct os_mempool *mp);
+#define os_memblock_get r_os_memblock_get
+/**
+ * Puts the memory block back into the pool, ignoring the put callback, if any.
+ * This function should only be called from a put callback to free a block
+ * without causing infinite recursion.
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put_from_cb r_os_memblock_put_from_cb
+
+
+/**
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put r_os_memblock_put
+
+#else
+/**
+ * Initialize a memory pool.
+ *
+ * @param mp Pointer to a pointer to a mempool
+ * @param blocks The number of blocks in the pool
+ * @param blocks_size The size of the block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+
+/**
+ * Initializes an extended memory pool. Extended attributes (e.g., callbacks)
+ * are not specified when this function is called; they are assigned manually
+ * after initialization.
+ *
+ * @param mpe The extended memory pool to initialize.
+ * @param blocks The number of blocks in the pool.
+ * @param block_size The size of each block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp The mempool to unregister.
+ *
+ * @return 0 on success;
+ * OS_INVALID_PARM if the mempool is not
+ * registered.
+ */
+os_error_t os_mempool_unregister(struct os_mempool *mp);
+
+/**
+ * Clears a memory pool.
+ *
+ * @param mp The mempool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_clear(struct os_mempool *mp);
+
+/**
+ * Clears an extended memory pool.
+ *
+ * @param mpe The extended memory pool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe);
+
+/**
+ * Performs an integrity check of the specified mempool. This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp The mempool to check.
+ *
+ * @return true if the memory pool passes the integrity
+ * check;
+ * false if the memory pool is corrupt.
+ */
+bool os_mempool_is_sane(const struct os_mempool *mp);
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp The mempool to check as parent.
+ * @param block_addr The memory block to check as child.
+ *
+ * @return 0 if the block does not belong to the mempool;
+ * 1 if the block does belong to the mempool.
+ */
+int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+
+/**
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *os_memblock_get(struct os_mempool *mp);
+
+/**
+ * Puts the memory block back into the pool, ignoring the put callback, if any.
+ * This function should only be called from a put callback to free a block
+ * without causing infinite recursion.
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
+
+/**
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_MEMPOOL_H_ */
+
+
+/**
+ * @} OSMempool
+ * @} OSKernel
+ */
diff --git a/lib/bt/porting/nimble/include/os/queue.h b/lib/bt/porting/nimble/include/os/queue.h
new file mode 100644
index 00000000..c184a394
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/queue.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
+ */
+
+#ifndef _QUEUE_H_
+#define _QUEUE_H_
+
+/* The common BSD linked list queue macros are already defined here for ESP-IDF */
+#include <sys/queue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file defines circular queues. The other types of data structures:
+ * singly-linked lists, singly-linked tail queues, lists and tail queues
+ * are used from sys/queue.h
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ CIRCLEQ
+ * _HEAD + + + + +
+ * _HEAD_INITIALIZER + + + + +
+ * _ENTRY + + + + +
+ * _INIT + + + + +
+ * _EMPTY + + + + +
+ * _FIRST + + + + +
+ * _NEXT + + + + +
+ * _PREV - - - + +
+ * _LAST - - + + +
+ * _FOREACH + + + + +
+ * _FOREACH_REVERSE - - - + +
+ * _INSERT_HEAD + + + + +
+ * _INSERT_BEFORE - + - + +
+ * _INSERT_AFTER + + + + +
+ * _INSERT_TAIL - - + + +
+ * _REMOVE_HEAD + - + - -
+ * _REMOVE + + + + +
+ *
+ */
+
+/*
+ * Circular queue declarations.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&(head), (void *)&(head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = CIRCLEQ_FIRST((head)); \
+ (var) != (void *)(head) || ((var) = NULL); \
+ (var) = CIRCLEQ_NEXT((var), field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = CIRCLEQ_LAST((head)); \
+ (var) != (void *)(head) || ((var) = NULL); \
+ (var) = CIRCLEQ_PREV((var), field))
+
+#define CIRCLEQ_INIT(head) do { \
+ CIRCLEQ_FIRST((head)) = (void *)(head); \
+ CIRCLEQ_LAST((head)) = (void *)(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
+ CIRCLEQ_PREV((elm), field) = (listelm); \
+ if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
+ CIRCLEQ_LAST((head)) = (elm); \
+ else \
+ CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
+ CIRCLEQ_NEXT((listelm), field) = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ CIRCLEQ_NEXT((elm), field) = (listelm); \
+ CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
+ if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
+ CIRCLEQ_FIRST((head)) = (elm); \
+ else \
+ CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
+ CIRCLEQ_PREV((listelm), field) = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
+ CIRCLEQ_PREV((elm), field) = (void *)(head); \
+ if (CIRCLEQ_LAST((head)) == (void *)(head)) \
+ CIRCLEQ_LAST((head)) = (elm); \
+ else \
+ CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
+ CIRCLEQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ CIRCLEQ_NEXT((elm), field) = (void *)(head); \
+ CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
+ if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
+ CIRCLEQ_FIRST((head)) = (elm); \
+ else \
+ CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
+ CIRCLEQ_LAST((head)) = (elm); \
+} while (0)
+
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+
+#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
+
+#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
+ CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
+ else \
+ CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
+ CIRCLEQ_PREV((elm), field); \
+ if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
+ CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
+ else \
+ CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
+ CIRCLEQ_NEXT((elm), field); \
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/lib/bt/porting/nimble/include/os/util.h b/lib/bt/porting/nimble/include/os/util.h
new file mode 100644
index 00000000..2438373e
--- /dev/null
+++ b/lib/bt/porting/nimble/include/os/util.h
@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_UTIL_
+#define H_OS_UTIL_
+
+/* Helpers to pass integers as pointers and vice-versa */
+#define POINTER_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define UINT_TO_POINTER(u) ((void *) ((uintptr_t) (u)))
+#define POINTER_TO_INT(p) ((int) ((intptr_t) (p)))
+#define INT_TO_POINTER(u) ((void *) ((intptr_t) (u)))
+
+/* Helper to retrieve pointer to "parent" object in structure */
+#define CONTAINER_OF(ptr, type, field) \
+ ((type *)(((char *)(ptr)) - offsetof(type, field)))
+
+/* Helper to calculate number of elements in array */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) \
+ (sizeof(array) / sizeof((array)[0]))
+#endif
+#endif