Bluetooth: host: Add IQ reports handing in DF connecte mode
Add reception of IQ sample report from controller. Add applications notification about received reports. Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
parent
f18637fe30
commit
a26ee7ce73
7 changed files with 123 additions and 0 deletions
|
@ -23,6 +23,7 @@
|
||||||
#include <bluetooth/hci_err.h>
|
#include <bluetooth/hci_err.h>
|
||||||
#include <bluetooth/addr.h>
|
#include <bluetooth/addr.h>
|
||||||
#include <bluetooth/gap.h>
|
#include <bluetooth/gap.h>
|
||||||
|
#include <bluetooth/direction.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -927,6 +928,17 @@ struct bt_conn_cb {
|
||||||
struct bt_conn_le_data_len_info *info);
|
struct bt_conn_le_data_len_info *info);
|
||||||
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */
|
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)
|
||||||
|
/** @brief Callback for IQ samples report collected when sampling
|
||||||
|
* CTE received by data channel PDU.
|
||||||
|
*
|
||||||
|
* @param conn The connection object.
|
||||||
|
* @param iq_report Report data for collected IQ samples.
|
||||||
|
*/
|
||||||
|
void (*cte_report_cb)(struct bt_conn *conn,
|
||||||
|
const struct bt_df_conn_iq_samples_report *iq_report);
|
||||||
|
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
|
||||||
|
|
||||||
struct bt_conn_cb *_next;
|
struct bt_conn_cb *_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,28 @@ struct bt_df_conn_cte_rx_param {
|
||||||
const uint8_t *ant_ids;
|
const uint8_t *ant_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bt_df_conn_iq_samples_report {
|
||||||
|
/** 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. */
|
||||||
|
uint8_t chan_idx;
|
||||||
|
/** The RSSI of the PDU with CTE (excluding CTE). */
|
||||||
|
int16_t rssi;
|
||||||
|
/** Id of antenna used to measure the RSSI. */
|
||||||
|
uint8_t rssi_ant_id;
|
||||||
|
/** Type of CTE (@ref bt_df_cte_type). */
|
||||||
|
uint8_t cte_type;
|
||||||
|
/** Duration of slots when received CTE type is AoA (@ref bt_df_antenna_switching_slot). */
|
||||||
|
uint8_t slot_durations;
|
||||||
|
/** Status of received PDU with CTE (@ref bt_df_packet_status). */
|
||||||
|
uint8_t packet_status;
|
||||||
|
/** Value of connection event counter when the CTE was received and sampled. */
|
||||||
|
uint16_t conn_evt_counter;
|
||||||
|
/** Number of IQ samples in report. */
|
||||||
|
uint8_t sample_count;
|
||||||
|
/** Pinter to IQ samples data. */
|
||||||
|
struct bt_hci_le_iq_sample const *sample;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* @brief Set or update the Constant Tone Extension parameters for periodic advertising set.
|
* @brief Set or update the Constant Tone Extension parameters for periodic advertising set.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/direction.h>
|
||||||
#include <bluetooth/conn.h>
|
#include <bluetooth/conn.h>
|
||||||
#include <drivers/bluetooth/hci_driver.h>
|
#include <drivers/bluetooth/hci_driver.h>
|
||||||
#include <bluetooth/att.h>
|
#include <bluetooth/att.h>
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
#include "att_internal.h"
|
#include "att_internal.h"
|
||||||
#include "gatt_internal.h"
|
#include "gatt_internal.h"
|
||||||
#include "iso_internal.h"
|
#include "iso_internal.h"
|
||||||
|
#include "direction_internal.h"
|
||||||
|
|
||||||
struct tx_meta {
|
struct tx_meta {
|
||||||
struct bt_conn_tx *tx;
|
struct bt_conn_tx *tx;
|
||||||
|
@ -2921,4 +2923,33 @@ int bt_conn_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)
|
||||||
|
void bt_hci_le_df_connection_iq_report(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_connection_iq_report(buf, &iq_report, &conn);
|
||||||
|
if (err) {
|
||||||
|
BT_ERR("Prepare CTE conn 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
|
||||||
|
|
||||||
#endif /* CONFIG_BT_CONN */
|
#endif /* CONFIG_BT_CONN */
|
||||||
|
|
|
@ -542,6 +542,55 @@ static int hci_df_set_conn_cte_rx_enable(struct bt_conn *conn, bool enable,
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct bt_hci_evt_le_connection_iq_report *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_RX_ENABLED)) {
|
||||||
|
BT_ERR("Received conn CTE report when CTE receive disabled");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(conn->cte_type & BIT(evt->cte_type))) {
|
||||||
|
BT_DBG("CTE filtered out by cte_type: %u", evt->cte_type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
report->chan_idx = evt->data_chan_idx;
|
||||||
|
report->rx_phy = evt->rx_phy;
|
||||||
|
report->chan_idx = evt->data_chan_idx;
|
||||||
|
report->rssi = evt->rssi;
|
||||||
|
report->rssi_ant_id = evt->rssi_ant_id;
|
||||||
|
report->cte_type = BIT(evt->cte_type);
|
||||||
|
report->packet_status = evt->packet_status;
|
||||||
|
report->slot_durations = evt->slot_durations;
|
||||||
|
report->conn_evt_counter = sys_le16_to_cpu(evt->conn_evt_counter);
|
||||||
|
report->sample_count = evt->sample_count;
|
||||||
|
report->sample = evt->sample;
|
||||||
|
|
||||||
|
*conn_to_report = conn;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
|
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
|
||||||
|
|
||||||
/* @brief Function initializes Direction Finding in Host
|
/* @brief Function initializes Direction Finding in Host
|
||||||
|
|
|
@ -10,3 +10,6 @@ int le_df_init(void);
|
||||||
void hci_df_prepare_connectionless_iq_report(struct net_buf *buf,
|
void hci_df_prepare_connectionless_iq_report(struct net_buf *buf,
|
||||||
struct bt_df_per_adv_sync_iq_samples_report *report,
|
struct bt_df_per_adv_sync_iq_samples_report *report,
|
||||||
struct bt_le_per_adv_sync **per_adv_sync_to_report);
|
struct bt_le_per_adv_sync **per_adv_sync_to_report);
|
||||||
|
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);
|
||||||
|
|
|
@ -2225,6 +2225,10 @@ static const struct event_handler meta_events[] = {
|
||||||
EVENT_HANDLER(BT_HCI_EVT_LE_CONNECTIONLESS_IQ_REPORT, bt_hci_le_df_connectionless_iq_report,
|
EVENT_HANDLER(BT_HCI_EVT_LE_CONNECTIONLESS_IQ_REPORT, bt_hci_le_df_connectionless_iq_report,
|
||||||
sizeof(struct bt_hci_evt_le_connectionless_iq_report)),
|
sizeof(struct bt_hci_evt_le_connectionless_iq_report)),
|
||||||
#endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
|
#endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
|
||||||
|
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)
|
||||||
|
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void hci_le_meta_event(struct net_buf *buf)
|
static void hci_le_meta_event(struct net_buf *buf)
|
||||||
|
|
|
@ -450,3 +450,5 @@ void bt_hci_read_remote_features_complete(struct net_buf *buf);
|
||||||
void bt_hci_read_remote_ext_features_complete(struct net_buf *buf);
|
void bt_hci_read_remote_ext_features_complete(struct net_buf *buf);
|
||||||
void bt_hci_role_change(struct net_buf *buf);
|
void bt_hci_role_change(struct net_buf *buf);
|
||||||
void bt_hci_synchronous_conn_complete(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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue