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:
Carles Cufi 2019-10-07 18:33:48 +02:00 committed by Carles Cufí
commit 6c34983ed2
4 changed files with 94 additions and 44 deletions

View file

@ -86,18 +86,6 @@ config BT_OBSERVER
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"
config BT_CONN
@ -126,6 +114,27 @@ config BT_HCI_ACL_FLOW_CONTROL
to the host. This is particularly useful when the host and
controller are on separate cores since it ensures that we do
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
# Workaround for not being able to have commas in macro arguments

View file

@ -532,8 +532,10 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
rp->status = 0x00;
(void)memset(&rp->commands[0], 0, sizeof(rp->commands));
#if defined(CONFIG_BT_REMOTE_VERSION)
/* Read Remote Version Info. */
rp->commands[2] |= BIT(7);
#endif
/* Set Event Mask, and Reset. */
rp->commands[5] |= BIT(6) | BIT(7);
/* 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)
static void le_conn_param_req(struct pdu_data *pdu_data, u16_t handle,
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);
break;
case PDU_DATA_LLCTRL_TYPE_VERSION_IND:
remote_version_info(pdu_data, handle, buf);
break;
#if defined(CONFIG_BT_CTLR_LE_ENC)
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
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->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)
{

View file

@ -45,6 +45,10 @@
#include "ll_sw/lll.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 "hal/debug.h"
@ -70,6 +74,32 @@ static sys_slist_t hbuf_pend;
static s32_t hbuf_count;
#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
* @details Execution context: Controller thread
@ -82,13 +112,13 @@ static void prio_recv_thread(void *p1, void *p2, void *p3)
{
while (1) {
struct node_rx_pdu *node_rx;
struct net_buf *buf;
u8_t num_cmplt;
u16_t handle;
/* While there are completed rx nodes */
while ((num_cmplt = ll_rx_get((void *)&node_rx, &handle))) {
#if defined(CONFIG_BT_CONN)
struct net_buf *buf;
buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
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 */
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);
if (buf) {
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
* pushing all those up to Host before waiting for
* ULL mayfly
* pushing all those up to Host before waiting
* for ULL mayfly
*/
continue;
}
BT_DBG("sem take...");

View file

@ -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);
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_remote_version_info_encode(struct net_buf *buf,
struct pdu_data *pdu_data, u16_t handle);
#endif
int hci_vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt);