diff --git a/apps/bttester/src/btp_gap.c b/apps/bttester/src/btp_gap.c index 8056eaf13..715ff4473 100644 --- a/apps/bttester/src/btp_gap.c +++ b/apps/bttester/src/btp_gap.c @@ -909,7 +909,7 @@ auth_passkey_display(uint16_t conn_handle, unsigned int passkey) return; } - rc = ble_hs_hci_rand(&pk.passkey, sizeof(pk.passkey)); + rc = ble_hs_hci_util_rand(&pk.passkey, sizeof(pk.passkey)); assert(rc == 0); /* Max value is 999999 */ pk.passkey %= 1000000; diff --git a/apps/bttester/src/btp_gatt.c b/apps/bttester/src/btp_gatt.c index 1c6320510..863d06acc 100644 --- a/apps/bttester/src/btp_gatt.c +++ b/apps/bttester/src/btp_gatt.c @@ -665,7 +665,7 @@ discover_destroy(void) } static void -read_destroy() +read_destroy(void) { gatt_buf_clear(); } diff --git a/nimble/host/include/host/ble_hs_hci.h b/nimble/host/include/host/ble_hs_hci.h index 237712080..5b28d9991 100644 --- a/nimble/host/include/host/ble_hs_hci.h +++ b/nimble/host/include/host/ble_hs_hci.h @@ -100,7 +100,7 @@ int ble_hs_hci_set_chan_class(const uint8_t *chan_map); * A BLE host core return code on unexpected * error. */ -int ble_hs_hci_rand(void *dst, int len); +int ble_hs_hci_util_rand(void *dst, int len); #if MYNEWT_VAL(BLE_HCI_VS) /** diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index c4d058849..66722fe99 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -438,7 +438,7 @@ int bt_le_adv_start(const struct ble_gap_adv_params *param, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len); -int bt_le_adv_stop(); +int bt_le_adv_stop(void); struct k_work_delayable { struct ble_npl_callout work; diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 26865058e..ec45e808b 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -18,6 +18,14 @@ #include "mesh/glue.h" #include "pb_gatt_srv.h" +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + #if MYNEWT_VAL(BLE_MESH_ADV_LEGACY) /* Convert from ms to 0.625ms units */ #define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index ee89ee876..5bce3d8d2 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -618,7 +618,7 @@ int bt_rand(void *buf, size_t len) { int rc; - rc = ble_hs_hci_rand(buf, len); + rc = ble_hs_hci_util_rand(buf, len); if (rc != 0) { return -1; } diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index e9e2d2b12..01b1eac36 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -300,6 +300,7 @@ static void prov_dh_key_gen(void) uint8_t remote_pk_le[BT_PUB_KEY_LEN]; remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; +#if !CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { if (uECC_valid_public_key(remote_pk, &curve_secp256r1)) { @@ -316,6 +317,7 @@ static void prov_dh_key_gen(void) prov_fail(PROV_ERR_UNEXP_ERR); return; } +#endif /* Copy remote key in little-endian for bt_dh_key_gen(). * X and Y halves are swapped independently. The bt_dh_key_gen() diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 91c87e50f..00af2f849 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -27,6 +27,14 @@ #include "proxy_msg.h" #include "pb_gatt_srv.h" +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + #if defined(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) #define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME #else diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index eca53fe16..c013ad9d1 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -800,6 +800,11 @@ ble_hs_init(void) ble_hs_evq_set(nimble_port_get_dflt_eventq()); #endif +#if SOC_ESP_NIMBLE_CONTROLLER + /* Configure the HCI transport to communicate with a host. */ + ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); +#endif + /* Enqueue the start event to the default event queue. Using the default * queue ensures the event won't run until the end of main(). This allows * the application to configure this package in the meantime. @@ -853,7 +858,9 @@ ble_hs_deinit(void) ble_monitor_deinit(); #endif +#if SOC_ESP_NIMBLE_CONTROLLER ble_hci_trans_cfg_hs(NULL, NULL, NULL, NULL); +#endif ble_npl_mutex_deinit(&ble_hs_mutex); diff --git a/nimble/host/src/ble_hs_flow.c b/nimble/host/src/ble_hs_flow.c index 8b8430dae..6cb70b861 100644 --- a/nimble/host/src/ble_hs_flow.c +++ b/nimble/host/src/ble_hs_flow.c @@ -40,7 +40,7 @@ static ble_npl_event_fn ble_hs_flow_event_cb; static struct ble_npl_event ble_hs_flow_ev; /* Connection handle associated with each mbuf in ACL pool */ -static uint16_t ble_hs_flow_mbuf_conn_handle[ MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT) ]; +static uint16_t ble_hs_flow_mbuf_conn_handle[ MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT) ]; static inline int ble_hs_flow_mbuf_index(const struct os_mbuf *om) @@ -135,7 +135,7 @@ ble_hs_flow_inc_completed_pkts(struct ble_hs_conn *conn) conn->bhc_completed_pkts++; ble_hs_flow_num_completed_pkts++; - if (ble_hs_flow_num_completed_pkts > MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)) { + if (ble_hs_flow_num_completed_pkts > MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT)) { ble_hs_sched_reset(BLE_HS_ECONTROLLER); return; } @@ -143,7 +143,7 @@ ble_hs_flow_inc_completed_pkts(struct ble_hs_conn *conn) /* If the number of free buffers is at or below the configured threshold, * send an immediate number-of-copmleted-packets event. */ - num_free = MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT) - + num_free = MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT) - ble_hs_flow_num_completed_pkts; if (num_free <= MYNEWT_VAL(BLE_HS_FLOW_CTRL_THRESH)) { ble_npl_eventq_put(ble_hs_evq_get(), &ble_hs_flow_ev); @@ -231,7 +231,7 @@ ble_hs_flow_startup(void) struct ble_hci_cb_ctlr_to_host_fc_cp enable_cmd; struct ble_hci_cb_host_buf_size_cp buf_size_cmd = { .acl_data_len = htole16(MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)), - .acl_num = htole16(MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)), + .acl_num = htole16(MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT)), }; int rc; @@ -265,7 +265,11 @@ ble_hs_flow_startup(void) /* Flow control successfully enabled. */ ble_hs_flow_num_completed_pkts = 0; +#if SOC_ESP_NIMBLE_CONTROLLER + ble_hci_trans_set_acl_free_cb(ble_hs_flow_acl_free, NULL); +#else ble_transport_register_put_acl_from_ll_cb(ble_hs_flow_acl_free); +#endif ble_npl_callout_init(&ble_hs_flow_timer, ble_hs_evq_get(), ble_hs_flow_event_cb, NULL); #endif diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c index f8a64e931..70e4bc44f 100644 --- a/nimble/host/src/ble_hs_hci.c +++ b/nimble/host/src/ble_hs_hci.c @@ -24,6 +24,8 @@ #include "mem/mem.h" #include "ble_hs_priv.h" +#include "nimble/transport.h" + #define BLE_HCI_CMD_TIMEOUT_MS 2000 static struct ble_npl_mutex ble_hs_hci_mutex; diff --git a/nimble/host/src/ble_hs_hci_cmd.c b/nimble/host/src/ble_hs_hci_cmd.c index 69fa16702..3ab9ea088 100644 --- a/nimble/host/src/ble_hs_hci_cmd.c +++ b/nimble/host/src/ble_hs_hci_cmd.c @@ -41,7 +41,7 @@ ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) { int rc; - rc = ble_transport_to_ll_cmd(cmd); + rc = ble_transport_to_ll_cmd((uint8_t *)cmd); switch (rc) { case 0: return 0; @@ -61,7 +61,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) uint8_t *buf; int rc; - cmd = ble_transport_alloc_cmd(); + cmd = (struct ble_hci_cmd *)ble_transport_alloc_cmd(); BLE_HS_DBG_ASSERT(cmd != NULL); buf = (uint8_t *)cmd; diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index c3147b383..c743edc60 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -1025,7 +1025,7 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) rc = entry->cb(ev->opcode, ev->data, ev->length); } - ble_transport_free(ev); + ble_transport_free((uint8_t *)ev); return rc; } diff --git a/nimble/host/src/ble_hs_hci_util.c b/nimble/host/src/ble_hs_hci_util.c index 780325269..95108a77a 100644 --- a/nimble/host/src/ble_hs_hci_util.c +++ b/nimble/host/src/ble_hs_hci_util.c @@ -66,7 +66,7 @@ ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr) } int -ble_hs_hci_rand(void *dst, int len) +ble_hs_hci_util_rand(void *dst, int len) { struct ble_hci_le_rand_rp rsp; uint8_t *u8ptr; diff --git a/nimble/host/src/ble_hs_id.c b/nimble/host/src/ble_hs_id.c index 63f750c9e..2af736f1a 100644 --- a/nimble/host/src/ble_hs_id.c +++ b/nimble/host/src/ble_hs_id.c @@ -54,7 +54,7 @@ ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr) out_addr->type = BLE_ADDR_RANDOM; - rc = ble_hs_hci_rand(out_addr->val, 6); + rc = ble_hs_hci_util_rand(out_addr->val, 6); if (rc != 0) { return rc; } diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index a4fcd7fd2..7c68e0f62 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -272,7 +272,7 @@ ble_sm_gen_pair_rand(uint8_t *pair_rand) } #endif - rc = ble_hs_hci_rand(pair_rand, 16); + rc = ble_hs_hci_util_rand(pair_rand, 16); if (rc != 0) { return rc; } @@ -293,7 +293,7 @@ ble_sm_gen_ediv(struct ble_sm_master_id *master_id) } #endif - rc = ble_hs_hci_rand(&master_id->ediv, sizeof master_id->ediv); + rc = ble_hs_hci_util_rand(&master_id->ediv, sizeof master_id->ediv); if (rc != 0) { return rc; } @@ -314,7 +314,7 @@ ble_sm_gen_master_id_rand(struct ble_sm_master_id *master_id) } #endif - rc = ble_hs_hci_rand(&master_id->rand_val, sizeof master_id->rand_val); + rc = ble_hs_hci_util_rand(&master_id->rand_val, sizeof master_id->rand_val); if (rc != 0) { return rc; } @@ -336,7 +336,7 @@ ble_sm_gen_ltk(struct ble_sm_proc *proc, uint8_t *ltk) } #endif - rc = ble_hs_hci_rand(ltk, proc->key_size); + rc = ble_hs_hci_util_rand(ltk, proc->key_size); if (rc != 0) { return rc; } @@ -361,7 +361,7 @@ ble_sm_gen_csrk(struct ble_sm_proc *proc, uint8_t *csrk) } #endif - rc = ble_hs_hci_rand(csrk, 16); + rc = ble_hs_hci_util_rand(csrk, 16); if (rc != 0) { return rc; } diff --git a/nimble/host/src/ble_sm_alg.c b/nimble/host/src/ble_sm_alg.c index abfa8e45b..4e9218dae 100644 --- a/nimble/host/src/ble_sm_alg.c +++ b/nimble/host/src/ble_sm_alg.c @@ -749,7 +749,7 @@ ble_sm_alg_rand(uint8_t *dst, unsigned int size) size -= num; } #else - if (ble_hs_hci_rand(dst, size)) { + if (ble_hs_hci_util_rand(dst, size)) { return 0; } #endif diff --git a/nimble/host/src/ble_sm_sc.c b/nimble/host/src/ble_sm_sc.c index ffcdc692e..50ad196a5 100644 --- a/nimble/host/src/ble_sm_sc.c +++ b/nimble/host/src/ble_sm_sc.c @@ -893,7 +893,7 @@ ble_sm_sc_oob_generate_data(struct ble_sm_sc_oob_data *oob_data) return rc; } - rc = ble_hs_hci_rand(oob_data->r, 16); + rc = ble_hs_hci_util_rand(oob_data->r, 16); if (rc) { return rc; } diff --git a/nimble/transport/include/nimble/transport.h b/nimble/transport/include/nimble/transport.h index fcb3297cf..16e99c84e 100644 --- a/nimble/transport/include/nimble/transport.h +++ b/nimble/transport/include/nimble/transport.h @@ -29,13 +29,309 @@ extern "C" { #if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc #include #endif +#include +#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 +#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 struct os_mbuf; /* Initialization */ void ble_transport_init(void); /* Allocators for supported data types */ +#if !SOC_ESP_NIMBLE_CONTROLLER void *ble_transport_alloc_cmd(void); void *ble_transport_alloc_evt(int discardable); struct os_mbuf *ble_transport_alloc_acl_from_hs(void); @@ -45,13 +341,20 @@ struct os_mbuf *ble_transport_alloc_iso_from_ll(void); /* Generic deallocator for cmd/evt buffers */ void ble_transport_free(void *buf); +#endif /* Register put callback on acl_from_ll mbufs (for ll-hs flow control) */ int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn *cb); -/* Send data to hs/ll side */ +#if CONFIG_BT_CONTROLLER_ENABLED +#define ble_transport_to_ll_acl ble_hci_trans_hs_acl_tx +#define ble_transport_to_ll_cmd ble_hci_trans_hs_cmd_tx +#else int ble_transport_to_ll_cmd(void *buf); int ble_transport_to_ll_acl(struct os_mbuf *om); +#endif + +/* Send data to hs/ll side */ int ble_transport_to_ll_iso(struct os_mbuf *om); int ble_transport_to_hs_evt(void *buf); int ble_transport_to_hs_acl(struct os_mbuf *om); diff --git a/nimble/transport/include/nimble/transport_impl.h b/nimble/transport/include/nimble/transport_impl.h index 8d95c8920..d59733788 100644 --- a/nimble/transport/include/nimble/transport_impl.h +++ b/nimble/transport/include/nimble/transport_impl.h @@ -24,6 +24,9 @@ extern "C" { #endif +#include "os/os_mempool.h" +#include "syscfg/syscfg.h" + /* Init functions to be implemented for transport acting as HS/LL side */ extern void ble_transport_ll_init(void); extern void ble_transport_hs_init(void); diff --git a/nimble/transport/src/transport.c b/nimble/transport/src/transport.c index c9b37a7e9..a6b150863 100644 --- a/nimble/transport/src/transport.c +++ b/nimble/transport/src/transport.c @@ -28,6 +28,10 @@ #if BLE_TRANSPORT_IPC #include #endif +#include "esp_nimble_mem.h" + +int os_msys_buf_alloc(void); +void os_msys_buf_free(void); #define OMP_FLAG_FROM_HS (0x01) #define OMP_FLAG_FROM_LL (0x02) @@ -70,23 +74,24 @@ BLE_MBUF_MEMBLOCK_OVERHEAD + \ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)) -static uint8_t pool_cmd_buf[ OS_MEMPOOL_BYTES(POOL_CMD_COUNT, POOL_CMD_SIZE) ]; +#if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED +static os_membuf_t *pool_cmd_buf; static struct os_mempool pool_cmd; -static uint8_t pool_evt_buf[ OS_MEMPOOL_BYTES(POOL_EVT_COUNT, POOL_EVT_SIZE) ]; +static os_membuf_t *pool_evt_buf; static struct os_mempool pool_evt; -static uint8_t pool_evt_lo_buf[ OS_MEMPOOL_BYTES(POOL_EVT_LO_COUNT, POOL_EVT_SIZE) ]; +static os_membuf_t *pool_evt_lo_buf; static struct os_mempool pool_evt_lo; #if POOL_ACL_COUNT > 0 -static uint8_t pool_acl_buf[ OS_MEMPOOL_BYTES(POOL_ACL_COUNT, POOL_ACL_SIZE) ]; +static os_membuf_t *pool_acl_buf; static struct os_mempool_ext pool_acl; static struct os_mbuf_pool mpool_acl; #endif #if POOL_ISO_COUNT > 0 -static uint8_t pool_iso_buf[ OS_MEMPOOL_BYTES(POOL_ISO_COUNT, POOL_ISO_SIZE) ]; +static os_membuf_t *pool_iso_buf; static struct os_mempool_ext pool_iso; static struct os_mbuf_pool mpool_iso; #endif @@ -275,29 +280,29 @@ ble_transport_ipc_free(void *buf) static os_error_t ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) { + os_error_t err; + err = 0; + +#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) struct os_mbuf *om; struct os_mbuf_pkthdr *pkthdr; - bool do_put; bool from_ll; - os_error_t err; +#endif +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) + if (transport_put_acl_from_ll_cb) { + err = transport_put_acl_from_ll_cb(mpe, data, arg); + } +#else + err = os_memblock_put_from_cb(&mpe->mpe_mp, data); +#endif + +#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) om = data; pkthdr = OS_MBUF_PKTHDR(om); - do_put = true; from_ll = (pkthdr->omp_flags & OMP_FLAG_FROM_MASK) == OMP_FLAG_FROM_LL; - err = 0; - if (from_ll && transport_put_acl_from_ll_cb) { - err = transport_put_acl_from_ll_cb(mpe, data, arg); - do_put = false; - } - - if (do_put) { - err = os_memblock_put_from_cb(&mpe->mpe_mp, data); - } - -#if BLE_TRANSPORT_IPC_ON_HS if (from_ll && !err) { hci_ipc_put(HCI_IPC_TYPE_ACL); } @@ -307,6 +312,68 @@ ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) } #endif +void ble_buf_free(void) +{ + os_msys_buf_free(); + + nimble_platform_mem_free(pool_evt_buf); + pool_evt_buf = NULL; + nimble_platform_mem_free(pool_evt_lo_buf); + pool_evt_lo_buf = NULL; + nimble_platform_mem_free(pool_cmd_buf); + pool_cmd_buf = NULL; +#if POOL_ACL_COUNT > 0 + nimble_platform_mem_free(pool_acl_buf); + pool_acl_buf = NULL; +#endif +#if POOL_ISO_COUNT > 0 + nimble_platform_mem_free(pool_iso_buf); + pool_iso_buf = NULL; +#endif +} + +esp_err_t ble_buf_alloc(void) +{ + if (os_msys_buf_alloc()) { + return ESP_ERR_NO_MEM; + } + + pool_evt_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT), + MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)))); + + pool_evt_lo_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT), + MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)))); + + pool_cmd_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_CMD_COUNT, POOL_CMD_SIZE))); + +#if POOL_ACL_COUNT > 0 + pool_acl_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_ACL_COUNT, + POOL_ACL_SIZE))); + if(!pool_acl_buf) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } +#endif +#if POOL_ISO_COUNT > 0 + pool_iso_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_ISO_COUNT, + POOL_ISO_SIZE)); + if(!pool_iso_buf) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } +#endif + if (!pool_evt_buf || !pool_evt_lo_buf || !pool_cmd_buf ) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + void ble_transport_init(void) { @@ -349,6 +416,22 @@ ble_transport_init(void) #endif } +void +ble_transport_deinit(void) +{ + int rc = 0; + rc = os_mempool_ext_clear(&pool_acl); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_clear(&pool_evt_lo); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_clear(&pool_evt); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_clear(&pool_cmd); + SYSINIT_PANIC_ASSERT(rc == 0); +} int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn (*cb)) { @@ -373,3 +456,5 @@ ble_transport_ipc_buf_evt_type_get(void *buf) return 0; } #endif +#endif + diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index 402a77782..1aeb000d3 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -39,7 +39,6 @@ #endif -#include "nimble/ble_hci_trans.h" #include "esp_intr_alloc.h" #include "freertos/FreeRTOS.h" @@ -105,9 +104,8 @@ esp_err_t esp_nimble_init(void) /* Initialize the global memory pool */ os_mempool_module_init(); os_msys_init(); - /* Initialize transport */ - ble_transport_init(); -#endif + +#endif /* Initialize the host */ ble_transport_hs_init(); diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index 4c3e68bd8..d3cd19587 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -45,8 +45,8 @@ static const char *TAG = "Timer"; #define OS_MEM_ALLOC (1) #if CONFIG_BT_NIMBLE_ENABLED -#define BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) -#define BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT) +#define BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) +#define BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT) #define BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) #define BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS) #else