Bluetooth: controller: complete DF TX params set in conn mode

HCI_LE_Set_Connection_CTE_Transmit_Parameters host command was
not completely implemented in controller. There were missign
storage of TX parameters in ll_conn instance.

The commit adds missing part of the command handling.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2021-12-09 13:02:03 +01:00 committed by Carles Cufí
commit 1ff9baf010
9 changed files with 81 additions and 26 deletions

View file

@ -102,7 +102,7 @@ config BT_CTLR_DF_CONN_CTE_REQ
config BT_CTLR_DF_CONN_CTE_RSP config BT_CTLR_DF_CONN_CTE_RSP
bool "Enable Connection CTE Response feature" bool "Enable Connection CTE Response feature"
depends on BT_CTLR_DF_CTE_TX && BT_CONN depends on BT_CTLR_DF_CONN_CTE_TX
help help
Enable support for Bluetooth v5.1 Connection CTE Response feature Enable support for Bluetooth v5.1 Connection CTE Response feature
in controller. in controller.
@ -124,6 +124,14 @@ config BT_CTLR_DF_SCAN_CTE_RX
Enable support for Bluetooth v5.1 connectionless CTE reception Enable support for Bluetooth v5.1 connectionless CTE reception
in controller. 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 config BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC
bool "Enable sampling of CTE for PDUs with bad CRC" bool "Enable sampling of CTE for PDUs with bad CRC"
depends on BT_CTLR_DF_SCAN_CTE_RX depends on BT_CTLR_DF_SCAN_CTE_RX

View file

@ -2858,7 +2858,7 @@ static void le_df_connectionless_iq_report(struct pdu_data *pdu_rx,
} }
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_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, static void le_df_set_conn_cte_tx_params(struct net_buf *buf,
struct net_buf **evt) 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->status = status;
rp->handle = handle_le16; 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) #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) 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): case BT_OCF(BT_HCI_OP_LE_READ_ANT_INFO):
le_df_read_ant_inf(cmd, evt); le_df_read_ant_inf(cmd, evt);
break; 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): case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS):
le_df_set_conn_cte_tx_params(cmd, evt); le_df_set_conn_cte_tx_params(cmd, evt);
break; 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) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS): case BT_OCF(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS):
le_df_set_conn_cte_rx_params(cmd, evt); le_df_set_conn_cte_rx_params(cmd, evt);

View file

@ -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); 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 */ /* 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 ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types,
uint8_t switching_patterns_len, uint8_t switching_patterns_len, const uint8_t *ant_id);
uint8_t *ant_id);
/* Enables or disables CTE sampling in direction fingin connected mode. */ /* 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 ll_df_set_conn_cte_rx_params(uint16_t handle, uint8_t sampling_enable,
uint8_t slot_durations, uint8_t switch_pattern_len, uint8_t slot_durations, uint8_t switch_pattern_len,

View file

@ -151,6 +151,9 @@ struct lll_conn {
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
struct lll_df_conn_rx_params df_rx_params; struct lll_df_conn_rx_params df_rx_params;
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #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); int lll_conn_init(void);

View file

@ -860,7 +860,7 @@ static void empty_tx_init(void)
p = (void *)radio_pkt_empty_get(); p = (void *)radio_pkt_empty_get();
p->ll_id = PDU_DATA_LLID_DATA_CONTINUE; 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) #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
p->resv = 0U; p->resv = 0U;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */

View file

@ -109,6 +109,11 @@ enum df_cte_sampling_state {
DF_CTE_SAMPLING_DISABLED, 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 */ /* Parameters for reception of Constant Tone Extension in connected mode */
struct lll_df_conn_rx_params { struct lll_df_conn_rx_params {
uint8_t state : 2; 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 /* @brief Structure to store data required to prepare LE Connection IQ Report event or LE
* Connectionless IQ Report event. * 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 cte_conn_iq_report {
struct pdu_cte_info cte_info; struct pdu_cte_info cte_info;
@ -134,3 +136,14 @@ struct cte_conn_iq_report {
struct iq_sample sample[0]; 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];
};

View file

@ -34,9 +34,9 @@
#include "lll_adv.h" #include "lll_adv.h"
#include "lll/lll_adv_pdu.h" #include "lll/lll_adv_pdu.h"
#include "lll_scan.h" #include "lll_scan.h"
#include "lll/lll_df_types.h"
#include "lll_conn.h" #include "lll_conn.h"
#include "lll_filter.h" #include "lll_filter.h"
#include "lll/lll_df_types.h"
#if !defined(CONFIG_BT_LL_SW_LLCP_LEGACY) #if !defined(CONFIG_BT_LL_SW_LLCP_LEGACY)
#include "ll_sw/ull_tx_queue.h" #include "ll_sw/ull_tx_queue.h"

View file

@ -2058,7 +2058,7 @@ void ull_pdu_data_init(struct pdu_data *pdu_tx)
{ {
LL_ASSERT(pdu_tx); LL_ASSERT(pdu_tx);
pdu_tx->cp = PDU_DATA_CTE_PRESENT_BIT_DISABLED; pdu_tx->cp = false;
pdu_tx->rfu = 0U; pdu_tx->rfu = 0U;
#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
pdu_tx->resv = 0U; pdu_tx->resv = 0U;

View file

@ -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; return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
} }
if ((cte_type == BT_HCI_LE_AOD_CTE_1US || if ((cte_type == BT_HCI_LE_AOD_CTE_1US || cte_type == BT_HCI_LE_AOD_CTE_2US) &&
cte_type == BT_HCI_LE_AOD_CTE_2US) && (num_ant_ids < BT_HCI_LE_CTE_LEN_MIN ||
(num_ant_ids < LLL_DF_MIN_ANT_PATTERN_LEN || num_ant_ids > BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN || !ant_ids)) {
num_ant_ids > BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN ||
!ant_ids)) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL; 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 */ #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. /* @brief Function sets CTE transmission parameters for a connection.
* *
* @param handle Connection handle. * @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. * @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 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) { struct lll_df_conn_tx_cfg *df_tx_cfg;
if (!IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX)) { struct ll_conn *conn;
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
conn = ll_connected_get(handle);
if (!conn) {
return BT_HCI_ERR_UNKNOWN_CONN_ID;
} }
if (switch_pattern_len < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN || df_tx_cfg = &conn->lll.df_tx_cfg;
switch_pattern_len > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX || !ant_id) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}
}
if (df_tx_cfg->cte_rsp_en) {
return BT_HCI_ERR_CMD_DISALLOWED; 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 ((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;
}
}
/* 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) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
/* @brief Function sets CTE reception parameters for a connection. /* @brief Function sets CTE reception parameters for a connection.