Bluetooth: host: df: Add handling of HCI_LE_CTE_Request_Failed

There were no handling of HCI_LE_CTE_Request_Failed event.
The commit adds missing implementation. An application will
be notified about failed request by cte_report_cb. It is the
same callback that is used for reporting collected CTE IQ
samples. The same callback was used to avoid creation new callback.
To give an application possibility to distinguish between regular
IQ samples report and request failed additional member err was added
to bf_df_conn_iq_samples_report structure.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2022-01-08 14:06:49 +01:00 committed by Christopher Friedt
parent 41ad4f6880
commit 2feedecdac
6 changed files with 91 additions and 1 deletions

View File

@ -137,7 +137,18 @@ struct bt_df_conn_cte_rx_param {
const uint8_t *ant_ids;
};
enum bt_df_conn_iq_report_err {
/** IQ samples report received successfully. */
BT_DF_IQ_REPORT_ERR_SUCCESS,
/** Received PDU without CTE. No valid data in report. */
BT_DF_IQ_REPORT_ERR_NO_CTE,
/** Peer rejected CTE request. No valid data in report. */
BT_DF_IQ_REPORT_ERR_PEER_REJECTED,
};
struct bt_df_conn_iq_samples_report {
/** Report receive failed reason. */
enum bt_df_conn_iq_report_err err;
/** PHY that was used to receive PDU with CTE that was sampled. */
uint8_t rx_phy;
/** Channel index used to receive PDU with CTE that was sampled. */

View File

@ -2953,4 +2953,35 @@ void bt_hci_le_df_connection_iq_report(struct net_buf *buf)
}
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_REQ)
void bt_hci_le_df_cte_req_failed(struct net_buf *buf)
{
struct bt_df_conn_iq_samples_report iq_report;
struct bt_conn *conn;
struct bt_conn_cb *cb;
int err;
err = hci_df_prepare_conn_cte_req_failed(buf, &iq_report, &conn);
if (err) {
BT_ERR("Prepare CTE REQ failed IQ report failed %d", err);
return;
}
for (cb = callback_list; cb; cb = cb->_next) {
if (cb->cte_report_cb) {
cb->cte_report_cb(conn, &iq_report);
}
}
STRUCT_SECTION_FOREACH(bt_conn_cb, cb)
{
if (cb->cte_report_cb) {
cb->cte_report_cb(conn, &iq_report);
}
}
bt_conn_unref(conn);
}
#endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */
#endif /* CONFIG_BT_CONN */

View File

@ -605,7 +605,6 @@ int hci_df_prepare_connection_iq_report(struct net_buf *buf,
evt = net_buf_pull_mem(buf, sizeof(*evt));
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle));
if (!conn) {
BT_ERR("Unknown conn handle 0x%04X for iq samples report",
sys_le16_to_cpu(evt->conn_handle));
@ -622,6 +621,7 @@ int hci_df_prepare_connection_iq_report(struct net_buf *buf,
return -EINVAL;
}
report->err = BT_DF_IQ_REPORT_ERR_SUCCESS;
report->chan_idx = evt->data_chan_idx;
report->rx_phy = evt->rx_phy;
report->chan_idx = evt->data_chan_idx;
@ -710,6 +710,45 @@ static int hci_df_set_conn_cte_req_enable(struct bt_conn *conn, bool enable,
return err;
}
int hci_df_prepare_conn_cte_req_failed(struct net_buf *buf,
struct bt_df_conn_iq_samples_report *report,
struct bt_conn **conn_to_report)
{
struct bt_hci_evt_le_cte_req_failed *evt;
struct bt_conn *conn;
if (buf->len < sizeof(*evt)) {
BT_ERR("Unexpected end of buffer");
return -EINVAL;
}
evt = net_buf_pull_mem(buf, sizeof(*evt));
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle));
if (!conn) {
BT_ERR("Unknown conn handle 0x%04X for iq samples report",
sys_le16_to_cpu(evt->conn_handle));
return -EINVAL;
}
if (!atomic_test_bit(conn->flags, BT_CONN_CTE_REQ_ENABLED)) {
BT_ERR("Received conn CTE request notification when CTE REQ disabled");
return -EINVAL;
}
(void)memset(report, 0U, sizeof(*report));
if (evt->status == BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE) {
report->err = BT_DF_IQ_REPORT_ERR_NO_CTE;
} else {
report->err = BT_DF_IQ_REPORT_ERR_PEER_REJECTED;
}
*conn_to_report = conn;
return 0;
}
#endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RSP)

View File

@ -13,3 +13,6 @@ void hci_df_prepare_connectionless_iq_report(struct net_buf *buf,
int hci_df_prepare_connection_iq_report(struct net_buf *buf,
struct bt_df_conn_iq_samples_report *report,
struct bt_conn **conn_to_report);
int hci_df_prepare_conn_cte_req_failed(struct net_buf *buf,
struct bt_df_conn_iq_samples_report *report,
struct bt_conn **conn_to_report);

View File

@ -2229,6 +2229,11 @@ static const struct event_handler meta_events[] = {
EVENT_HANDLER(BT_HCI_EVT_LE_CONNECTION_IQ_REPORT, bt_hci_le_df_connection_iq_report,
sizeof(struct bt_hci_evt_le_connection_iq_report)),
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_REQ)
EVENT_HANDLER(BT_HCI_EVT_LE_CTE_REQUEST_FAILED, bt_hci_le_df_cte_req_failed,
sizeof(struct bt_hci_evt_le_cte_req_failed)),
#endif /* CONFIG_BT_DF_CONNECTION_CTE_REQ */
};
static void hci_le_meta_event(struct net_buf *buf)

View File

@ -469,3 +469,4 @@ void bt_hci_role_change(struct net_buf *buf);
void bt_hci_synchronous_conn_complete(struct net_buf *buf);
void bt_hci_le_df_connection_iq_report(struct net_buf *buf);
void bt_hci_le_df_cte_req_failed(struct net_buf *buf);