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:
parent
78962268c2
commit
40cdd65901
5 changed files with 61 additions and 18 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue