diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 531f620ca43..66a3534bf24 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1524,12 +1524,13 @@ static void le_big_create_sync(struct net_buf *buf, struct net_buf **evt) } -static void le_big_terminate_sync(struct net_buf *buf, struct net_buf **evt) +static void le_big_terminate_sync(struct net_buf *buf, struct net_buf **evt, + void **node_rx) { struct bt_hci_cp_le_big_terminate_sync *cmd = (void *)buf->data; uint8_t status; - status = ll_big_sync_terminate(cmd->big_handle); + status = ll_big_sync_terminate(cmd->big_handle, node_rx); *evt = cmd_complete_status(status); } @@ -3243,7 +3244,7 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, break; case BT_OCF(BT_HCI_OP_LE_BIG_TERMINATE_SYNC): - le_big_terminate_sync(cmd, evt); + le_big_terminate_sync(cmd, evt, node_rx); break; #endif /* CONFIG_BT_CTLR_SYNC_ISO */ #endif /* CONFIG_BT_OBSERVER */ diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 07aa010d7c1..7ef0d47f3b7 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -147,7 +147,7 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, uint8_t encryption, uint8_t *bcode, uint8_t mse, uint16_t sync_timeout, uint8_t num_bis, uint8_t *bis); -uint8_t ll_big_sync_terminate(uint8_t big_handle); +uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx); #else /* !CONFIG_BT_CTLR_ADV_EXT */ uint8_t ll_scan_enable(uint8_t enable); #endif /* !CONFIG_BT_CTLR_ADV_EXT */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index b3429189b03..6ea1b35f21e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -114,11 +114,13 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, return BT_HCI_ERR_SUCCESS; } -uint8_t ll_big_sync_terminate(uint8_t big_handle) +uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx) { - memq_link_t *big_sync_estab; - memq_link_t *big_sync_lost; struct ll_sync_iso *sync_iso; + struct node_rx_pdu *node_rx; + memq_link_t *link_sync_estab; + memq_link_t *link_sync_lost; + struct ll_sync_set *sync; int err; sync_iso = ull_sync_iso_get(big_handle); @@ -126,19 +128,53 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle) return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; } - err = ull_ticker_stop_with_mark( - TICKER_ID_SCAN_SYNC_ISO_BASE + big_handle, - sync_iso, &sync_iso->lll); + sync = sync_iso->sync; + if (sync) { + struct node_rx_sync_iso *se; + + if (sync->iso.sync_iso != sync_iso) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + sync->iso.sync_iso = NULL; + sync_iso->sync = NULL; + + node_rx = (void *)sync->iso.node_rx_estab; + link_sync_estab = node_rx->hdr.link; + link_sync_lost = sync_iso->node_rx_lost.hdr.link; + + ll_rx_link_release(link_sync_lost); + ll_rx_link_release(link_sync_estab); + ll_rx_release(node_rx); + + node_rx = (void *)&sync_iso->node_rx_lost; + node_rx->hdr.type = NODE_RX_TYPE_SYNC_ISO; + node_rx->hdr.handle = 0xffff; + + /* NOTE: struct node_rx_lost has uint8_t member following the + * struct node_rx_hdr to store the reason. + */ + se = (void *)node_rx->pdu; + se->status = BT_HCI_ERR_OP_CANCELLED_BY_HOST; + + /* NOTE: Since NODE_RX_TYPE_SYNC_ISO is only generated from ULL + * context, pass ULL context as parameter. + */ + node_rx->hdr.rx_ftr.param = sync_iso; + + *rx = node_rx; + + return BT_HCI_ERR_SUCCESS; + } + + err = ull_ticker_stop_with_mark((TICKER_ID_SCAN_SYNC_ISO_BASE + + big_handle), sync_iso, &sync_iso->lll); LL_ASSERT(err == 0 || err == -EALREADY); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; } - big_sync_lost = sync_iso->node_rx_lost.link; - ll_rx_link_release(big_sync_lost); - - big_sync_estab = sync_iso->node_rx_estab.link; - ll_rx_link_release(big_sync_estab); + link_sync_lost = sync_iso->node_rx_lost.hdr.link; + ll_rx_link_release(link_sync_lost); ull_sync_iso_release(sync_iso); @@ -198,17 +234,17 @@ void ull_sync_iso_setup(struct ll_sync_iso *sync_iso, struct node_rx_hdr *node_rx, struct pdu_biginfo *biginfo) { - uint16_t handle; - struct node_rx_sync_iso *se; - uint16_t interval; - uint32_t interval_us; uint32_t ticks_slot_overhead; + struct node_rx_sync_iso *se; uint32_t ticks_slot_offset; - uint32_t ret; + struct lll_sync_iso *lll; struct node_rx_ftr *ftr; uint32_t sync_offset_us; struct node_rx_pdu *rx; - struct lll_sync_iso *lll; + uint32_t interval_us; + uint16_t interval; + uint16_t handle; + uint32_t ret; lll = &sync_iso->lll; handle = ull_sync_iso_handle_get(sync_iso); @@ -218,7 +254,7 @@ void ull_sync_iso_setup(struct ll_sync_iso *sync_iso, /* TODO: Populate LLL with information from the BIGINFO */ - rx = (void *)sync_iso->node_rx_estab.link; + rx = (void *)sync_iso->sync->iso.node_rx_estab; rx->hdr.type = NODE_RX_TYPE_SYNC_ISO; rx->hdr.handle = handle; rx->hdr.rx_ftr.param = sync_iso; diff --git a/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c b/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c index 33c6456c0b3..92174836c6c 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c +++ b/tests/bluetooth/bsim_bt/bsim_test_iso/src/main.c @@ -294,6 +294,7 @@ static void test_iso_recv_main(void) uint8_t encryption = 0; uint8_t bcode[16] = { 0 }; uint16_t sync_timeout = 0; + struct node_rx_hdr *node_rx; printk("Creating BIG...\n"); err = ll_big_sync_create(big_handle, sync->handle, encryption, bcode, @@ -307,7 +308,7 @@ static void test_iso_recv_main(void) k_sleep(K_MSEC(5000)); printk("Terminating BIG...\n"); - err = ll_big_sync_terminate(big_handle); + err = ll_big_sync_terminate(big_handle, (void **)&node_rx); if (err) { FAIL("Could not terminate BIG sync: %d\n", err); return;