Commit cd470da2 authored by Morten Priess's avatar Morten Priess Committed by Carles Cufi
Browse files

Bluetooth: controller: Send disconnect complete when CIS is terminated



Previously the host would handle disconnecting associated CISes and
invoking callbacks when a host ACL conn was disconnected.

This responsibility has now been moved to the controller, which needs to
send a NODE_RX_TYPE_TERMINATE with the CIS handle for proper
disconnection in the host. This is in accordance with the spec.

As disconnect reason, the CIS uses the ACL reason, which is passed to
the host along with the handle.

Signed-off-by: default avatarMorten Priess <mtpr@oticon.com>
parent 57ca5298
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -1403,6 +1403,7 @@ void ll_rx_mem_release(void **node_rx)
#if defined(CONFIG_BT_CONN)
		case NODE_RX_TYPE_TERMINATE:
		{
			if (IS_ACL_HANDLE(rx_free->handle)) {
				struct ll_conn *conn;
				memq_link_t *link;

@@ -1416,6 +1417,7 @@ void ll_rx_mem_release(void **node_rx)

				ll_conn_release(conn);
			}
		}
		break;
#endif /* CONFIG_BT_CONN */

+10 −2
Original line number Diff line number Diff line
@@ -1961,8 +1961,15 @@ static void conn_cleanup_iso_cis_released_cb(struct ll_conn *conn)

	cis = ll_conn_iso_stream_get_by_acl(conn, NULL);
	if (cis) {
		struct node_rx_pdu *rx;
		uint8_t reason;

		/* More associated CISes - stop next */
		ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb);
		rx = (void *)&conn->llcp_terminate.node_rx;
		reason = *(uint8_t *)rx->pdu;

		ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb,
				      reason);
	} else {
		/* No more CISes associated with conn - finalize */
		conn_cleanup_finalize(conn);
@@ -2038,7 +2045,8 @@ static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
	cis = ll_conn_iso_stream_get_by_acl(conn, NULL);
	if (cis) {
		/* Stop CIS and defer cleanup to after teardown. */
		ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb);
		ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb,
				      reason);
		return;
	}
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
+16 −2
Original line number Diff line number Diff line
@@ -274,9 +274,11 @@ void ull_conn_iso_done(struct node_rx_event_done *done)
 * @param cis		 Pointer to connected ISO stream to stop
 * @param cis_relased_cb Callback to invoke when the CIS has been released.
 *                       NULL to ignore.
 * @param reason         Termination reason
 */
void ull_conn_iso_cis_stop(struct ll_conn_iso_stream *cis,
			   ll_iso_stream_released_cb_t cis_released_cb)
			   ll_iso_stream_released_cb_t cis_released_cb,
			   uint8_t reason)
{
	struct ll_conn_iso_group *cig;
	struct ull_hdr *hdr;
@@ -287,6 +289,7 @@ void ull_conn_iso_cis_stop(struct ll_conn_iso_stream *cis,
	}
	cis->teardown = 1;
	cis->released_cb = cis_released_cb;
	cis->terminate_reason = reason;

	/* Check ref count to determine if any pending LLL events in pipeline */
	cig = cis->group;
@@ -486,12 +489,23 @@ static void cis_disabled_cb(void *param)
		LL_ASSERT(cis);

		if (cis->teardown) {
			struct ll_conn *conn;
			ll_iso_stream_released_cb_t cis_released_cb;
			struct node_rx_pdu *node_terminate;
			struct ll_conn *conn;

			conn = ll_conn_get(cis->lll.acl_handle);
			cis_released_cb = cis->released_cb;

			/* Create and enqueue termination node */
			node_terminate = ull_pdu_rx_alloc();
			LL_ASSERT(node_terminate);
			node_terminate->hdr.handle = cis->lll.handle;
			node_terminate->hdr.type = NODE_RX_TYPE_TERMINATE;
			*((uint8_t *)node_terminate->pdu) = cis->terminate_reason;

			ll_rx_put(node_terminate->hdr.link, node_terminate);
			ll_rx_sched();

			ll_conn_iso_stream_release(cis);
			cig->lll.num_cis--;

+2 −1
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ struct ll_conn_iso_stream *ll_conn_iso_stream_get_by_group(struct ll_conn_iso_gr
void ull_conn_iso_done(struct node_rx_event_done *done);
void ull_conn_iso_cis_established(struct ll_conn_iso_stream *cis);
void ull_conn_iso_cis_stop(struct ll_conn_iso_stream *cis,
			   ll_iso_stream_released_cb_t cis_released_cb);
			   ll_iso_stream_released_cb_t cis_released_cb,
			   uint8_t reason);

void ull_conn_iso_resume_ticker_start(struct lll_event *resume_event,
				      uint16_t cis_handle,
+3 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ struct ll_conn_iso_stream {
	struct lll_conn_iso_stream lll;
	uint32_t sync_delay;
	uint8_t  cis_id;
	uint8_t  terminate_reason;
	struct ll_iso_datapath *datapath_in;
	struct ll_iso_datapath *datapath_out;
	uint32_t offset;          /* Offset of CIS from ACL event in us */
Loading