From 6b324122e7cfa3099b7fe98190cc0e5fb25b3730 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 5 Oct 2022 14:18:25 +0200 Subject: [PATCH] Bluetooth: controller: fix CIS REQ event generation and rejection Check LE event mask state as well as host controlled feature mask state and reject CIS request accordingly. Release pre-allocated ISO resources on rejection of request Signed-off-by: Erik Brockhoff --- subsys/bluetooth/controller/hci/hci.c | 17 ++++++----- .../bluetooth/controller/ll_sw/ull_llcp_cc.c | 2 ++ .../controller/ll_sw/ull_peripheral_iso.c | 30 ++++++++++++++++++- .../ll_sw/ull_peripheral_iso_internal.h | 1 + .../mock_ctrl/src/ull_peripheral_iso.c | 4 +++ 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index f152d49a7d7..25ac6f6ceaa 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -4097,14 +4097,6 @@ static void le_cis_request(struct pdu_data *pdu_data, struct node_rx_conn_iso_req *req; void *node; - if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) || - !(le_event_mask & BT_EVT_MASK_LE_CIS_REQ)) { - return; - } - - sep = meta_evt(buf, BT_HCI_EVT_LE_CIS_REQ, sizeof(*sep)); - sep->acl_handle = sys_cpu_to_le16(node_rx->hdr.handle); - /* Check for pdu field being aligned before accessing CIS established * event. */ @@ -4112,6 +4104,15 @@ static void le_cis_request(struct pdu_data *pdu_data, LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab)); req = node; + if (!(ll_feat_get() & BIT64(BT_LE_FEAT_BIT_ISO_CHANNELS)) || + !(event_mask & BT_EVT_MASK_LE_META_EVENT) || + !(le_event_mask & BT_EVT_MASK_LE_CIS_REQ)) { + ll_cis_reject(req->cis_handle, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); + return; + } + + sep = meta_evt(buf, BT_HCI_EVT_LE_CIS_REQ, sizeof(*sep)); + sep->acl_handle = sys_cpu_to_le16(node_rx->hdr.handle); sep->cis_handle = sys_cpu_to_le16(req->cis_handle); sep->cig_id = req->cig_id; sep->cis_id = req->cis_id; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index d3ccbff008d..1dbc35d7b88 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -463,6 +463,8 @@ static void rp_cc_state_wait_reply(struct ll_conn *conn, struct proc_ctx *ctx, u ctx->data.cis_create.error = BT_HCI_ERR_CONN_ACCEPT_TIMEOUT; /* If timeout is hit, fall through and reject */ case RP_CC_EVT_CIS_REQ_REJECT: + /* CIS Request is rejected, so clean up CIG/CIS acquisitions */ + ull_peripheral_iso_release(ctx->data.cis_create.cis_handle); /* Continue procedure in next prepare run */ ctx->state = RP_CC_STATE_WAIT_TX_REJECT_IND; break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index 3a8855a646b..289e1dfe93a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -123,7 +123,7 @@ uint8_t ll_cis_reject(uint16_t handle, uint8_t reason) struct ll_conn *acl_conn = ll_cis_get_acl_awaiting_reply(handle, &status); if (acl_conn) { - /* Accept request */ + /* Reject request */ ull_cp_cc_reject(acl_conn, reason); } #endif @@ -141,6 +141,28 @@ int ull_peripheral_iso_reset(void) return 0; } +/* Use this function to release CIS/CIG resources on an aborted CIS setup + * ie if CIS setup is 'cancelled' after call to ull_peripheral_iso_acquire() + * because of a rejection of the CIS request + */ +void ull_peripheral_iso_release(uint16_t cis_handle) +{ + struct ll_conn_iso_stream *cis; + struct ll_conn_iso_group *cig; + + cis = ll_conn_iso_stream_get(cis_handle); + LL_ASSERT(cis); + + cig = cis->group; + + ll_conn_iso_stream_release(cis); + cig->lll.num_cis--; + + if (!cig->lll.num_cis) { + ll_conn_iso_group_release(cig); + } +} + uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, struct pdu_data_llctrl_cis_req *req, uint16_t *cis_handle) @@ -202,6 +224,12 @@ uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, /* Acquire new CIS */ cis = ll_conn_iso_stream_acquire(); if (cis == NULL) { + if (!cig->lll.num_cis) { + /* No CIS's in CIG, so this was just allocated + * so release as we can't use it + */ + ll_conn_iso_group_release(cig); + } /* No space for new CIS */ return BT_HCI_ERR_INSUFFICIENT_RESOURCES; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h index b0670d54729..b4db867e83a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso_internal.h @@ -8,6 +8,7 @@ int ull_peripheral_iso_init(void); int ull_peripheral_iso_reset(void); +void ull_peripheral_iso_release(uint16_t cis_handle); uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, struct pdu_data_llctrl_cis_req *req, uint16_t *cis_handle); diff --git a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c index 08d345f6855..1ddbe88c9e8 100644 --- a/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c +++ b/tests/bluetooth/controller/mock_ctrl/src/ull_peripheral_iso.c @@ -39,6 +39,10 @@ #include "ull_conn_iso_internal.h" #include "lll_peripheral_iso.h" +void ull_peripheral_iso_release(uint16_t cis_handle) +{ +} + uint8_t ull_peripheral_iso_acquire(struct ll_conn *acl, struct pdu_data_llctrl_cis_req *req, uint16_t *cis_handle)