diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index dd9c3a7beac..25cd87e2bdb 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -31,6 +31,7 @@ if(CONFIG_BT_HCI_HOST) zephyr_library_sources( uuid.c addr.c + buf.c hci_core.c hci_common.c ) diff --git a/subsys/bluetooth/host/buf.c b/subsys/bluetooth/host/buf.c new file mode 100644 index 00000000000..a1e7addf96e --- /dev/null +++ b/subsys/bluetooth/host/buf.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2015 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "hci_core.h" +#include "conn_internal.h" +#include "audio/iso_internal.h" + +#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE) +#define LOG_MODULE_NAME bt_buf +#include "common/log.h" + +NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT, + BT_BUF_RX_SIZE, NULL); + +#if defined(CONFIG_BT_CONN) +#define NUM_COMLETE_EVENT_SIZE BT_BUF_SIZE(\ + sizeof(struct bt_hci_evt_hdr) + \ + sizeof(struct bt_hci_cp_host_num_completed_packets) + \ + CONFIG_BT_MAX_CONN * sizeof(struct bt_hci_handle_count)) +/* Dedicated pool for HCI_Number_of_Completed_Packets. This event is always + * consumed synchronously by bt_recv_prio() so a single buffer is enough. + * Having a dedicated pool for it ensures that exhaustion of the RX pool + * cannot block the delivery of this priority event. + */ +NET_BUF_POOL_FIXED_DEFINE(num_complete_pool, 1, NUM_COMLETE_EVENT_SIZE, NULL); +#endif /* CONFIG_BT_CONN */ + +#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) +#define DISCARDABLE_EVENT_SIZE BT_BUF_SIZE(CONFIG_BT_DISCARDABLE_BUF_SIZE) +NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_DISCARDABLE_BUF_COUNT, + DISCARDABLE_EVENT_SIZE, NULL); +#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ + +#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) +#define ACL_IN_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_RX_MTU) +NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BT_ACL_RX_COUNT, ACL_IN_SIZE, + sizeof(struct acl_data), bt_hci_host_num_completed_packets); +#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ + +struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) +{ + struct net_buf *buf; + + __ASSERT(type == BT_BUF_EVT || type == BT_BUF_ACL_IN || + type == BT_BUF_ISO_IN, "Invalid buffer type requested"); + + if (IS_ENABLED(CONFIG_BT_ISO) && type == BT_BUF_ISO_IN) { + return bt_iso_get_rx(timeout); + } + +#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) + if (type == BT_BUF_EVT) { + buf = net_buf_alloc(&hci_rx_pool, timeout); + } else { + buf = net_buf_alloc(&acl_in_pool, timeout); + } +#else + buf = net_buf_alloc(&hci_rx_pool, timeout); +#endif + + if (buf) { + net_buf_reserve(buf, BT_BUF_RESERVE); + bt_buf_set_type(buf, type); + } + + return buf; +} + +struct net_buf *bt_buf_get_cmd_complete(k_timeout_t timeout) +{ + struct net_buf *buf; + unsigned int key; + + key = irq_lock(); + buf = bt_dev.sent_cmd; + bt_dev.sent_cmd = NULL; + irq_unlock(key); + + BT_DBG("sent_cmd %p", buf); + + if (buf) { + bt_buf_set_type(buf, BT_BUF_EVT); + buf->len = 0U; + net_buf_reserve(buf, BT_BUF_RESERVE); + + return buf; + } + + return bt_buf_get_rx(BT_BUF_EVT, timeout); +} + +struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, + k_timeout_t timeout) +{ + switch (evt) { +#if defined(CONFIG_BT_CONN) + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: + { + struct net_buf *buf; + + buf = net_buf_alloc(&num_complete_pool, timeout); + if (buf) { + net_buf_reserve(buf, BT_BUF_RESERVE); + bt_buf_set_type(buf, BT_BUF_EVT); + } + + return buf; + } +#endif /* CONFIG_BT_CONN */ + case BT_HCI_EVT_CMD_COMPLETE: + case BT_HCI_EVT_CMD_STATUS: + return bt_buf_get_cmd_complete(timeout); + default: +#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) + if (discardable) { + struct net_buf *buf; + + buf = net_buf_alloc(&discardable_pool, timeout); + if (buf) { + net_buf_reserve(buf, BT_BUF_RESERVE); + bt_buf_set_type(buf, BT_BUF_EVT); + } + + return buf; + } +#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ + + return bt_buf_get_rx(BT_BUF_EVT, timeout); + } +} diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 8256a1017f9..6a71f1cebf6 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -117,6 +117,17 @@ struct bt_conn_tx { uint32_t pending_no_cb; }; +struct acl_data { + /** BT_BUF_ACL_IN */ + uint8_t type; + + /* Index into the bt_conn storage array */ + uint8_t index; + + /** ACL connection handle */ + uint16_t handle; +}; + struct bt_conn { uint16_t handle; uint8_t type; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 1539ed3141c..98385288ab5 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -148,17 +148,6 @@ struct cmd_data { struct k_sem *sync; }; -struct acl_data { - /** BT_BUF_ACL_IN */ - uint8_t type; - - /* Index into the bt_conn storage array */ - uint8_t index; - - /** ACL connection handle */ - uint16_t handle; -}; - static struct cmd_data cmd_data[CONFIG_BT_HCI_CMD_COUNT]; #define cmd(buf) (&cmd_data[net_buf_id(buf)]) @@ -171,28 +160,6 @@ static struct cmd_data cmd_data[CONFIG_BT_HCI_CMD_COUNT]; NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_HCI_CMD_COUNT, CMD_BUF_SIZE, NULL); -NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT, - BT_BUF_RX_SIZE, NULL); - -#if defined(CONFIG_BT_CONN) -#define NUM_COMLETE_EVENT_SIZE BT_BUF_SIZE(\ - sizeof(struct bt_hci_evt_hdr) + \ - sizeof(struct bt_hci_cp_host_num_completed_packets) + \ - CONFIG_BT_MAX_CONN * sizeof(struct bt_hci_handle_count)) -/* Dedicated pool for HCI_Number_of_Completed_Packets. This event is always - * consumed synchronously by bt_recv_prio() so a single buffer is enough. - * Having a dedicated pool for it ensures that exhaustion of the RX pool - * cannot block the delivery of this priority event. - */ -NET_BUF_POOL_FIXED_DEFINE(num_complete_pool, 1, NUM_COMLETE_EVENT_SIZE, NULL); -#endif /* CONFIG_BT_CONN */ - -#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) -#define DISCARDABLE_EVENT_SIZE BT_BUF_SIZE(CONFIG_BT_DISCARDABLE_BUF_SIZE) -NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_DISCARDABLE_BUF_COUNT, - DISCARDABLE_EVENT_SIZE, NULL); -#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ - struct event_handler { uint8_t event; uint8_t min_len; @@ -234,7 +201,7 @@ static inline void handle_event(uint8_t event, struct net_buf *buf, } #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -static void report_completed_packet(struct net_buf *buf) +void bt_hci_host_num_completed_packets(struct net_buf *buf) { struct bt_hci_cp_host_num_completed_packets *cp; @@ -282,11 +249,7 @@ static void report_completed_packet(struct net_buf *buf) bt_hci_cmd_send(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, buf); } - -#define ACL_IN_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_RX_MTU) -NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BT_ACL_RX_COUNT, ACL_IN_SIZE, - sizeof(struct acl_data), report_completed_packet); -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif /* defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) */ struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) { @@ -9122,97 +9085,6 @@ int bt_le_set_chan_map(uint8_t chan_map[5]) buf, NULL); } -struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) -{ - struct net_buf *buf; - - __ASSERT(type == BT_BUF_EVT || type == BT_BUF_ACL_IN || - type == BT_BUF_ISO_IN, "Invalid buffer type requested"); - - if (IS_ENABLED(CONFIG_BT_ISO) && type == BT_BUF_ISO_IN) { - return bt_iso_get_rx(timeout); - } - -#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) - if (type == BT_BUF_EVT) { - buf = net_buf_alloc(&hci_rx_pool, timeout); - } else { - buf = net_buf_alloc(&acl_in_pool, timeout); - } -#else - buf = net_buf_alloc(&hci_rx_pool, timeout); -#endif - - if (buf) { - net_buf_reserve(buf, BT_BUF_RESERVE); - bt_buf_set_type(buf, type); - } - - return buf; -} - -struct net_buf *bt_buf_get_cmd_complete(k_timeout_t timeout) -{ - struct net_buf *buf; - unsigned int key; - - key = irq_lock(); - buf = bt_dev.sent_cmd; - bt_dev.sent_cmd = NULL; - irq_unlock(key); - - BT_DBG("sent_cmd %p", buf); - - if (buf) { - bt_buf_set_type(buf, BT_BUF_EVT); - buf->len = 0U; - net_buf_reserve(buf, BT_BUF_RESERVE); - - return buf; - } - - return bt_buf_get_rx(BT_BUF_EVT, timeout); -} - -struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout) -{ - switch (evt) { -#if defined(CONFIG_BT_CONN) - case BT_HCI_EVT_NUM_COMPLETED_PACKETS: - { - struct net_buf *buf; - - buf = net_buf_alloc(&num_complete_pool, timeout); - if (buf) { - net_buf_reserve(buf, BT_BUF_RESERVE); - bt_buf_set_type(buf, BT_BUF_EVT); - } - - return buf; - } -#endif /* CONFIG_BT_CONN */ - case BT_HCI_EVT_CMD_COMPLETE: - case BT_HCI_EVT_CMD_STATUS: - return bt_buf_get_cmd_complete(timeout); - default: -#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) - if (discardable) { - struct net_buf *buf; - - buf = net_buf_alloc(&discardable_pool, timeout); - if (buf) { - net_buf_reserve(buf, BT_BUF_RESERVE); - bt_buf_set_type(buf, BT_BUF_EVT); - } - - return buf; - } -#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ - - return bt_buf_get_rx(BT_BUF_EVT, timeout); - } -} - #if defined(CONFIG_BT_BREDR) static int br_start_inquiry(const struct bt_br_discovery_param *param) { diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index ea2b87e95f2..1d77af54a6a 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -340,6 +340,8 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param, void bt_le_adv_resume(void); bool bt_le_scan_random_addr_check(void); +void bt_hci_host_num_completed_packets(struct net_buf *buf); + /* HCI event handlers */ void hci_evt_pin_code_req(struct net_buf *buf); void hci_evt_link_key_notify(struct net_buf *buf);