[PATCH BlueZ 7/9] bap: Handle req to sync to multiple BISes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When syncing to multiple BISes from the same BIG, an acquire call
will be issued by the Audio Server for each BIS. These need to be
merged so that the controller will receive only one req which
includes all the BISes.

When a call to create a BIG sync request is received, a check is
performed to find if any streams are in RELEASING or PENDING
state. If there are, they are part of multiple BISes sync and the
audio server was not reacquired them yet. Otherwise, the request
is allocated and the num_bis and bc_bis are set, based on streams
in ENABLING state.
---
 profiles/audio/bap.c | 101 +++++++++++++++++++++++++++++--------------
 1 file changed, 68 insertions(+), 33 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 666d3324e..7251d8759 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -1031,21 +1031,22 @@ static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
 
 	DBG("BIG Sync completed");
 
-	if (setup->io) {
-		g_io_channel_unref(setup->io);
-		g_io_channel_shutdown(setup->io, TRUE, NULL);
-		setup->io = NULL;
+	req->iso_bc_addr.bc_num_bis--;
+	if (req->iso_bc_addr.bc_num_bis == 0) {
+		if (setup->io) {
+			g_io_channel_unref(setup->io);
+			g_io_channel_shutdown(setup->io, TRUE, NULL);
+			setup->io = NULL;
+		}
+		/* This device is no longer needed */
+		btd_service_connecting_complete(bap_data->service, 0);
+		queue_remove(bap_data->adapter->bcast_pa_requests, req);
+		queue_destroy(req->setups, NULL);
+		free(req);
 	}
 
-	/* This device is no longer needed */
-	btd_service_connecting_complete(bap_data->service, 0);
-
 	fd = g_io_channel_unix_get_fd(io);
 
-	queue_remove(bap_data->adapter->bcast_pa_requests, req);
-	queue_destroy(req->setups, NULL);
-	free(req);
-
 	if (bt_bap_stream_set_io(setup->stream, fd)) {
 		bt_bap_stream_start(setup->stream, NULL, NULL);
 		g_io_channel_set_close_on_unref(io, FALSE);
@@ -2289,38 +2290,72 @@ static gboolean pa_idle_timer(gpointer user_data)
 	return TRUE;
 }
 
+static void find_pending_req(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	bool *pending = user_data;
+
+	if (bt_bap_stream_get_state(setup->stream) ==
+		BT_BAP_STREAM_STATE_PENDING ||
+		bt_bap_stream_get_state(setup->stream) ==
+		BT_BAP_STREAM_STATE_RELEASING)
+		*pending = TRUE;
+}
+
+static void count_pending(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	struct bap_bcast_pa_req *req = user_data;
+
+	if (bt_bap_stream_get_state(setup->stream) ==
+				BT_BAP_STREAM_STATE_ENABLING) {
+		req->iso_bc_addr.bc_bis[req->iso_bc_addr.bc_num_bis] =
+				get_bis_from_stream(setup->stream);
+		req->iso_bc_addr.bc_num_bis++;
+		DBG("pushing setup for BIS %d",
+				get_bis_from_stream(setup->stream));
+		queue_push_tail(req->setups, setup);
+	}
+}
+
 static void setup_accept_io_broadcast(struct bap_data *data,
 					struct bap_setup *setup)
 {
-	struct bap_bcast_pa_req *req = new0(struct bap_bcast_pa_req, 1);
+	struct bap_bcast_pa_req *req;
+	bool pending = FALSE;
 	struct bap_adapter *adapter = data->adapter;
 
-	req->setups = queue_new();
-	req->iso_bc_addr.bc_bdaddr_type =
+	/* Search for requests to sync to the same BIG.
+	 * If any, merge the current request with it.
+	 */
+	queue_foreach(data->bcast_snks, find_pending_req, &pending);
+	if (!pending) {
+		req = new0(struct bap_bcast_pa_req, 1);
+		req->iso_bc_addr.bc_bdaddr_type =
 			btd_device_get_bdaddr_type(data->device);
-	memcpy(&req->iso_bc_addr.bc_bdaddr,
+		memcpy(&req->iso_bc_addr.bc_bdaddr,
 			device_get_address(data->device), sizeof(bdaddr_t));
-	req->iso_bc_addr.bc_bis[req->iso_bc_addr.bc_num_bis] =
-			get_bis_from_stream(setup->stream);
-	req->iso_bc_addr.bc_num_bis++;
-	queue_push_tail(req->setups, setup);
-
-	/* Timer could be stopped if all other requests were treated.
-	 * Check the state of the timer and turn it on so that this request
-	 * can also be treated.
-	 */
-	if (adapter->pa_timer_id == 0)
-		adapter->pa_timer_id = g_timeout_add_seconds(PA_IDLE_TIMEOUT,
+		req->setups = queue_new();
+		queue_foreach(data->bcast_snks, count_pending, req);
+
+		/* Timer could be stopped if all other requests were treated.
+		 * Check the state of the timer and turn it on so that this
+		 * request can also be treated.
+		 */
+		if (adapter->pa_timer_id == 0)
+			adapter->pa_timer_id = g_timeout_add_seconds(
+								PA_IDLE_TIMEOUT,
 								pa_idle_timer,
 								adapter);
 
-	/* Add this request to the PA queue.
-	 * We don't need to check the queue here, as we cannot have
-	 * BAP_PA_BIG_SYNC_REQ before a short PA (BAP_PA_SHORT_REQ)
-	 */
-	req->type = BAP_PA_BIG_SYNC_REQ;
-	req->in_progress = FALSE;
-	queue_push_tail(adapter->bcast_pa_requests, req);
+		/* Add this request to the PA queue.
+		 * We don't need to check the queue here, as we cannot have
+		 * BAP_PA_BIG_SYNC_REQ before a short PA (BAP_PA_SHORT_REQ)
+		 */
+		req->type = BAP_PA_BIG_SYNC_REQ;
+		req->in_progress = FALSE;
+		queue_push_tail(adapter->bcast_pa_requests, req);
+	}
 }
 
 static void setup_create_ucast_io(struct bap_data *data,
-- 
2.40.1





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux