From dbf86b03592060fc20b3de56df06efd87217e54a Mon Sep 17 00:00:00 2001 From: Piotr Pryga Date: Fri, 28 Jan 2022 22:58:34 +0100 Subject: [PATCH] Bluetooth: Controller: Add CTE REQ disable when change PHY to CODED Accodring to BT 5.3 Core Vol 4, Part E section 7.8.85 the CTE request procedure has to be disabled as if Host issued the HCI_LE_Connection- CTE_Request_Enable with enable property set to 0. It means a Controller should automaticall disable the procedure. There were no handling of this part of specification. Signed-off-by: Piotr Pryga --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 19 ++++++++- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 33 ++++++++++----- .../controller/ll_sw/ull_llcp_common.c | 40 +++++++++++++++---- 3 files changed, 72 insertions(+), 20 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 00bfe5f48a6..b459c544c74 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1654,9 +1654,24 @@ void ull_conn_done(struct node_rx_event_done *done) if (conn->llcp.cte_req.req_expire > elapsed_event) { conn->llcp.cte_req.req_expire -= elapsed_event; } else { + uint8_t err; + conn->llcp.cte_req.req_expire = 0U; - ull_cp_cte_req(conn, conn->llcp.cte_req.min_cte_len, - conn->llcp.cte_req.cte_type); + + err = ull_cp_cte_req(conn, conn->llcp.cte_req.min_cte_len, + conn->llcp.cte_req.cte_type); + + if (err == BT_HCI_ERR_CMD_DISALLOWED) { + /* Conditions has changed e.g. PHY was changed to CODED. + * New CTE REQ is not possible. Disable the periodic requests. + * + * If the CTE REQ is in active state, let it complete and disable + * in regular control procedure way. + */ + if (!conn->llcp.cte_req.is_active) { + ull_cp_cte_req_set_disable(conn); + } + } } } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 923e70fd2cf..0a39d9b038f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -903,19 +903,30 @@ uint8_t ull_cp_cte_req(struct ll_conn *conn, uint8_t min_cte_len, uint8_t cte_ty { struct proc_ctx *ctx; - ctx = llcp_create_local_procedure(PROC_CTE_REQ); - if (!ctx) { - return BT_HCI_ERR_CMD_DISALLOWED; + /* 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. + */ +#if defined(CONFIG_BT_CTLR_PHY) + if (conn->lll.phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ + ctx = llcp_create_local_procedure(PROC_CTE_REQ); + if (!ctx) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + + ctx->data.cte_req.min_len = min_cte_len; + ctx->data.cte_req.type = cte_type; + + conn->llcp.cte_req.is_active = 1U; + + llcp_lr_enqueue(conn, ctx); + + return BT_HCI_ERR_SUCCESS; } - ctx->data.cte_req.min_len = min_cte_len; - ctx->data.cte_req.type = cte_type; - - conn->llcp.cte_req.is_active = 1U; - - llcp_lr_enqueue(conn, ctx); - - return BT_HCI_ERR_SUCCESS; + return BT_HCI_ERR_CMD_DISALLOWED; } void ull_cp_cte_req_set_disable(struct ll_conn *conn) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index a77b525b644..b8e8a7b0811 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -353,14 +353,22 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t conn->llcp.cte_req.req_interval != 0U) { conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval; } else { - conn->llcp.cte_req.is_enabled = 0U; + /* TODO: add wait for notification buffer */ lp_comm_ntf(conn, ctx); ull_cp_cte_req_set_disable(conn); } } else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND && ctx->reject_ext_ind.reject_opcode == PDU_DATA_LLCTRL_TYPE_CTE_REQ) { + /* TODO: add wait for notification buffer */ lp_comm_ntf(conn, ctx); - conn->llcp.cte_req.is_enabled = 0U; + ull_cp_cte_req_set_disable(conn); + } 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 + * says CTE REQ has to be automatically disabled as if it had been requested + * by Host. There is no notification send to Host. + */ + ull_cp_cte_req_set_disable(conn); } llcp_rr_set_paused_cmd(conn, PROC_NONE); @@ -467,12 +475,30 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ) case PROC_CTE_REQ: - if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || - (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { - ctx->state = LP_COMMON_STATE_WAIT_TX; +#if defined(CONFIG_BT_CTLR_PHY) + if (conn->lll.phy_rx != PHY_CODED) { +#else + if (1) { +#endif /* CONFIG_BT_CTLR_PHY */ + if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx) || + (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { + ctx->state = LP_COMMON_STATE_WAIT_TX; + } else { + lp_comm_tx(conn, ctx); + ctx->state = LP_COMMON_STATE_WAIT_RX; + } } else { - lp_comm_tx(conn, ctx); - ctx->state = LP_COMMON_STATE_WAIT_RX; + /* The PHY was changed to CODED when the request was waiting in a local + * request queue. + * + * Use of pair: proc PROC_CTE_REQ and rx_opcode PDU_DATA_LLCTRL_TYPE_UNUSED + * to complete the procedure before sending a request to peer. + * This is a special complete execution path to disable the procedure + * due to change of RX PHY to CODED. + */ + ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED; + ctx->state = LP_COMMON_STATE_IDLE; + llcp_lr_complete(conn); } break; #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */