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 <erbr@oticon.com>
This commit is contained in:
Erik Brockhoff 2022-10-05 14:18:25 +02:00 committed by Fabio Baltieri
commit 6b324122e7
5 changed files with 45 additions and 9 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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)