Bluetooth: controller: Handle remote version as a prio event
The remote version information event needs to be processed by the prio_recv_thread() thread in order to unblock the Host RX thread (effectively hci_driver's recv_thread()) when it blocks waiting for a response to a remote version information. Add the same time gate the inclusion of the feature behind a new Kconfig option: CONFIG_BT_REMOTE_INFO. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
b37be1c0c5
commit
6c34983ed2
4 changed files with 94 additions and 44 deletions
|
@ -86,18 +86,6 @@ config BT_OBSERVER
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
config BT_PHY_UPDATE
|
|
||||||
bool "PHY Update"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Enable support for Bluetooth 5.0 PHY Update Procedure.
|
|
||||||
|
|
||||||
config BT_DATA_LEN_UPDATE
|
|
||||||
bool "Data Length Update"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Enable support for Bluetooth v4.2 LE Data Length Update procedure.
|
|
||||||
|
|
||||||
source "subsys/bluetooth/services/Kconfig"
|
source "subsys/bluetooth/services/Kconfig"
|
||||||
|
|
||||||
config BT_CONN
|
config BT_CONN
|
||||||
|
@ -126,6 +114,27 @@ config BT_HCI_ACL_FLOW_CONTROL
|
||||||
to the host. This is particularly useful when the host and
|
to the host. This is particularly useful when the host and
|
||||||
controller are on separate cores since it ensures that we do
|
controller are on separate cores since it ensures that we do
|
||||||
not run out of incoming ACL buffers.
|
not run out of incoming ACL buffers.
|
||||||
|
|
||||||
|
config BT_REMOTE_VERSION
|
||||||
|
bool "Enable fetching of remote version"
|
||||||
|
# Enable if building a Controller-only build
|
||||||
|
default y if BT_HCI_RAW
|
||||||
|
help
|
||||||
|
Enable this to get access to the remote version in the Controller and
|
||||||
|
in the Host through bt_conn_get_info(). The fields in question can
|
||||||
|
be then found in the bt_conn_info struct.
|
||||||
|
|
||||||
|
config BT_PHY_UPDATE
|
||||||
|
bool "PHY Update"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable support for Bluetooth 5.0 PHY Update Procedure.
|
||||||
|
|
||||||
|
config BT_DATA_LEN_UPDATE
|
||||||
|
bool "Data Length Update"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable support for Bluetooth v4.2 LE Data Length Update procedure.
|
||||||
endif # BT_CONN
|
endif # BT_CONN
|
||||||
|
|
||||||
# Workaround for not being able to have commas in macro arguments
|
# Workaround for not being able to have commas in macro arguments
|
||||||
|
|
|
@ -532,8 +532,10 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
|
||||||
rp->status = 0x00;
|
rp->status = 0x00;
|
||||||
(void)memset(&rp->commands[0], 0, sizeof(rp->commands));
|
(void)memset(&rp->commands[0], 0, sizeof(rp->commands));
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_REMOTE_VERSION)
|
||||||
/* Read Remote Version Info. */
|
/* Read Remote Version Info. */
|
||||||
rp->commands[2] |= BIT(7);
|
rp->commands[2] |= BIT(7);
|
||||||
|
#endif
|
||||||
/* Set Event Mask, and Reset. */
|
/* Set Event Mask, and Reset. */
|
||||||
rp->commands[5] |= BIT(6) | BIT(7);
|
rp->commands[5] |= BIT(6) | BIT(7);
|
||||||
/* Read TX Power Level. */
|
/* Read TX Power Level. */
|
||||||
|
@ -3211,27 +3213,6 @@ static void le_unknown_rsp(struct pdu_data *pdu_data, u16_t handle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remote_version_info(struct pdu_data *pdu_data, u16_t handle,
|
|
||||||
struct net_buf *buf)
|
|
||||||
{
|
|
||||||
struct pdu_data_llctrl_version_ind *ver_ind;
|
|
||||||
struct bt_hci_evt_remote_version_info *ep;
|
|
||||||
|
|
||||||
if (!(event_mask & BT_EVT_MASK_REMOTE_VERSION_INFO)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep));
|
|
||||||
ep = net_buf_add(buf, sizeof(*ep));
|
|
||||||
|
|
||||||
ver_ind = &pdu_data->llctrl.version_ind;
|
|
||||||
ep->status = 0x00;
|
|
||||||
ep->handle = sys_cpu_to_le16(handle);
|
|
||||||
ep->version = ver_ind->version_number;
|
|
||||||
ep->manufacturer = ver_ind->company_id;
|
|
||||||
ep->subversion = ver_ind->sub_version_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||||
static void le_conn_param_req(struct pdu_data *pdu_data, u16_t handle,
|
static void le_conn_param_req(struct pdu_data *pdu_data, u16_t handle,
|
||||||
struct net_buf *buf)
|
struct net_buf *buf)
|
||||||
|
@ -3299,10 +3280,6 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx,
|
||||||
le_remote_feat_complete(0x00, pdu_data, handle, buf);
|
le_remote_feat_complete(0x00, pdu_data, handle, buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PDU_DATA_LLCTRL_TYPE_VERSION_IND:
|
|
||||||
remote_version_info(pdu_data, handle, buf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
|
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
|
||||||
encrypt_change(pdu_data->llctrl.reject_ind.error_code, handle,
|
encrypt_change(pdu_data->llctrl.reject_ind.error_code, handle,
|
||||||
|
@ -3408,7 +3385,30 @@ void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num)
|
||||||
hc->handle = sys_cpu_to_le16(handle);
|
hc->handle = sys_cpu_to_le16(handle);
|
||||||
hc->count = sys_cpu_to_le16(num);
|
hc->count = sys_cpu_to_le16(num);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#if defined(CONFIG_BT_REMOTE_VERSION)
|
||||||
|
void hci_remote_version_info_encode(struct net_buf *buf,
|
||||||
|
struct pdu_data *pdu_data, u16_t handle)
|
||||||
|
{
|
||||||
|
struct pdu_data_llctrl_version_ind *ver_ind;
|
||||||
|
struct bt_hci_evt_remote_version_info *ep;
|
||||||
|
|
||||||
|
if (!(event_mask & BT_EVT_MASK_REMOTE_VERSION_INFO)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep));
|
||||||
|
ep = net_buf_add(buf, sizeof(*ep));
|
||||||
|
|
||||||
|
ver_ind = &pdu_data->llctrl.version_ind;
|
||||||
|
ep->status = 0x00;
|
||||||
|
ep->handle = sys_cpu_to_le16(handle);
|
||||||
|
ep->version = ver_ind->version_number;
|
||||||
|
ep->manufacturer = ver_ind->company_id;
|
||||||
|
ep->subversion = ver_ind->sub_version_number;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_REMOTE_VERSION */
|
||||||
|
#endif /* CONFIG_BT_CONN */
|
||||||
|
|
||||||
u8_t hci_get_class(struct node_rx_pdu *node_rx)
|
u8_t hci_get_class(struct node_rx_pdu *node_rx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
#include "ll_sw/lll.h"
|
#include "ll_sw/lll.h"
|
||||||
#include "ll.h"
|
#include "ll.h"
|
||||||
|
|
||||||
|
#if (!defined(CONFIG_BT_LL_SW_SPLIT))
|
||||||
|
#include "ll_sw/ctrl.h"
|
||||||
|
#endif /* CONFIG_BT_LL_SW_SPLIT */
|
||||||
|
|
||||||
#include "hci_internal.h"
|
#include "hci_internal.h"
|
||||||
|
|
||||||
#include "hal/debug.h"
|
#include "hal/debug.h"
|
||||||
|
@ -70,6 +74,32 @@ static sys_slist_t hbuf_pend;
|
||||||
static s32_t hbuf_count;
|
static s32_t hbuf_count;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct net_buf *process_prio_evt(struct node_rx_pdu *node_rx)
|
||||||
|
{
|
||||||
|
/* Currently the only event processed */
|
||||||
|
#if defined(CONFIG_BT_REMOTE_VERSION)
|
||||||
|
struct pdu_data *pdu_data = PDU_DATA(node_rx);
|
||||||
|
struct net_buf *buf;
|
||||||
|
u16_t handle;
|
||||||
|
|
||||||
|
/* Avoid using hci_get_class() to speed things up */
|
||||||
|
if (node_rx->hdr.user_meta == HCI_CLASS_EVT_LLCP) {
|
||||||
|
|
||||||
|
handle = node_rx->hdr.handle;
|
||||||
|
if (pdu_data->llctrl.opcode ==
|
||||||
|
PDU_DATA_LLCTRL_TYPE_VERSION_IND) {
|
||||||
|
|
||||||
|
buf = bt_buf_get_evt(BT_HCI_EVT_REMOTE_VERSION_INFO,
|
||||||
|
false, K_FOREVER);
|
||||||
|
hci_remote_version_info_encode(buf, pdu_data, handle);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_BT_CONN */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handover from Controller thread to Host thread
|
* @brief Handover from Controller thread to Host thread
|
||||||
* @details Execution context: Controller thread
|
* @details Execution context: Controller thread
|
||||||
|
@ -82,13 +112,13 @@ static void prio_recv_thread(void *p1, void *p2, void *p3)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
struct node_rx_pdu *node_rx;
|
struct node_rx_pdu *node_rx;
|
||||||
|
struct net_buf *buf;
|
||||||
u8_t num_cmplt;
|
u8_t num_cmplt;
|
||||||
u16_t handle;
|
u16_t handle;
|
||||||
|
|
||||||
/* While there are completed rx nodes */
|
/* While there are completed rx nodes */
|
||||||
while ((num_cmplt = ll_rx_get((void *)&node_rx, &handle))) {
|
while ((num_cmplt = ll_rx_get((void *)&node_rx, &handle))) {
|
||||||
#if defined(CONFIG_BT_CONN)
|
#if defined(CONFIG_BT_CONN)
|
||||||
struct net_buf *buf;
|
|
||||||
|
|
||||||
buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
|
buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
|
||||||
false, K_FOREVER);
|
false, K_FOREVER);
|
||||||
|
@ -108,15 +138,24 @@ static void prio_recv_thread(void *p1, void *p2, void *p3)
|
||||||
/* Find out and store the class for this node */
|
/* Find out and store the class for this node */
|
||||||
node_rx->hdr.user_meta = hci_get_class(node_rx);
|
node_rx->hdr.user_meta = hci_get_class(node_rx);
|
||||||
|
|
||||||
/* Send the rx node up to Host thread, recv_thread() */
|
buf = process_prio_evt(node_rx);
|
||||||
BT_DBG("RX node enqueue");
|
if (buf) {
|
||||||
k_fifo_put(&recv_fifo, node_rx);
|
BT_DBG("Priority event");
|
||||||
|
bt_recv_prio(buf);
|
||||||
|
} else {
|
||||||
|
/* Send the rx node up to Host thread,
|
||||||
|
* recv_thread()
|
||||||
|
*/
|
||||||
|
BT_DBG("RX node enqueue");
|
||||||
|
k_fifo_put(&recv_fifo, node_rx);
|
||||||
|
}
|
||||||
|
|
||||||
/* There may still be completed nodes, continue
|
/* There may still be completed nodes, continue
|
||||||
* pushing all those up to Host before waiting for
|
* pushing all those up to Host before waiting
|
||||||
* ULL mayfly
|
* for ULL mayfly
|
||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_DBG("sem take...");
|
BT_DBG("sem take...");
|
||||||
|
|
|
@ -46,6 +46,8 @@ u8_t hci_get_class(struct node_rx_pdu *node_rx);
|
||||||
int hci_acl_handle(struct net_buf *acl, struct net_buf **evt);
|
int hci_acl_handle(struct net_buf *acl, struct net_buf **evt);
|
||||||
void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf);
|
void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf);
|
||||||
void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num);
|
void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num);
|
||||||
|
void hci_remote_version_info_encode(struct net_buf *buf,
|
||||||
|
struct pdu_data *pdu_data, u16_t handle);
|
||||||
#endif
|
#endif
|
||||||
int hci_vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
int hci_vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
||||||
struct net_buf **evt);
|
struct net_buf **evt);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue