diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-03-28 14:32:49 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-03-28 14:32:49 +1100 |
| commit | ee29c25b29eaa4fac4e897442634b69ecc8d8125 (patch) | |
| tree | 8c5f1a140463f20f104316fa3492984e191154e9 /lib/bt/porting/nimble/include | |
| parent | 239e6d89507a24c849385f4bfa93ac4ad58e5de5 (diff) | |
| download | tangara-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.h | 319 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/nimble/ble_hci_trans.h | 328 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/nimble/nimble_npl.h | 180 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/nimble/nimble_opt.h | 34 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h | 128 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/nimble/nimble_port.h | 78 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/endian.h | 296 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/os.h | 66 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/os_error.h | 69 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/os_mbuf.h | 1145 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/os_mempool.h | 407 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/queue.h | 218 | ||||
| -rw-r--r-- | lib/bt/porting/nimble/include/os/util.h | 45 |
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 |
