Bluetooth: Controller: llcp: add missing handling LL_UNKNOWN in CTE llcp

There was missing handling of LL_UNKNOWN_RSP in CTE request control
procedure.In case there is a pending CTE request and peer responses
with LL_UNKNOWN_RSP then Host should be notified with HCI_LE_CTE_-
Request_Failed event. The pending CTE request procedure should be
completed.
Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2022-04-29 07:59:31 +02:00 committed by Carles Cufí
commit 40cdd65901
5 changed files with 61 additions and 18 deletions

View file

@ -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, le_remote_feat_complete(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE,
NULL, handle, buf); NULL, handle, buf);
break; 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: default:
BT_WARN("type: 0x%02x", pdu_data->llctrl.unknown_rsp.type); BT_WARN("type: 0x%02x", pdu_data->llctrl.unknown_rsp.type);
break; break;

View file

@ -404,7 +404,17 @@ struct llcp_struct {
struct { struct {
uint8_t sent; uint8_t sent;
uint8_t valid; 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; 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; uint64_t features_used;
} fex; } fex;

View file

@ -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; 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 /* 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. * verification of PHY. In case the PHY has changed to CODE the request should be stopped.
*/ */

View file

@ -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); llcp_ntf_encode_cte_req(pdu);
} }
break; break;
case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
llcp_ntf_encode_unknown_rsp(ctx, pdu);
break;
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND: case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
llcp_ntf_encode_reject_ext_ind(ctx, pdu); llcp_ntf_encode_reject_ext_ind(ctx, pdu);
break; break;
@ -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) static void lp_comm_complete_cte_req(struct ll_conn *conn, struct proc_ctx *ctx)
{ {
if (conn->llcp.cte_req.is_enabled) { if (conn->llcp.cte_req.is_enabled) {
@ -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; conn->llcp.cte_req.req_interval;
} }
ctx->state = LP_COMMON_STATE_IDLE; 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 { } 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 && } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND &&
ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) {
if (llcp_ntf_alloc_is_available()) { lp_comm_ntf_cte_req_tx(conn, ctx);
lp_comm_ntf(conn, ctx); } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP &&
ull_cp_cte_req_set_disable(conn); ctx->unknown_response.type == PDU_DATA_LLCTRL_TYPE_CTE_REQ) {
ctx->state = LP_COMMON_STATE_IDLE; /* CTE response is unsupported in peer, so disable locally for this
} else { * connection
ctx->state = LP_COMMON_STATE_WAIT_NTF; */
} 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) { } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNUSED) {
/* This path is related with handling disable the CTE REQ when PHY /* 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 * has been changed to CODED PHY. BT 5.3 Core Vol 4 Part E 7.8.85

View file

@ -117,6 +117,15 @@ static inline bool feature_phy_coded(struct ll_conn *conn)
#endif #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 * for asymmetric features we can check either if we support it
* or if the peer supports it * or if the peer supports it
@ -148,10 +157,6 @@ static inline bool feature_peer_smi_tx(struct ll_conn *conn)
* per_adv * per_adv
* pwr_class1 * pwr_class1
* min_chann * min_chann
* CTE_req
* CTE_rsp
* CTE_tx
* CTE_rx
* ant_sw_CTE_tx * ant_sw_CTE_tx
* ant_sw_CTE_rx * ant_sw_CTE_rx
* tone_ext * tone_ext