diff --git a/subsys/bluetooth/controller/Kconfig.df b/subsys/bluetooth/controller/Kconfig.df index bc2e16a6c39..b932353faa9 100644 --- a/subsys/bluetooth/controller/Kconfig.df +++ b/subsys/bluetooth/controller/Kconfig.df @@ -102,7 +102,7 @@ config BT_CTLR_DF_CONN_CTE_REQ config BT_CTLR_DF_CONN_CTE_RSP bool "Enable Connection CTE Response feature" - depends on BT_CTLR_DF_CTE_TX && BT_CONN + depends on BT_CTLR_DF_CONN_CTE_TX help Enable support for Bluetooth v5.1 Connection CTE Response feature in controller. @@ -124,6 +124,14 @@ config BT_CTLR_DF_SCAN_CTE_RX Enable support for Bluetooth v5.1 connectionless CTE reception in controller. +config BT_CTLR_DF_CONN_CTE_TX + bool "Enable Connection based CTE Transmitter" + depends on BT_CTLR_DF_CTE_TX && BT_CONN + default y + help + Enable transmission 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 ac7ccc7ea61..fce119be73f 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -2858,7 +2858,7 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx, } #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) static void le_df_set_conn_cte_tx_params(struct net_buf *buf, struct net_buf **evt) { @@ -2879,7 +2879,7 @@ static void le_df_set_conn_cte_tx_params(struct net_buf *buf, rp->status = status; rp->handle = handle_le16; } -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) static void le_df_set_conn_cte_rx_params(struct net_buf *buf, struct net_buf **evt) @@ -4238,11 +4238,11 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, case BT_OCF(BT_HCI_OP_LE_READ_ANT_INFO): le_df_read_ant_inf(cmd, evt); break; -#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS): le_df_set_conn_cte_tx_params(cmd, evt); break; -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS): le_df_set_conn_cte_rx_params(cmd, evt); diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 24677f66c7a..36baeb2b987 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -297,8 +297,7 @@ uint8_t ll_df_set_cl_cte_tx_params(uint8_t adv_handle, uint8_t cte_len, uint8_t ll_df_set_cl_cte_tx_enable(uint8_t adv_handle, uint8_t cte_enable); /* Provides information about antennae switching and sampling settings */ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types, - uint8_t switching_patterns_len, - uint8_t *ant_id); + uint8_t switching_patterns_len, const uint8_t *ant_id); /* Enables or disables CTE sampling in direction fingin connected mode. */ 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, diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index 7221a07b107..e9b035e7191 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -151,6 +151,9 @@ struct lll_conn { #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_CTLR_DF_CONN_CTE_TX) + struct lll_df_conn_tx_cfg df_tx_cfg; +#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */ }; int lll_conn_init(void); 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 d8fb7302a3c..e2871953b16 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -860,7 +860,7 @@ static void empty_tx_init(void) p = (void *)radio_pkt_empty_get(); p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; - p->cp = PDU_DATA_CTE_PRESENT_BIT_DISABLED; + p->cp = false; #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) p->resv = 0U; #endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ 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 17291007548..d8e6500cf3e 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 @@ -109,6 +109,11 @@ enum df_cte_sampling_state { 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, + DF_CTE_CONN_TX_PARAMS_SET, +}; /* Parameters for reception of Constant Tone Extension in connected mode */ struct lll_df_conn_rx_params { uint8_t state : 2; @@ -119,9 +124,6 @@ struct lll_df_conn_rx_params { /* @brief Structure to store data required to prepare LE Connection IQ Report event or LE * Connectionless IQ Report event. - * - * TODO (ppryga): use struct cte_conn_iq_report in connected mode. Members are exactly the same as - * members of node_rx_iq_report except hdr. */ struct cte_conn_iq_report { struct pdu_cte_info cte_info; @@ -134,3 +136,14 @@ struct cte_conn_iq_report { struct iq_sample sample[0]; }; }; + +/* Configuration for transmission of Constant Tone Extension in connected mode */ +struct lll_df_conn_tx_cfg { + uint8_t state:1; + uint8_t ant_sw_len:7; + uint8_t cte_type:2; + uint8_t cte_length:6; /* Length of CTE in 8us units */ + uint8_t cte_rsp_en:1; /* CTE response is enabled */ + uint8_t cte_types_allowed:3; /* Bitfield with allowed CTE types */ + uint8_t ant_ids[BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN]; +}; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 005f60a023b..e0d17c98419 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -34,9 +34,9 @@ #include "lll_adv.h" #include "lll/lll_adv_pdu.h" #include "lll_scan.h" +#include "lll/lll_df_types.h" #include "lll_conn.h" #include "lll_filter.h" -#include "lll/lll_df_types.h" #if !defined(CONFIG_BT_LL_SW_LLCP_LEGACY) #include "ll_sw/ull_tx_queue.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index ae9c20e562b..bdf9414ab2c 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -2058,7 +2058,7 @@ void ull_pdu_data_init(struct pdu_data *pdu_tx) { LL_ASSERT(pdu_tx); - pdu_tx->cp = PDU_DATA_CTE_PRESENT_BIT_DISABLED; + pdu_tx->cp = false; pdu_tx->rfu = 0U; #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) pdu_tx->resv = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index 85bf06a2caa..0e857cd892e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -233,11 +233,9 @@ uint8_t ll_df_set_cl_cte_tx_params(uint8_t adv_handle, uint8_t cte_len, return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; } - if ((cte_type == BT_HCI_LE_AOD_CTE_1US || - cte_type == BT_HCI_LE_AOD_CTE_2US) && - (num_ant_ids < LLL_DF_MIN_ANT_PATTERN_LEN || - num_ant_ids > BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN || - !ant_ids)) { + if ((cte_type == BT_HCI_LE_AOD_CTE_1US || cte_type == BT_HCI_LE_AOD_CTE_2US) && + (num_ant_ids < BT_HCI_LE_CTE_LEN_MIN || + num_ant_ids > BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN || !ant_ids)) { return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; } @@ -961,7 +959,7 @@ static uint8_t cte_info_clear(struct ll_adv_set *adv, struct lll_df_adv_cfg *df_ } #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */ -#if defined CONFIG_BT_CTLR_DF_CONN_CTE_RSP +#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) /* @brief Function sets CTE transmission parameters for a connection. * * @param handle Connection handle. @@ -973,22 +971,56 @@ static uint8_t cte_info_clear(struct ll_adv_set *adv, struct lll_df_adv_cfg *df_ * @return Status of command completion. */ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types, uint8_t switch_pattern_len, - uint8_t *ant_id) + const uint8_t *ant_ids) { - if (cte_types & BT_HCI_LE_AOD_CTE_RSP_1US || cte_types & BT_HCI_LE_AOD_CTE_RSP_2US) { - if (!IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX)) { + struct lll_df_conn_tx_cfg *df_tx_cfg; + struct ll_conn *conn; + + conn = ll_connected_get(handle); + if (!conn) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + + df_tx_cfg = &conn->lll.df_tx_cfg; + + if (df_tx_cfg->cte_rsp_en) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + + /* Bits other than representing AoA, AoD 1us, AoD 2us are RFU */ + if (cte_types == 0U || + ((cte_types & (~(uint8_t)(BT_HCI_LE_AOA_CTE_RSP | BT_HCI_LE_AOD_CTE_RSP_1US | + BT_HCI_LE_AOD_CTE_RSP_2US))) != 0U)) { + return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; + } + + if (!IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX)) { + if (cte_types & BT_HCI_LE_AOD_CTE_RSP_2US) { return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; } - if (switch_pattern_len < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN || - switch_pattern_len > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX || !ant_id) { + if ((cte_types & BT_HCI_LE_AOD_CTE_RSP_1US) && + !IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US)) { return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; } } - return BT_HCI_ERR_CMD_DISALLOWED; + /* Check antenna switching pattern only whether CTE TX in AoD mode is allowed */ + if (((cte_types & BT_HCI_LE_AOD_CTE_RSP_1US) || (cte_types & BT_HCI_LE_AOD_CTE_RSP_2US)) && + (switch_pattern_len < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN || + switch_pattern_len > BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN || !ant_ids)) { + return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; + } + + (void)memcpy(df_tx_cfg->ant_ids, ant_ids, switch_pattern_len); + df_tx_cfg->ant_sw_len = switch_pattern_len; + + df_tx_cfg->cte_types_allowed = cte_types; + df_tx_cfg->state = DF_CTE_CONN_TX_PARAMS_SET; + + return BT_HCI_ERR_SUCCESS; } -#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ +#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.