Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion subsys/bluetooth/controller/hci/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -7908,7 +7908,11 @@ static void le_unknown_rsp(struct pdu_data *pdu_data, uint16_t handle,
le_remote_feat_complete(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE,
NULL, handle, buf);
break;

#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
case PDU_DATA_LLCTRL_TYPE_CTE_REQ:
le_df_cte_req_failed(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, handle, buf);
break;
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
default:
BT_WARN("type: 0x%02x", pdu_data->llctrl.unknown_rsp.type);
break;
Expand Down
10 changes: 10 additions & 0 deletions subsys/bluetooth/controller/ll_sw/ull_conn_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,17 @@ struct llcp_struct {
struct {
uint8_t sent;
uint8_t valid;
/*
* Stores features supported by peer device. The content of the member may be
* verified when feature exchange procedure has completed, valid member is set to 1.
*/
uint64_t features_peer;
/*
* Stores features common for two connected devices. Before feature exchange
* procedure is completed, the member stores information about all features
* supported by local device. After completion of the procedure, the feature set
* may be limited to features that are common.
*/
uint64_t features_used;
} fex;

Expand Down
64 changes: 28 additions & 36 deletions subsys/bluetooth/controller/ll_sw/ull_df.c
Original file line number Diff line number Diff line change
Expand Up @@ -1166,51 +1166,43 @@ uint8_t ll_df_set_conn_cte_req_enable(uint16_t handle, uint8_t enable,
ull_cp_cte_req_set_disable(conn);

return BT_HCI_ERR_SUCCESS;
} else {
if (!conn->lll.df_rx_cfg.is_initialized) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
}

if (conn->llcp.cte_req.is_enabled) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
if (!conn->lll.df_rx_cfg.is_initialized) {
return BT_HCI_ERR_CMD_DISALLOWED;
}

if (conn->llcp.cte_req.is_enabled) {
return BT_HCI_ERR_CMD_DISALLOWED;
}

#if defined(CONFIG_BT_CTLR_PHY)
/* CTE request may be enabled only in case the receiver PHY is not CODED */
if (conn->lll.phy_rx == PHY_CODED) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* CTE request may be enabled only in case the receiver PHY is not CODED */
if (conn->lll.phy_rx == PHY_CODED) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
#endif /* CONFIG_BT_CTLR_PHY */

if (cte_request_interval != 0 && cte_request_interval < conn->lll.latency) {
return BT_HCI_ERR_CMD_DISALLOWED;
}

if (requested_cte_length < BT_HCI_LE_CTE_LEN_MIN ||
requested_cte_length > BT_HCI_LE_CTE_LEN_MAX) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}

if (requested_cte_type != BT_HCI_LE_AOA_CTE &&
requested_cte_type != BT_HCI_LE_AOD_CTE_1US &&
requested_cte_type != BT_HCI_LE_AOD_CTE_2US) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}
if (cte_request_interval != 0 && cte_request_interval < conn->lll.latency) {
return BT_HCI_ERR_CMD_DISALLOWED;
}

/* If controller is aware of features supported by peer device then check
* whether required features are enabled.
*/
if (conn->llcp.fex.valid &&
(!(conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP)))) {
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
}
if (requested_cte_length < BT_HCI_LE_CTE_LEN_MIN ||
requested_cte_length > BT_HCI_LE_CTE_LEN_MAX) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}

conn->llcp.cte_req.is_enabled = 1U;
conn->llcp.cte_req.req_interval = cte_request_interval;
conn->llcp.cte_req.cte_type = requested_cte_type;
conn->llcp.cte_req.min_cte_len = requested_cte_length;
if (requested_cte_type != BT_HCI_LE_AOA_CTE &&
requested_cte_type != BT_HCI_LE_AOD_CTE_1US &&
requested_cte_type != BT_HCI_LE_AOD_CTE_2US) {
return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
}

conn->llcp.cte_req.is_enabled = 1U;
conn->llcp.cte_req.req_interval = cte_request_interval;
conn->llcp.cte_req.cte_type = requested_cte_type;
conn->llcp.cte_req.min_cte_len = requested_cte_length;

return ull_cp_cte_req(conn, requested_cte_length, requested_cte_type);
}
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
Expand Down
13 changes: 13 additions & 0 deletions subsys/bluetooth/controller/ll_sw/ull_llcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,19 @@ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_ty
{
struct proc_ctx *ctx;

/* If Controller gained, awareness:
* - by Feature Exchange control procedure that peer device does not support CTE response,
* - by reception LL_UNKNOWN_RSP with unknown type LL_CTE_REQ that peer device does not
* recognize CTE request,
* then response to Host that CTE request enable command is not possible due to unsupported
* remote feature.
*/
if ((conn->llcp.fex.valid &&
(!(conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_CONN_CTE_RESP)))) ||
(!conn->llcp.fex.valid && !feature_cte_req(conn))) {
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
}

/* The request may be started by periodic CTE request procedure, so it skips earlier
* verification of PHY. In case the PHY has changed to CODE the request should be stopped.
*/
Expand Down
41 changes: 27 additions & 14 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, stru
llcp_ntf_encode_cte_req(pdu);
}
break;
case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
llcp_ntf_encode_unknown_rsp(ctx, pdu);
break;
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
llcp_ntf_encode_reject_ext_ind(ctx, pdu);
break;
Expand All @@ -228,6 +231,17 @@ static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, stru
}
}

static void lp_comm_ntf_cte_req_tx(struct ll_conn *conn, struct proc_ctx *ctx)
{
if (llcp_ntf_alloc_is_available()) {
lp_comm_ntf(conn, ctx);
ull_cp_cte_req_set_disable(conn);
ctx->state = LP_COMMON_STATE_IDLE;
} else {
ctx->state = LP_COMMON_STATE_WAIT_NTF;
}
}

static void lp_comm_complete_cte_req(struct ll_conn *conn, struct proc_ctx *ctx)
{
if (conn->llcp.cte_req.is_enabled) {
Expand All @@ -238,22 +252,19 @@ static void lp_comm_complete_cte_req(struct ll_conn *conn, struct proc_ctx *ctx)
conn->llcp.cte_req.req_interval;
}
ctx->state = LP_COMMON_STATE_IDLE;
} else if (llcp_ntf_alloc_is_available()) {
lp_comm_ntf(conn, ctx);
ull_cp_cte_req_set_disable(conn);
ctx->state = LP_COMMON_STATE_IDLE;
} else {
ctx->state = LP_COMMON_STATE_WAIT_NTF;
lp_comm_ntf_cte_req_tx(conn, ctx);
}
} else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND &&
ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) {
if (llcp_ntf_alloc_is_available()) {
lp_comm_ntf(conn, ctx);
ull_cp_cte_req_set_disable(conn);
ctx->state = LP_COMMON_STATE_IDLE;
} else {
ctx->state = LP_COMMON_STATE_WAIT_NTF;
}
ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) {
lp_comm_ntf_cte_req_tx(conn, ctx);
} else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP &&
ctx->unknown_response.type == PDU_DATA_LLCTRL_TYPE_CTE_REQ) {
/* CTE response is unsupported in peer, so disable locally for this
* connection
*/
feature_unmask_features(conn, LL_FEAT_BIT_CONNECTION_CTE_REQ);
lp_comm_ntf_cte_req_tx(conn, ctx);
} else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNUSED) {
/* This path is related with handling disable the CTE REQ when PHY
* has been changed to CODED PHY. BT 5.3 Core Vol 4 Part E 7.8.85
Expand All @@ -263,7 +274,9 @@ static void lp_comm_complete_cte_req(struct ll_conn *conn, struct proc_ctx *ctx)
ull_cp_cte_req_set_disable(conn);
ctx->state = LP_COMMON_STATE_IDLE;
} else {
/* Illegal response opcode */
/* Illegal response opcode, internally changes state to
* LP_COMMON_STATE_IDLE
*/
lp_comm_terminate_invalid_pdu(conn, ctx);
}
} else {
Expand Down
13 changes: 9 additions & 4 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ static inline bool feature_phy_coded(struct ll_conn *conn)
#endif
}

static inline bool feature_cte_req(struct ll_conn *conn)
{
#if defined(CONFIG_BT_CTLR_DF) && defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
return conn->llcp.fex.features_used & LL_FEAT_BIT_CONNECTION_CTE_REQ;
#else
return 0;
#endif
}

/*
* for asymmetric features we can check either if we support it
* or if the peer supports it
Expand Down Expand Up @@ -148,10 +157,6 @@ static inline bool feature_peer_smi_tx(struct ll_conn *conn)
* per_adv
* pwr_class1
* min_chann
* CTE_req
* CTE_rsp
* CTE_tx
* CTE_rx
* ant_sw_CTE_tx
* ant_sw_CTE_rx
* tone_ext
Expand Down
Loading