diff --git a/subsys/bluetooth/controller/Kconfig.df b/subsys/bluetooth/controller/Kconfig.df index d8f65300ca3..4407225116d 100644 --- a/subsys/bluetooth/controller/Kconfig.df +++ b/subsys/bluetooth/controller/Kconfig.df @@ -90,6 +90,7 @@ config BT_CTLR_DF_ANT_SWITCH_RX config BT_CTLR_DF_CTE_RX bool "Enable reception of Constant Tone Extension feature" depends on BT_CTLR_DF_CTE_RX_SUPPORT + select BT_CTLR_CONN_RSSI if BT_CONN default y help Enable support for reception of Constant Tone Extension in controller. @@ -133,6 +134,14 @@ config BT_CTLR_DF_CONN_CTE_TX Enable transmission of Constant Tone Extension in direction finding connected mode. +config BT_CTRL_DF_CONN_CTE_RX + bool "Enable Connection based CTE Receiver" + depends on BT_CTLR_DF_CTE_RX && BT_CONN + default y + help + Enable reception and sampling of Constant Tone Extension in + direction finding connected mode. + config BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC bool "Enable sampling of CTE for PDUs with bad CRC" depends on BT_CTLR_DF_SCAN_CTE_RX diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 74316567947..2c730c2beb8 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2785,9 +2785,7 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, struct ll_sync_set *sync; struct lll_sync *lll; uint8_t samples_cnt; - int16_t iq_tmp; int16_t rssi; - uint8_t idx; iq_report = (struct node_rx_iq_report *)node_rx; @@ -2803,7 +2801,7 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, * It should be verified here, to avoid reporint IQ samples after * the functionality was disabled. */ - if (ull_df_sync_cfg_is_disabled_or_requested_to_disable(&lll->df_cfg)) { + if (ull_df_sync_cfg_is_not_enabled(&lll->df_cfg)) { /* Dropp further processing of the event. */ return; } @@ -2846,14 +2844,13 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, if (iq_report->packet_status == BT_HCI_LE_CTE_INSUFFICIENT_RESOURCES) { sep->sample[0].i = BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE; sep->sample[0].q = BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE; - sep->sample_count = 0; + sep->sample_count = 0U; } else { - for (idx = 0; idx < samples_cnt; ++idx) { - iq_tmp = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].i); - sep->sample[idx].i = (int8_t)iq_tmp; - iq_tmp = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].q); - sep->sample[idx].q = (int8_t)iq_tmp; + for (uint8_t idx = 0U; idx < samples_cnt; ++idx) { + sep->sample[idx].i = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].i); + sep->sample[idx].q = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].q); } + sep->sample_count = samples_cnt; } } @@ -2882,7 +2879,7 @@ static void le_df_set_conn_cte_tx_params(struct net_buf *buf, } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) static void le_df_set_conn_cte_rx_params(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_set_conn_cte_rx_params *cmd = (void *)buf->data; @@ -2902,6 +2899,81 @@ static void le_df_set_conn_cte_rx_params(struct net_buf *buf, struct net_buf **e rp->handle = handle_le16; } +static void le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct net_buf *buf) +{ + struct bt_hci_evt_le_connection_iq_report *sep; + struct node_rx_iq_report *iq_report; + struct lll_conn *lll; + uint8_t samples_cnt; + uint8_t phy_rx; + int16_t rssi; + + iq_report = (struct node_rx_iq_report *)node_rx; + + if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) || + !(le_event_mask & BT_EVT_MASK_LE_CONNECTION_IQ_REPORT)) { + return; + } + + lll = iq_report->hdr.rx_ftr.param; + + phy_rx = lll->phy_rx; + /* Make sure the report is generated for connection on PHY UNCODED */ + LL_ASSERT(phy_rx != PHY_CODED); + + /* TX LL thread has higher priority than RX thread. It may happen that host succefully + * disables CTE sampling in the meantime. It should be verified here, to avoid reporing + * IQ samples after the functionality was disabled. + */ + if (ull_df_conn_cfg_is_not_enabled(&lll->df_rx_cfg)) { + /* Dropp further processing of the event. */ + return; + } + + /* If there are no IQ samples due to insufficient resources HCI event should inform about + * it by store single octet with special I_sample and Q_sample data. + */ + samples_cnt = MAX(1, iq_report->sample_count); + + sep = meta_evt(buf, BT_HCI_EVT_LE_CONNECTION_IQ_REPORT, + (sizeof(*sep) + (samples_cnt * sizeof(struct bt_hci_le_iq_sample)))); + + rssi = RSSI_DBM_TO_DECI_DBM(iq_report->hdr.rx_ftr.rssi); + + sep->conn_handle = sys_cpu_to_le16(iq_report->hdr.handle); + sep->rx_phy = phy_rx; + sep->rssi = sys_cpu_to_le16(rssi); + sep->rssi_ant_id = iq_report->rssi_ant_id; + sep->cte_type = iq_report->cte_info.type; + + sep->data_chan_idx = iq_report->chan_idx; + sep->conn_evt_counter = sys_cpu_to_le16(lll->event_counter); + + if (sep->cte_type == BT_HCI_LE_AOA_CTE) { + sep->slot_durations = iq_report->local_slot_durations; + } else if (sep->cte_type == BT_HCI_LE_AOD_CTE_1US) { + sep->slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US; + } else { + sep->slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US; + } + + sep->packet_status = iq_report->packet_status; + + if (iq_report->packet_status == BT_HCI_LE_CTE_INSUFFICIENT_RESOURCES) { + sep->sample[0].i = BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE; + sep->sample[0].q = BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE; + sep->sample_count = 0U; + } else { + for (uint8_t idx = 0U; idx < samples_cnt; ++idx) { + sep->sample[idx].i = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].i); + sep->sample[idx].q = IQ_SHIFT_12_TO_8_BIT(iq_report->sample[idx].q); + } + sep->sample_count = samples_cnt; + } +} +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) static void le_df_set_conn_cte_req_enable(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_conn_cte_req_enable *cmd = (void *)buf->data; @@ -4260,10 +4332,12 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, le_df_set_conn_cte_tx_params(cmd, evt); break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS): le_df_set_conn_cte_rx_params(cmd, evt); break; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case BT_OCF(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE): le_df_set_conn_cte_req_enable(cmd, evt); break; @@ -6975,7 +7049,7 @@ static void encode_control(struct node_rx_pdu *node_rx, break; #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - case NODE_RX_TYPE_IQ_SAMPLE_REPORT: + case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: le_df_connectionless_iq_report(pdu_data, node_rx, buf); break; #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ @@ -7072,6 +7146,11 @@ static void encode_control(struct node_rx_pdu *node_rx, return; #endif /* CONFIG_BT_CTLR_CONN_ISO */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: + le_df_connection_iq_report(node_rx, buf); + return; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_ADV_INDICATION) @@ -7470,7 +7549,7 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) case NODE_RX_TYPE_SYNC_LOST: #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - case NODE_RX_TYPE_IQ_SAMPLE_REPORT: + case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ #if defined(CONFIG_BT_CTLR_SYNC_ISO) @@ -7494,6 +7573,9 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx) #if defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_CIS_ESTABLISHED: #endif /* CONFIG_BT_CTLR_CONN_ISO */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ return HCI_CLASS_EVT_REQUIRED; case NODE_RX_TYPE_TERMINATE: diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 6bc74958a89..77c660664c2 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -283,7 +283,8 @@ enum node_rx_type { NODE_RX_TYPE_CIS_ESTABLISHED, NODE_RX_TYPE_MESH_ADV_CPLT, NODE_RX_TYPE_MESH_REPORT, - NODE_RX_TYPE_IQ_SAMPLE_REPORT, + NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT, + NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT, #if defined(CONFIG_BT_CTLR_USER_EXT) /* No entries shall be added after the NODE_RX_TYPE_USER_START/END */ diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index e9b035e7191..8b75670e6f8 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -148,9 +148,9 @@ struct lll_conn { int8_t tx_pwr_lvl; #endif -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) - struct lll_df_conn_rx_params df_rx_params; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + struct lll_df_conn_rx_cfg df_rx_cfg; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) struct lll_df_conn_tx_cfg df_tx_cfg; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c index 1a952a58585..722749d7ac4 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c @@ -62,13 +62,6 @@ struct df_ant_cfg { #define MAX_ANTENNA_NUM 0 #endif -/* PDU_ANTENNA is defined outside of the #if block below because - * radio_df_pdu_antenna_switch_pattern_get() can get called even when - * the preprocessor condition being tested is 0. In this case, we use - * the default value of 0. - */ -#define PDU_ANTENNA DT_PROP_OR(RADIO_NODE, dfe_pdu_antenna, 0) - uint8_t radio_df_pdu_antenna_switch_pattern_get(void) { return PDU_ANTENNA; @@ -364,23 +357,6 @@ void radio_switch_complete_and_phy_end_b2b_tx(uint8_t phy_curr, uint8_t flags_cu #endif /* !CONFIG_BT_CTLR_TIFS_HW */ } -void radio_switch_complete_phyend_and_rx(uint8_t phy_rx) -{ -#if defined(CONFIG_BT_CTLR_TIFS_HW) - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_PHYEND_DISABLE_Msk | - RADIO_SHORTS_DISABLED_RXEN_Msk; -#else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_PHYEND_DISABLE_Msk; - - /* NOTE: As Tx chain delays are negligible constant values (~1 us) - * across nRF5x radios, sw_switch assumes the 1M chain delay for - * calculations. - */ - sw_switch(SW_SWITCH_TX, SW_SWITCH_RX, SW_SWITCH_PHY_1M, SW_SWITCH_FLAGS_DONTCARE, phy_rx, - SW_SWITCH_FLAGS_DONTCARE); -#endif /* !CONFIG_BT_CTLR_TIFS_HW */ -} - void radio_df_iq_data_packet_set(uint8_t *buffer, size_t len) { nrf_radio_dfe_buffer_set(NRF_RADIO, (uint32_t *)buffer, len); @@ -395,3 +371,8 @@ uint8_t radio_df_cte_status_get(void) { return NRF_RADIO->CTESTATUS; } + +bool radio_df_cte_ready(void) +{ + return (NRF_RADIO->EVENTS_CTEPRESENT != 0); +} diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.h index fef4c20e8bf..b9ddec795cd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.h @@ -4,6 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* PDU_ANTENNA is defined outside of the #if block below because + * radio_df_pdu_antenna_switch_pattern_get() can get called even when + * the preprocessor condition being tested is 0. In this case, we use + * the default value of 0. + */ +#define PDU_ANTENNA DT_PROP_OR(RADIO_NODE, dfe_pdu_antenna, 0) + /* Function configures Radio with information about GPIO pins that may be * used to drive antenna switching during CTE Tx/RX. */ @@ -53,8 +60,6 @@ void radio_switch_complete_and_phy_end_disable(void); /* Completes switching and enables shortcut between PHYEND and TXEN events */ void radio_switch_complete_and_phy_end_b2b_tx(uint8_t phy_curr, uint8_t flags_curr, uint8_t phy_next, uint8_t flags_next); -/* Completes switching and enables shortcut between PHYEND and RXEN events */ -void radio_switch_complete_phyend_and_rx(uint8_t phy_rx); /* Set buffer to store IQ samples collected during CTE sampling */ void radio_df_iq_data_packet_set(uint8_t *buffer, size_t len); @@ -62,3 +67,5 @@ void radio_df_iq_data_packet_set(uint8_t *buffer, size_t len); uint32_t radio_df_iq_samples_amount_get(void); /* Get CTE status (CTEInfo) parsed by Radio from received PDU */ uint8_t radio_df_cte_status_get(void); +/* Get information if CTE was present in a received packet */ +bool radio_df_cte_ready(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c index 26577076144..5450e2e58cb 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c @@ -27,7 +27,7 @@ #include "lll_vendor.h" #include "lll_clock.h" #include "lll_chan.h" -#include "lll/lll_df_types.h" +#include "lll_df_types.h" #include "lll_conn.h" #include "lll_adv_types.h" #include "lll_adv.h" diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c index e479e9f9a0a..8ef6ba1315c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c @@ -88,6 +88,10 @@ static int init_reset(void) static int prepare_cb(struct lll_prepare_param *p) { +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + struct lll_df_conn_rx_params *df_rx_params; + struct lll_df_conn_rx_cfg *df_rx_cfg; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ struct pdu_data *pdu_data_tx; uint32_t ticks_at_event; uint32_t ticks_at_start; @@ -178,22 +182,29 @@ static int prepare_cb(struct lll_prepare_param *p) radio_isr_set(lll_conn_isr_tx, lll); - /* TODO: Remove TIFS extension from IFS when EVETNS_END is switched to EVENTS_PHYEND */ - radio_tmr_tifs_set(EVENT_IFS_US + cte_len); + radio_tmr_tifs_set(EVENT_IFS_US); + +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + /* If CTE RX is enabled and the PHY is not CODED, store channel used for + * the connection event to report it with collected IQ samples. + * The configuration of the CTE receive may not change during the event, + * so config buffer is swapped in prepare and used in IRS handers. + */ + if (lll->phy_rx != PHY_CODED) { + df_rx_cfg = &lll->df_rx_cfg; + df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL); + + if (df_rx_params->is_enabled == true) { + lll->df_rx_cfg.chan = data_chan_use; + } + } +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) -#if defined(CONFIG_BT_CTLR_PHY) - radio_switch_complete_phyend_and_rx(lll->phy_rx); -#else /* !CONFIG_BT_CTLR_PHY */ - radio_switch_complete_phyend_and_rx(0); -#endif /* !CONFIG_BT_CTLR_PHY */ -#else #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(lll->phy_rx); #else /* !CONFIG_BT_CTLR_PHY */ radio_switch_complete_and_rx(0); #endif /* !CONFIG_BT_CTLR_PHY */ -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ ticks_at_event = p->ticks_at_expire; ull = HDR_LLL2ULL(lll); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index ca8af852337..68eb2d61cb8 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -22,12 +22,14 @@ #include "util/mem.h" #include "util/memq.h" #include "util/mfifo.h" +#include "util/dbuf.h" #include "pdu.h" #include "lll.h" #include "lll_clock.h" #include "lll_df_types.h" +#include "lll_df.h" #include "lll_conn.h" #include "lll_internal.h" @@ -46,7 +48,10 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, uint8_t *is_rx_enqueue, struct node_tx **tx_release, uint8_t *is_done); static void empty_tx_init(void); - +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, + uint8_t packet_status); +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) static struct pdu_data *get_last_tx_pdu(struct lll_conn *lll); #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ @@ -184,11 +189,15 @@ void lll_conn_isr_rx(void *param) uint8_t is_rx_enqueue; struct lll_conn *lll; uint8_t rssi_ready; + bool is_iq_report; uint8_t is_ull_rx; uint8_t trx_done; uint8_t is_done; uint8_t cte_len; uint8_t crc_ok; +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + bool cte_ready; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_latency_capture(); @@ -199,8 +208,15 @@ void lll_conn_isr_rx(void *param) if (trx_done) { crc_ok = radio_crc_is_valid(); rssi_ready = radio_rssi_is_ready(); +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + cte_ready = radio_df_cte_ready(); + +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ } else { crc_ok = rssi_ready = 0U; +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + cte_ready = 0U; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ } /* Clear radio rx status and events */ @@ -294,29 +310,17 @@ void lll_conn_isr_rx(void *param) #if defined(CONFIG_BT_PERIPHERAL) /* Event done for peripheral */ } else { -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) - radio_switch_complete_and_phy_end_disable(); -#else radio_switch_complete_and_disable(); -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ #endif /* CONFIG_BT_PERIPHERAL */ } } else { - radio_tmr_tifs_set(EVENT_IFS_US + cte_len); + radio_tmr_tifs_set(EVENT_IFS_US); -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) -#if defined(CONFIG_BT_CTLR_PHY) - radio_switch_complete_phyend_and_rx(lll->phy_rx); -#else /* !CONFIG_BT_CTLR_PHY */ - radio_switch_complete_phyend_and_rx(0); -#endif /* !CONFIG_BT_CTLR_PHY */ -#else #if defined(CONFIG_BT_CTLR_PHY) radio_switch_complete_and_rx(lll->phy_rx); #else /* !CONFIG_BT_CTLR_PHY */ radio_switch_complete_and_rx(0); #endif /* !CONFIG_BT_CTLR_PHY */ -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ radio_isr_set(lll_conn_isr_tx, param); @@ -402,7 +406,20 @@ lll_conn_isr_rx_exit: is_ull_rx = 1U; } - if (is_ull_rx) { +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + if (cte_ready) { + is_iq_report = + create_iq_report(lll, rssi_ready, + (crc_ok == true ? BT_HCI_LE_CTE_CRC_OK : + BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_TIME)); + } else { +#else + if (1) { +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + is_iq_report = false; + } + + if (is_ull_rx || is_iq_report) { ull_rx_sched(); } @@ -450,13 +467,58 @@ void lll_conn_isr_tx(void *param) lll = param; +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) + enum radio_end_evt_delay_state end_evt_delay; +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ + + if (lll->phy_rx != PHY_CODED) { + struct lll_df_conn_rx_params *df_rx_params; + struct lll_df_conn_rx_cfg *df_rx_cfg; + + df_rx_cfg = &lll->df_rx_cfg; + /* Get last swapped CTE RX configuration. Do not swap it again here. + * It should remain unchanged for connection event duration. + */ + df_rx_params = dbuf_curr_get(&df_rx_cfg->hdr); + + if (df_rx_params->is_enabled) { + lll_df_conf_cte_rx_enable(df_rx_params->slot_durations, + df_rx_params->ant_sw_len, df_rx_params->ant_ids, + df_rx_cfg->chan, CTE_INFO_IN_S1_BYTE); + } else { + lll_df_conf_cte_info_parsing_enable(); + } +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) + end_evt_delay = END_EVT_DELAY_ENABLED; + } else { + end_evt_delay = END_EVT_DELAY_DISABLED; +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ + } + +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) + /* Use special API for SOC that requires compensation for PHYEND event delay. */ #if defined(CONFIG_BT_CTLR_PHY) - radio_switch_complete_and_tx(lll->phy_rx, 0, - lll->phy_tx, - lll->phy_flags); + radio_switch_complete_with_delay_compensation_and_tx(lll->phy_rx, 0, lll->phy_tx, + lll->phy_flags, end_evt_delay); +#else /* !CONFIG_BT_CTLR_PHY */ + radio_switch_complete_with_delay_compensation_and_tx(0, 0, 0, 0, end_evt_delay); +#endif /* !CONFIG_BT_CTLR_PHY */ + +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + +/* Use regular API for cases when: + * - CTE RX is not enabled, + * - SOC does not require compensation for PHYEND event delay. + */ +#if !defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) +#if defined(CONFIG_BT_CTLR_PHY) + radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx, lll->phy_flags); #else /* !CONFIG_BT_CTLR_PHY */ radio_switch_complete_and_tx(0, 0, 0, 0); #endif /* !CONFIG_BT_CTLR_PHY */ +#endif /* !CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ lll_conn_rx_pkt_set(lll); @@ -473,6 +535,7 @@ void lll_conn_isr_tx(void *param) cte_len = 0U; } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ + /* +/- 2us active clock jitter, +1 us hcto compensation */ hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + (EVENT_CLOCK_JITTER_US << 1) + RANGE_DELAY_US + HCTO_START_DELAY_US; @@ -491,11 +554,16 @@ void lll_conn_isr_tx(void *param) radio_tmr_hcto_configure(hcto); -#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CONN_RSSI) +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + if (true) { +#elif defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CONN_RSSI) if (!trx_cnt && !lll->role) { +#else + if (false) { +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + radio_rssi_measure(); } -#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_CONN_RSSI */ #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \ defined(HAL_RADIO_GPIO_HAVE_PA_PIN) @@ -929,6 +997,51 @@ static void empty_tx_init(void) #endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ } +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +static inline bool create_iq_report(struct lll_conn *lll, uint8_t rssi_ready, uint8_t packet_status) +{ + struct lll_df_conn_rx_params *rx_params; + struct lll_df_conn_rx_cfg *rx_cfg; + + if (lll->phy_rx == PHY_CODED) { + return false; + } + + rx_cfg = &lll->df_rx_cfg; + + rx_params = dbuf_curr_get(&rx_cfg->hdr); + + if (rx_params->is_enabled) { + struct node_rx_iq_report *iq_report; + struct node_rx_ftr *ftr; + uint8_t cte_info; + uint8_t ant; + + cte_info = radio_df_cte_status_get(); + ant = radio_df_pdu_antenna_switch_pattern_get(); + iq_report = ull_df_iq_report_alloc(); + + iq_report->hdr.type = NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT; + iq_report->sample_count = radio_df_iq_samples_amount_get(); + iq_report->packet_status = packet_status; + iq_report->rssi_ant_id = ant; + iq_report->cte_info = *(struct pdu_cte_info *)&cte_info; + iq_report->local_slot_durations = rx_params->slot_durations; + + ftr = &iq_report->hdr.rx_ftr; + ftr->param = lll; + ftr->rssi = ((rssi_ready) ? radio_rssi_get() : BT_HCI_LE_RSSI_NOT_AVAILABLE); + + ull_rx_put(iq_report->hdr.link, iq_report); + + return true; + } + + return false; +} + +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) /** * @brief Get latest transmitted pdu_data instance diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c index 91f15dbed4e..8e58773e5d3 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c @@ -32,6 +32,16 @@ #include #include "hal/debug.h" +/* Minimum number of antenna switch patterns required by Direction Finding Extension to be + * configured in SWTICHPATTER register. The value is set to 2, even though the radio peripheral + * specification requires 3. + * Radio always configures three antenna patterns. First pattern is set implicitly in + * radio_df_ant_switch_pattern_set. It is provided by DTS radio.dfe_pdu_antenna property. + * There is a need for two more patterns to be provided by an application. + * They are aimed for: reference period and switch-sample period. + */ +#define DF_MIN_ANT_NUM_REQUIRED 2 + static int init_reset(void); #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) static void df_cte_tx_configure(uint8_t cte_type, uint8_t cte_length, uint8_t ant_ids_len, @@ -213,7 +223,9 @@ struct lll_df_sync_cfg *lll_df_sync_cfg_latest_get(struct lll_df_sync *df_cfg, return &df_cfg->cfg[first]; } +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) /* @brief Function initializes reception of Constant Tone Extension. * * @param slot_duration Switching and sampling slots duration (1us or 2us). @@ -252,7 +264,36 @@ void lll_df_conf_cte_rx_enable(uint8_t slot_duration, uint8_t ant_num, const uin radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT); node_rx->chan_idx = chan_idx; } -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +/** + * @brief Function initializes parsing of received PDU for CTEInfo. + * + * Parsing a PDU for CTEInfo is required to successfully receive a PDU that may include CTE. + * It makes possible to correctly interpret PDU content by Radio peripheral. + */ +void lll_df_conf_cte_info_parsing_enable(void) +{ + /* Use of mandatory 2 us switching and sampling slots for CTEInfo parsing. + * The configuration here does not matter for actual IQ sampling. + * The collected data will not be reported to host. + */ + radio_df_cte_rx_4us_switching(true); + +#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) + /* Use PDU_ANTENNA so no actual antenna change will be done. */ + static uint8_t ant_ids[DF_MIN_ANT_NUM_REQUIRED] = { PDU_ANTENNA, PDU_ANTENNA }; + + radio_df_ant_switching_pin_sel_cfg(); + radio_df_ant_switch_pattern_clear(); + radio_df_ant_switch_pattern_set(ant_ids, DF_MIN_ANT_NUM_REQUIRED); +#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */ + + /* Do not set storage for IQ samples, it is irrelevant for parsing of a PDU for CTEInfo. */ + radio_df_iq_data_packet_set(NULL, 0); +} +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ /* @brief Function performs common steps for initialization and reset * of Direction Finding LLL module. diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h index 04554dac0ee..83889ea31ce 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_internal.h @@ -61,3 +61,6 @@ void lll_df_conf_cte_rx_enable(uint8_t slot_duration, uint8_t ant_num, const uin /* Enable CTE transmission according to provided configuration */ void lll_df_conn_cte_tx_enable(const struct lll_df_conn_tx_cfg *df_cfg); + +/* Enabled parsing of a PDU for CTEInfo */ +void lll_df_conf_cte_info_parsing_enable(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h index 88c2c7ca6a4..b19d3b19788 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df_types.h @@ -66,7 +66,7 @@ struct lll_df_adv_cfg { #define IQ_SAMPLE_CNT (PDU_DC_LL_HEADER_SIZE + LL_LENGTH_OCTETS_RX_MAX) #define RSSI_DBM_TO_DECI_DBM(x) (-(x) * 10) -#define IQ_SHIFT_12_TO_8_BIT(x) ((x) >> 4) +#define IQ_SHIFT_12_TO_8_BIT(x) ((int8_t)((x) >> 4)) /* Structure to store an single IQ sample */ struct iq_sample { @@ -94,7 +94,7 @@ struct node_rx_iq_report { */ struct lll_df_sync_cfg { uint8_t is_enabled:1; - uint8_t slot_durations:2; /* One of possible values: 1us, 2us. */ + uint8_t slot_durations:2; /* Bit field where: BIT(0) is 1us, BIT(1) is 2us. */ uint8_t max_cte_count:5; /* Max number of received CTEs. */ uint8_t cte_count:5; /* Received CTEs count. */ uint8_t ant_sw_len:7; @@ -108,13 +108,6 @@ struct lll_df_sync { struct lll_df_sync_cfg cfg[DOUBLE_BUFFER_SIZE]; }; -/* Names for allowed states for CTE sampling in connected mode */ -enum df_cte_sampling_state { - DF_CTE_SAMPLING_UNINITIALIZED, - DF_CTE_SAMPLING_ENABLED, - DF_CTE_SAMPLING_DISABLED, -}; - /* Names for allowed states for CTE transmit parameters in connected mode */ enum df_cte_tx_state { DF_CTE_CONN_TX_PARAMS_UNINITIALIZED, @@ -122,10 +115,26 @@ enum df_cte_tx_state { }; /* Parameters for reception of Constant Tone Extension in connected mode */ struct lll_df_conn_rx_params { - uint8_t state : 2; - uint8_t slot_durations : 2; /* One of possible values: 1 us, 2 us. */ - uint8_t ant_sw_len : 7; + uint8_t is_enabled:1; + uint8_t ant_sw_len:7; uint8_t ant_ids[BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN]; + uint8_t slot_durations:2; /* Bit field where: BIT(0) is 1us, BIT(1) is 2us. */ +}; + +/* Double buffer to store receive and sampling configuration for connected mode */ +struct lll_df_conn_rx_cfg { + /* Stores information if the RX configuration was set at least once. + * It is required for handling HCI_LE_Connection_CTE_Request_Enable HCI command. + * See BT 5.3 Core specification Vol 4, Part E, sec. 7.8.85. + */ + uint8_t is_initialized:1; + /* Channel is set only once for a connection vent. The information will be used during CTE + * RX configuration by ISR handlers. + */ + uint8_t chan:6; + /* Double buffer header must be placed just before memory for the buffer. */ + struct dbuf_hdr hdr; + struct lll_df_conn_rx_params params[DOUBLE_BUFFER_SIZE]; }; /* @brief Structure to store data required to prepare LE Connection IQ Report event or LE diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index 9bccf97b27d..7587ff17d6c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -31,6 +31,7 @@ #include "lll_chan.h" #include "lll_internal.h" +#include "lll_df_internal.h" #include "lll_tim_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) @@ -100,6 +101,10 @@ static int init_reset(void) static int prepare_cb(struct lll_prepare_param *p) { +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + struct lll_df_conn_rx_params *df_rx_params; + struct lll_df_conn_rx_cfg *df_rx_cfg; +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ uint32_t ticks_at_event; uint32_t ticks_at_start; uint16_t event_counter; @@ -208,13 +213,54 @@ static int prepare_cb(struct lll_prepare_param *p) radio_tmr_tifs_set(EVENT_IFS_US); +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) + enum radio_end_evt_delay_state end_evt_delay; +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ + + if (lll->phy_rx != PHY_CODED) { + df_rx_cfg = &lll->df_rx_cfg; + df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL); + + if (df_rx_params->is_enabled == true) { + lll_df_conf_cte_rx_enable(df_rx_params->slot_durations, + df_rx_params->ant_sw_len, df_rx_params->ant_ids, + data_chan_use, CTE_INFO_IN_S1_BYTE); + lll->df_rx_cfg.chan = data_chan_use; + } else { + lll_df_conf_cte_info_parsing_enable(); + } +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) + end_evt_delay = END_EVT_DELAY_ENABLED; + } else { + end_evt_delay = END_EVT_DELAY_DISABLED; +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ + } + +#if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE) +/* Use special API for SOC that requires compensation for PHYEND event delay. */ #if defined(CONFIG_BT_CTLR_PHY) - radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx, - lll->phy_flags); + radio_switch_complete_with_delay_compensation_and_tx(lll->phy_rx, 0, lll->phy_tx, + lll->phy_flags, end_evt_delay); #else /* !CONFIG_BT_CTLR_PHY */ - radio_switch_complete_and_tx(0, 0, 0, 0); + radio_switch_complete_with_delay_compensation_and_tx(0, 0, 0, 0, end_evt_delay); #endif /* !CONFIG_BT_CTLR_PHY */ +#endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + + /* Use regular API for cases when: + * - CTE RX is not enabled, + * - SOC does not require compensation for PHYEND event delay. + */ + if (!IS_ENABLED(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)) { +#if defined(CONFIG_BT_CTLR_PHY) + radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx, lll->phy_flags); +#else /* !CONFIG_BT_CTLR_PHY && !CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */ + radio_switch_complete_and_tx(0, 0, 0, 0); +#endif /* !CONFIG_BT_CTLR_PHY */ + } + ticks_at_event = p->ticks_at_expire; ull = HDR_LLL2ULL(lll); ticks_at_event += lll_event_offset_get(ull); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 5729698d658..a94a2729596 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -949,7 +949,7 @@ static inline int create_iq_report(struct lll_sync *lll, uint8_t rssi_ready, ant = radio_df_pdu_antenna_switch_pattern_get(); iq_report = ull_df_iq_report_alloc(); - iq_report->hdr.type = NODE_RX_TYPE_IQ_SAMPLE_REPORT; + iq_report->hdr.type = NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT; iq_report->sample_count = sample_cnt; iq_report->packet_status = packet_status; iq_report->rssi_ant_id = ant; diff --git a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_df_types.h b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_df_types.h index d622e20826c..f54fc5feb09 100644 --- a/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_df_types.h @@ -8,5 +8,6 @@ * The file shall be used if Direction Finding support is added to OpenISA lower link layer. */ -/* Forward declaration of the type to avoid build errors in ULL code. */ +/* Forward declarations of types to avoid build errors in ULL code. */ struct lll_df_sync; +struct lll_df_conn_rx_cfg; diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index b4964a594b8..60b991c47bf 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -229,7 +229,7 @@ #endif #else #define BT_CTLR_ADV_EXT_RX_CNT 0 -#endif +#endif /* CONFIG_BT_CTLR_DF_CTE_RX */ #if !defined(TICKER_USER_LLL_VENDOR_OPS) #define TICKER_USER_LLL_VENDOR_OPS 0 @@ -1203,9 +1203,13 @@ void ll_rx_dequeue(void) #endif #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - case NODE_RX_TYPE_IQ_SAMPLE_REPORT: + case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + /* Ensure that at least one 'case' statement is present for this * code block. */ @@ -1276,8 +1280,10 @@ void ll_rx_mem_release(void **node_rx) #if defined(CONFIG_BT_OBSERVER) #if defined(CONFIG_BT_CTLR_ADV_EXT) case NODE_RX_TYPE_EXT_SCAN_TERMINATE: + { mem_release(rx_free, &mem_pdu_rx.free); - break; + } + break; #endif /* CONFIG_BT_CTLR_ADV_EXT */ #endif /* CONFIG_BT_OBSERVER */ @@ -1452,16 +1458,6 @@ void ll_rx_mem_release(void **node_rx) } break; -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - case NODE_RX_TYPE_IQ_SAMPLE_REPORT: - { - ull_iq_report_link_inc_quota(1); - ull_df_iq_report_mem_release(rx_free); - ull_df_rx_iq_report_alloc(1); - } - break; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ - #if defined(CONFIG_BT_CTLR_SYNC_ISO) case NODE_RX_TYPE_SYNC_ISO: { @@ -1487,6 +1483,19 @@ void ll_rx_mem_release(void **node_rx) #endif /* CONFIG_BT_CTLR_SYNC_ISO */ #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: + case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: + { + const uint8_t report_cnt = 1U; + + ull_iq_report_link_inc_quota(report_cnt); + ull_df_iq_report_mem_release(rx_free); + ull_df_rx_iq_report_alloc(report_cnt); + } + break; +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + #if defined(CONFIG_BT_CONN) || defined(CONFIG_BT_CTLR_CONN_ISO) case NODE_RX_TYPE_TERMINATE: { @@ -2432,17 +2441,20 @@ static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) ull_sync_established_report(link, rx); } break; -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - case NODE_RX_TYPE_IQ_SAMPLE_REPORT: { +#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ +#endif /* CONFIG_BT_CTLR_ADV_EXT */ +#endif /* CONFIG_BT_OBSERVER */ + +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + case NODE_RX_TYPE_SYNC_IQ_SAMPLE_REPORT: + case NODE_RX_TYPE_CONN_IQ_SAMPLE_REPORT: + { (void)memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL); ll_rx_put(link, rx); ll_rx_sched(); } break; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ -#endif /* CONFIG_BT_CTLR_ADV_EXT */ -#endif /* CONFIG_BT_OBSERVER */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CONN) case NODE_RX_TYPE_CONNECTION: diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index b067d9715bd..88c31505f63 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1025,6 +1025,9 @@ uint8_t ll_adv_enable(uint8_t enable) #if defined(CONFIG_BT_CTLR_CONN_META) memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); #endif /* CONFIG_BT_CTLR_CONN_META */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ conn->connect_expire = 6; conn->supervision_expire = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 9d7455bd559..c5a3b590dd2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -270,6 +270,11 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); #endif /* CONFIG_BT_CTLR_CONN_META */ +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) + conn_lll->df_rx_cfg.is_initialized = false; + conn_lll->df_rx_cfg.hdr.elem_size = sizeof(struct lll_df_conn_rx_params); +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ + conn->connect_expire = CONN_ESTAB_COUNTDOWN; conn->supervision_expire = 0U; conn_interval_us = (uint32_t)interval * CONN_INT_UNIT_US; diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 10d957775f7..c2675d7bec0 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -17,7 +17,7 @@ #include "util/mem.h" #include "util/memq.h" #include "util/mfifo.h" -#include "util/dbuff.h" +#include "util/dbuf.h" #include "pdu.h" @@ -51,7 +51,7 @@ #include "common/log.h" #include "hal/debug.h" -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) #define CTE_LEN_MAX_US 160U @@ -74,7 +74,7 @@ static MFIFO_DEFINE(iq_report_free, sizeof(void *), IQ_REPORT_CNT); /* Number of available instance of linked list to be used for node_rx_iq_reports. */ static uint8_t mem_link_iq_report_quota_pdu; -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX*/ /* ToDo: * - Add release of df_adv_cfg when adv_sync is released. @@ -166,7 +166,7 @@ static int init_reset(void) &df_adv_cfg_free); #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */ -#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) /* Re-initialize the free IQ report mfifo */ MFIFO_INIT(iq_report_free); @@ -178,7 +178,7 @@ static int init_reset(void) /* Allocate free IQ report node rx */ mem_link_iq_report_quota_pdu = IQ_REPORT_CNT; ull_df_rx_iq_report_alloc(UINT8_MAX); -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ return 0; } @@ -469,6 +469,35 @@ uint8_t ll_df_set_cl_iq_sampling_enable(uint16_t handle, return 0; } +void ull_df_sync_cfg_init(struct lll_df_sync *df_cfg) +{ + (void)memset(&df_cfg->cfg, 0, sizeof(df_cfg->cfg)); + df_cfg->first = 0U; + df_cfg->last = 0U; +} + +bool ull_df_sync_cfg_is_not_enabled(struct lll_df_sync *df_cfg) +{ + struct lll_df_sync_cfg *cfg; + + /* If new CTE sampling configuration was enqueued, get reference to + * latest congiruation without swapping buffers. Buffer should be + * swapped only at the beginning of the radio event. + * + * We may not get here if CTE sampling is not enabled in current + * configuration. + */ + if (lll_df_sync_cfg_is_modified(df_cfg)) { + cfg = lll_df_sync_cfg_peek(df_cfg); + } else { + cfg = lll_df_sync_cfg_curr_get(df_cfg); + } + + return !cfg->is_enabled; +} +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ + +#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) || defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) void *ull_df_iq_report_alloc_peek(uint8_t count) { if (count > MFIFO_AVAIL_COUNT_GET(iq_report_free)) { @@ -529,17 +558,12 @@ void ull_df_rx_iq_report_alloc(uint8_t max) ull_iq_report_link_inc_quota(-1); } } +#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX || CONFIG_BT_CTRL_DF_CONN_CTE_RX */ -void ull_df_sync_cfg_init(struct lll_df_sync *cfg) +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +bool ull_df_conn_cfg_is_not_enabled(struct lll_df_conn_rx_cfg *rx_cfg) { - memset(&cfg->cfg[0], 0, DOUBLE_BUFFER_SIZE * sizeof(cfg->cfg[0])); - cfg->first = 0U; - cfg->last = 0U; -} - -uint8_t ull_df_sync_cfg_is_disabled_or_requested_to_disable(struct lll_df_sync *df_cfg) -{ - struct lll_df_sync_cfg *cfg; + struct lll_df_conn_rx_params *rx_params; /* If new CTE sampling configuration was enqueued, get reference to * latest congiruation without swapping buffers. Buffer should be @@ -548,15 +572,15 @@ uint8_t ull_df_sync_cfg_is_disabled_or_requested_to_disable(struct lll_df_sync * * We may not get here if CTE sampling is not enabled in current * configuration. */ - if (lll_df_sync_cfg_is_modified(df_cfg)) { - cfg = lll_df_sync_cfg_peek(df_cfg); + if (dbuf_is_modified(&rx_cfg->hdr)) { + rx_params = dbuf_peek(&rx_cfg->hdr); } else { - cfg = lll_df_sync_cfg_curr_get(df_cfg); + rx_params = dbuf_curr_get(&rx_cfg->hdr); } - return !cfg->is_enabled; + return !rx_params->is_enabled; } -#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) /* @brief Function releases unused memory for DF advertising configuration. @@ -1023,8 +1047,15 @@ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types, uint8_t } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) -/* @brief Function sets CTE reception parameters for a connection. +#if defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +/** + * @brief Function sets CTE reception parameters for a connection. + * + * @note: The CTE may not be send/received with PHY CODED. The BT Core 5.3 specification does not + * mention special handling of CTE receive and sampling while the functionality is enabled + * for a connection that currently uses PHY CODED. Enable of CTE receive for a PHY CODED + * will introduce coplications for TISF maintenance by software switch. To avoid that + * the lower link layer will enable the functionality when connection uses PHY UNCODED only. * * @param handle Connection handle. * @param sampling_enable Enable or disable CTE RX. When the parameter is set to false, @@ -1039,18 +1070,28 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, uint8_t slot_durations, uint8_t switch_pattern_len, const uint8_t *ant_ids) { - struct lll_df_conn_rx_params *df_rx_params; + struct lll_df_conn_rx_params *params_rx; + struct dbuf_hdr *params_buf_hdr; + struct lll_df_conn_rx_cfg *cfg_rx; struct ll_conn *conn; + uint8_t params_idx; conn = ll_connected_get(handle); if (!conn) { return BT_HCI_ERR_UNKNOWN_CONN_ID; } - df_rx_params = &conn->lll.df_rx_params; + cfg_rx = &conn->lll.df_rx_cfg; + /* This is an information for HCI_LE_Connection_CTE_Request_Enable that + * HCI_LE_Set_Connection_CTE_Receive_Parameters was called at least once. + */ + cfg_rx->is_initialized = true; + params_buf_hdr = &cfg_rx->hdr; + + params_rx = dbuf_alloc(params_buf_hdr, ¶ms_idx); if (!sampling_enable) { - df_rx_params->state = DF_CTE_SAMPLING_DISABLED; + params_rx->is_enabled = false; } else { if (IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)) { if (!((IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US) && @@ -1065,15 +1106,19 @@ uint8_t ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable, } } - df_rx_params->state = DF_CTE_SAMPLING_ENABLED; - df_rx_params->slot_durations = slot_durations; - memcpy(df_rx_params->ant_ids, ant_ids, switch_pattern_len); - df_rx_params->ant_sw_len = switch_pattern_len; + params_rx->is_enabled = true; + params_rx->slot_durations = slot_durations; + (void)memcpy(params_rx->ant_ids, ant_ids, switch_pattern_len); + params_rx->ant_sw_len = switch_pattern_len; } + dbuf_enqueue(params_buf_hdr, params_idx); + return BT_HCI_ERR_SUCCESS; } +#endif /* CONFIG_BT_CTRL_DF_CONN_CTE_RX */ +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) /* @brief Function enables or disables CTE request control procedure for a connection. * * The procedure may be enabled in two modes: @@ -1111,7 +1156,7 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable, uint8_t c * Requires refactored LLCPs. */ } else { - if (conn->df_rx_params.state == DF_CTE_SAMPLING_UNINITIALIZED) { + if (!conn->df_rx_params.is_enabled) { return BT_HCI_ERR_CMD_DISALLOWED; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_df_internal.h b/subsys/bluetooth/controller/ll_sw/ull_df_internal.h index 6f2438b0c6d..8f5cb47df2e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_df_internal.h @@ -20,4 +20,6 @@ void ull_df_rx_iq_report_alloc(uint8_t max); /* Initialized DF sync configuration. */ void ull_df_sync_cfg_init(struct lll_df_sync *cfg); /* Returns information if CTE sampling for periodic sync is requested to disable. */ -uint8_t ull_df_sync_cfg_is_disabled_or_requested_to_disable(struct lll_df_sync *df_cfg); +bool ull_df_sync_cfg_is_not_enabled(struct lll_df_sync *df_cfg); +/* Returns information if CTE sampling for a connection is not enabled. */ +bool ull_df_conn_cfg_is_not_enabled(struct lll_df_conn_rx_cfg *rx_cfg); diff --git a/subsys/bluetooth/controller/ll_sw/ull_df_types.h b/subsys/bluetooth/controller/ll_sw/ull_df_types.h index ec064c949cf..42f669daf20 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_df_types.h @@ -28,7 +28,15 @@ enum df_switch_sample_support { * - for ULL -> LL(HCI). */ #if defined(CONFIG_BT_PER_ADV_SYNC_MAX) && defined(CONFIG_BT_CTLR_DF_PER_SCAN_CTE_NUM_MAX) -#define IQ_REPORT_CNT (CONFIG_BT_PER_ADV_SYNC_MAX * CONFIG_BT_CTLR_DF_PER_SCAN_CTE_NUM_MAX * 2) +#define SYNC_IQ_REPORT_CNT (CONFIG_BT_PER_ADV_SYNC_MAX * CONFIG_BT_CTLR_DF_PER_SCAN_CTE_NUM_MAX * 2) #else -#define IQ_REPORT_CNT 0 +#define SYNC_IQ_REPORT_CNT 0U #endif + +#if defined(CONFIG_BT_MAX_CONN) && defined(CONFIG_BT_CTRL_DF_CONN_CTE_RX) +#define CONN_IQ_REPORT_CNT (CONFIG_BT_MAX_CONN * 2) +#else +#define CONN_IQ_REPORT_CNT 0U +#endif + +#define IQ_REPORT_CNT (SYNC_IQ_REPORT_CNT + CONN_IQ_REPORT_CNT) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 28f32ee7a4c..2b1a133a6ad 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c index 860525d97fd..f0955b0936b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 7b6df24280f..619c2045f02 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index a5343427a7b..cb194bd92cf 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index 8cb7b53dae7..bba4fea04a1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -17,6 +17,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index e55660ef09e..e142dd192e6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c index c76b2efc5cd..60f0a0e7328 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index 895222741d9..021b2a35cc3 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index c156b51ec4b..9f2ea5e3bea 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/mem.h" #include "util/memq.h" +#include "util/dbuf.h" #include "pdu.h" #include "ll.h" diff --git a/tests/bluetooth/df/common/src/bt_conn_common.c b/tests/bluetooth/df/common/src/bt_conn_common.c index 988c3ead681..227c3549148 100644 --- a/tests/bluetooth/df/common/src/bt_conn_common.c +++ b/tests/bluetooth/df/common/src/bt_conn_common.c @@ -10,6 +10,7 @@ #include #include +#include "util/dbuf.h" #include diff --git a/tests/bluetooth/df/connectionless_cte_chains/src/common.c b/tests/bluetooth/df/connectionless_cte_chains/src/common.c index 887fde83d9d..ea067c69f6b 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/src/common.c +++ b/tests/bluetooth/df/connectionless_cte_chains/src/common.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/memq.h" #include "util/mem.h" +#include "util/dbuf.h" #include "pdu.h" diff --git a/tests/bluetooth/df/connectionless_cte_chains/src/test_add_cte_to_chain.c b/tests/bluetooth/df/connectionless_cte_chains/src/test_add_cte_to_chain.c index b735b99dd69..79bb31ed1e6 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/src/test_add_cte_to_chain.c +++ b/tests/bluetooth/df/connectionless_cte_chains/src/test_add_cte_to_chain.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/memq.h" #include "util/mem.h" +#include "util/dbuf.h" #include "pdu.h" diff --git a/tests/bluetooth/df/connectionless_cte_chains/src/test_remove_cte_from_chain.c b/tests/bluetooth/df/connectionless_cte_chains/src/test_remove_cte_from_chain.c index 3903fddc39a..974ddee6744 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/src/test_remove_cte_from_chain.c +++ b/tests/bluetooth/df/connectionless_cte_chains/src/test_remove_cte_from_chain.c @@ -16,6 +16,7 @@ #include "util/util.h" #include "util/memq.h" #include "util/mem.h" +#include "util/dbuf.h" #include "pdu.h" diff --git a/tests/bluetooth/df/connectionless_cte_rx/src/common.c b/tests/bluetooth/df/connectionless_cte_rx/src/common.c index fe5db1e8050..98e0d44a5c9 100644 --- a/tests/bluetooth/df/connectionless_cte_rx/src/common.c +++ b/tests/bluetooth/df/connectionless_cte_rx/src/common.c @@ -14,6 +14,7 @@ #include #include +#include "util/dbuf.h" #include #include