Bluetooth: host: Add host API to run conn CTE TX params set

Add host API to allow execution of HCI_LE_Set_Connection_CTE_Transmit_-
Parameters HCI command.

The commit also provides a refactored version of hci_df_set_conn_cte_tx-
_param function. The function was aligned to other hci_df_XXX functions
structure with separated parameters validation and preparation of
command object before it is send to controller.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
Co-authored-by: Emil Gydesen <Thalley@users.noreply.github.com>
This commit is contained in:
Piotr Pryga 2021-12-27 22:05:59 +01:00 committed by Carles Cufí
commit 87448f99fe
2 changed files with 118 additions and 36 deletions

View file

@ -142,6 +142,18 @@ struct bt_df_conn_iq_samples_report {
/** Pinter to IQ samples data. */ /** Pinter to IQ samples data. */
struct bt_hci_le_iq_sample const *sample; struct bt_hci_le_iq_sample const *sample;
}; };
/** Constant Tone Extension parameters for CTE transmission in connected mode. */
struct bt_df_conn_cte_tx_param {
/**
* Bitfield with allowed CTE types (@ref bt_df_cte_type. All enum members may be used except
* BT_DF_CTE_TYPE_NONE).
*/
uint8_t cte_types;
/** Number of antenna switch pattern. */
uint8_t num_ant_ids;
/** Antenna switch pattern. */
const uint8_t *ant_ids;
};
/** /**
* @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.
@ -218,6 +230,22 @@ int bt_df_conn_cte_rx_enable(struct bt_conn *conn, const struct bt_df_conn_cte_r
*/ */
int bt_df_conn_cte_rx_disable(struct bt_conn *conn); int bt_df_conn_cte_rx_disable(struct bt_conn *conn);
/**
* @brief Set Constant Tone Extension transmission parameters for a connection.
*
* The function is available if @kconfig{CONFIG_BT_DF_CONNECTION_CTE_TX} is enabled.
*
* @note If neither BT_DF_CTE_TYPE_AOD_1US or BT_DF_CTE_TYPE_AOD_2US are set
* in the bitfield, then the bt_df_conn_cte_tx_param.num_ant_ids and
* bt_df_conn_cte_tx_param.ant_ids parameters will be ignored.
*
* @param conn Connection object.
* @param params CTE transmission parameters.
*
* @return Zero in case of success, other value in case of failure.
*/
int bt_df_set_conn_cte_tx_param(struct bt_conn *conn, const struct bt_df_conn_cte_tx_param *params);
/** /**
* @brief Enable Constant Tone Extension response procedure for a connection. * @brief Enable Constant Tone Extension response procedure for a connection.
* *

View file

@ -389,62 +389,90 @@ void hci_df_prepare_connectionless_iq_report(struct net_buf *buf,
} }
#endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */ #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) #if defined(CONFIG_BT_DF_CONNECTION_CTE_TX)
/* @brief Function sets CTE parameters for connection object static bool validate_conn_cte_tx_params(const struct bt_df_conn_cte_tx_param *params)
{
if (!(params->cte_types & BT_DF_CTE_TYPE_ALL)) {
return false;
}
/* If AoD is not enabled, ant_ids are ignored by controller:
* BT Core spec 5.2 Vol 4, Part E sec. 7.8.84.
*/
if ((params->cte_types & BT_DF_CTE_TYPE_AOD_1US ||
params->cte_types & BT_DF_CTE_TYPE_AOD_1US) &&
(params->num_ant_ids < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN ||
params->num_ant_ids > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX || !params->ant_ids ||
!BT_FEAT_LE_ANT_SWITCH_TX_AOD(bt_dev.le.features))) {
return false;
}
return true;
}
static void prepare_conn_cte_tx_params_cmd(struct net_buf *buf, const struct bt_conn *conn,
const struct bt_df_conn_cte_tx_param *params)
{
struct bt_hci_cp_le_set_conn_cte_tx_params *cp;
uint8_t *ant_ids;
cp = net_buf_add(buf, sizeof(*cp));
(void)memset(cp, 0, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->cte_types = params->cte_types;
if (params->cte_types & (BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US)) {
cp->switch_pattern_len = params->num_ant_ids;
ant_ids = net_buf_add(buf, cp->switch_pattern_len);
(void)memcpy(ant_ids, params->ant_ids, cp->switch_pattern_len);
} else {
cp->switch_pattern_len = 0U;
}
}
/**
* @brief Function sets CTE parameters for connection object
* *
* @param[in] cte_types Allowed response CTE types * @param conn Connection object
* @param[in] num_ant_id Number of available antenna identification * @param params CTE transmission parameters.
* patterns in @p ant_id array.
* @param[in] ant_id Array with antenna identification patterns.
* *
* @return Zero in case of success, other value in case of failure. * @return Zero in case of success, other value in case of failure.
*/ */
static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, uint8_t cte_types, static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn,
uint8_t num_ant_id, uint8_t *ant_id) const struct bt_df_conn_cte_tx_param *params)
{ {
__ASSERT_NO_MSG(conn);
__ASSERT_NO_MSG(cte_types != 0);
struct bt_hci_cp_le_set_conn_cte_tx_params *cp;
struct bt_hci_rp_le_set_conn_cte_tx_params *rp; struct bt_hci_rp_le_set_conn_cte_tx_params *rp;
struct bt_hci_cmd_state_set state;
struct net_buf *buf, *rsp; struct net_buf *buf, *rsp;
uint8_t num_ant_ids;
int err; int err;
/* If AoD is not enabled, ant_ids are ignored by controller: /* If AoD is not enabled, ant_ids are ignored by controller:
* BT Core spec 5.2 Vol 4, Part E sec. 7.8.84. * BT Core spec 5.2 Vol 4, Part E sec. 7.8.84.
*/ */
if (cte_types & BT_HCI_LE_AOD_CTE_RSP_1US || if (!validate_conn_cte_tx_params(params)) {
cte_types & BT_HCI_LE_AOD_CTE_RSP_2US) { return -EINVAL;
if (num_ant_id < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN ||
num_ant_id > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX ||
!ant_id) {
return -EINVAL;
}
__ASSERT_NO_MSG((sizeof(*cp) + num_ant_id) < UINT8_MAX);
} }
num_ant_ids = ((params->cte_types & (BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US)) ?
params->num_ant_ids : 0);
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS, buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS,
sizeof(*cp) + num_ant_id); sizeof(struct bt_hci_cp_le_set_conn_cte_tx_params) + num_ant_ids);
if (!buf) { if (!buf) {
return -ENOBUFS; return -ENOBUFS;
} }
cp = net_buf_add(buf, sizeof(*cp)); prepare_conn_cte_tx_params_cmd(buf, conn, params);
cp->handle = sys_cpu_to_le16(conn->handle);
cp->cte_types = cte_types;
if (num_ant_id) { /* CTE transmission parameters must be set only once for connection lifetime, hence the
uint8_t *dest_ant_id = net_buf_add(buf, num_ant_id); * flag BT_CONN_CTE_TX_PARAMS_SET is always set to true and never set to false.
*/
bt_hci_cmd_state_set_init(buf, &state, conn->flags, BT_CONN_CTE_TX_PARAMS_SET, true);
memcpy(dest_ant_id, ant_id, num_ant_id); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS, buf, &rsp);
cp->switch_pattern_len = num_ant_id;
} else {
cp->switch_pattern_len = 0;
}
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS,
buf, &rsp);
if (err) { if (err) {
return err; return err;
} }
@ -458,7 +486,7 @@ static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, uint8_t cte_types,
return err; return err;
} }
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */ #endif /* CONFIG_BT_DF_CONNECTION_CTE_TX */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX) #if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)
static void prepare_conn_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_conn *conn, static void prepare_conn_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_conn *conn,
@ -812,6 +840,32 @@ int bt_df_conn_cte_rx_disable(struct bt_conn *conn)
} }
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */ #endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_TX)
int bt_df_set_conn_cte_tx_param(struct bt_conn *conn, const struct bt_df_conn_cte_tx_param *params)
{
CHECKIF(!conn) {
return -EINVAL;
}
CHECKIF(!params) {
return -EINVAL;
}
if (conn->state != BT_CONN_CONNECTED) {
BT_ERR("not connected!");
return -ENOTCONN;
}
if (atomic_test_bit(conn->flags, BT_CONN_CTE_RSP_ENABLED)) {
BT_WARN("CTE response procedure is enabled");
return -EINVAL;
}
return hci_df_set_conn_cte_tx_param(conn, params);
}
#endif /* CONFIG_BT_DF_CONNECTION_CTE_TX */
#if defined(CONFIG_BT_DF_CONNECTION_CTE_RSP) #if defined(CONFIG_BT_DF_CONNECTION_CTE_RSP)
static int bt_df_set_conn_cte_rsp_enable(struct bt_conn *conn, bool enable) static int bt_df_set_conn_cte_rsp_enable(struct bt_conn *conn, bool enable)
{ {