|
59 | 59 |
|
60 | 60 | #include "ull_iso_internal.h" |
61 | 61 | #include "ull_conn_iso_internal.h" |
| 62 | +#include "ull_central_iso_internal.h" |
62 | 63 | #include "ull_peripheral_iso_internal.h" |
63 | 64 | #include "lll/lll_adv_types.h" |
64 | 65 | #include "lll_adv.h" |
@@ -438,43 +439,44 @@ uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason) |
438 | 439 |
|
439 | 440 | /* Sanity-check instance to make sure it's created but not connected */ |
440 | 441 | if (cis->group && cis->lll.handle == handle && !cis->established) { |
441 | | - if (cis->group->state == CIG_STATE_CONFIGURABLE) { |
442 | | - /* Disallow if CIG is still in configurable state */ |
443 | | - return BT_HCI_ERR_CMD_DISALLOWED; |
| 442 | + struct ll_conn_iso_group *cig = cis->group; |
444 | 443 |
|
445 | | - } else if (cis->group->state == CIG_STATE_INITIATING) { |
446 | | - conn = ll_connected_get(cis->lll.acl_handle); |
447 | | - LL_ASSERT_DBG(conn != NULL); |
| 444 | + conn = ll_connected_get(cis->lll.acl_handle); |
448 | 445 |
|
449 | | - /* CIS is not yet established - try to cancel procedure */ |
450 | | - if (ull_cp_cc_cancel(conn)) { |
451 | | - /* Successfully canceled - complete disconnect */ |
452 | | - struct node_rx_pdu *node_terminate; |
| 446 | + if (conn == NULL || !ull_lp_cc_is_enqueued(conn, cis)) { |
| 447 | + /* Disallow if CIS is not created yet or terminated */ |
| 448 | + return BT_HCI_ERR_CMD_DISALLOWED; |
| 449 | + } |
453 | 450 |
|
454 | | - node_terminate = ull_pdu_rx_alloc(); |
455 | | - LL_ASSERT_ERR(node_terminate); |
| 451 | + /* CIS is not yet established - try to cancel procedure */ |
| 452 | + if (ull_cp_cc_cancel(conn, cis)) { |
| 453 | + /* Successfully canceled - complete disconnect */ |
| 454 | + struct node_rx_pdu *node_terminate; |
456 | 455 |
|
457 | | - node_terminate->hdr.handle = handle; |
458 | | - node_terminate->hdr.type = NODE_RX_TYPE_TERMINATE; |
459 | | - *((uint8_t *)node_terminate->pdu) = |
460 | | - BT_HCI_ERR_LOCALHOST_TERM_CONN; |
| 456 | + node_terminate = &cis->node_rx_terminate.rx; |
461 | 457 |
|
462 | | - ll_rx_put_sched(node_terminate->hdr.link, |
463 | | - node_terminate); |
| 458 | + node_terminate->hdr.handle = handle; |
| 459 | + node_terminate->hdr.type = NODE_RX_TYPE_TERMINATE; |
| 460 | + *((uint8_t *)node_terminate->pdu) = |
| 461 | + BT_HCI_ERR_LOCALHOST_TERM_CONN; |
464 | 462 |
|
465 | | - /* We're no longer initiating a connection */ |
466 | | - cis->group->state = CIG_STATE_CONFIGURABLE; |
| 463 | + ll_rx_put_sched(node_terminate->hdr.link, |
| 464 | + node_terminate); |
467 | 465 |
|
468 | | - /* This is now a successful disconnection */ |
469 | | - return BT_HCI_ERR_SUCCESS; |
| 466 | + /* We're no longer initiating a connection */ |
| 467 | + if (ull_central_iso_all_cises_terminated(cig)) { |
| 468 | + cig->state = CIG_STATE_INACTIVE; |
470 | 469 | } |
471 | 470 |
|
472 | | - /* Procedure could not be canceled in the current |
473 | | - * state - let it run its course and enqueue a |
474 | | - * terminate procedure. |
475 | | - */ |
476 | | - return ull_cp_cis_terminate(conn, cis, reason); |
| 471 | + /* This is now a successful disconnection */ |
| 472 | + return BT_HCI_ERR_SUCCESS; |
477 | 473 | } |
| 474 | + |
| 475 | + /* Procedure could not be canceled in the current |
| 476 | + * state - let it run its course and enqueue a |
| 477 | + * terminate procedure. |
| 478 | + */ |
| 479 | + return ull_cp_cis_terminate(conn, cis, reason); |
478 | 480 | } |
479 | 481 | #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */ |
480 | 482 | /* Disallow if CIS is not connected */ |
@@ -1897,8 +1899,54 @@ static void conn_cleanup_finalize(struct ll_conn *conn) |
1897 | 1899 | struct lll_conn *lll = &conn->lll; |
1898 | 1900 | uint32_t ticker_status; |
1899 | 1901 |
|
| 1902 | + if ((IS_ENABLED(CONFIG_BT_CTLR_PERIPHERAL_ISO) || |
| 1903 | + IS_ENABLED(CONFIG_BT_CTLR_CENTRAL_ISO)) && |
| 1904 | + ull_cp_cc_is_active(conn)) { |
| 1905 | + /* CIS creation procedure active, notify LLCP */ |
| 1906 | + ull_cp_cc_acl_disconnect(conn); |
| 1907 | + } |
| 1908 | + |
| 1909 | + /* Set LLCP state - flushes control procedures */ |
1900 | 1910 | ull_cp_state_set(conn, ULL_CP_DISCONNECTED); |
1901 | 1911 |
|
| 1912 | +#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || defined(CONFIG_BT_CTLR_CENTRAL_ISO) |
| 1913 | + /* Find and clean non-established, allocated CISes associated with this ACL conn */ |
| 1914 | + for (uint8_t handle = LL_CIS_HANDLE_BASE; handle <= LL_CIS_HANDLE_LAST; handle++) { |
| 1915 | + struct ll_conn_iso_stream *cis; |
| 1916 | + struct ll_conn_iso_group *cig; |
| 1917 | + |
| 1918 | + cis = ll_conn_iso_stream_get(handle); |
| 1919 | + cig = cis->group; |
| 1920 | + if (cig != NULL && cig->lll.num_cis != 0U && |
| 1921 | + cis->lll.acl_handle == conn->lll.handle) { |
| 1922 | + if (IS_PERIPHERAL(cig)) { |
| 1923 | + /* Remove data paths associated with this CIS for both directions. |
| 1924 | + * Disable them one at a time to make sure both are removed, even if |
| 1925 | + * only one is set. |
| 1926 | + * Note: This only applies for peripherals, for centrals an explicit |
| 1927 | + * command is required to clean up a CIG and associated CISes. |
| 1928 | + * See e.g. BT Core v5.4, Vol 4, Part E, Section 7.8.100 |
| 1929 | + */ |
| 1930 | + ll_remove_iso_path(handle, BIT(BT_HCI_DATAPATH_DIR_HOST_TO_CTLR)); |
| 1931 | + ll_remove_iso_path(handle, BIT(BT_HCI_DATAPATH_DIR_CTLR_TO_HOST)); |
| 1932 | + |
| 1933 | + ll_conn_iso_stream_release(cis); |
| 1934 | + cig->lll.num_cis--; |
| 1935 | + |
| 1936 | + if (cig->lll.num_cis == 0U) { |
| 1937 | + /* No more streams in the group - release group */ |
| 1938 | + ll_conn_iso_group_release(cig); |
| 1939 | + } |
| 1940 | + } else if (IS_CENTRAL(cig) && cig->state == CIG_STATE_INITIATING && |
| 1941 | + ull_central_iso_all_cises_terminated(cig)) { |
| 1942 | + |
| 1943 | + /* We're no longer initiating a connection */ |
| 1944 | + cig->state = CIG_STATE_INACTIVE; |
| 1945 | + } |
| 1946 | + } |
| 1947 | + } |
| 1948 | +#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */ |
| 1949 | + |
1902 | 1950 | /* Update tx buffer queue handling */ |
1903 | 1951 | #if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE) |
1904 | 1952 | ull_cp_update_tx_buffer_queue(conn); |
|
0 commit comments