diff mbox series

[BlueZ,2/9] bap: Drop union from bap_bcast_pa_req and add setups queue

Message ID 20241004123523.1012743-3-vlad.pruteanu@nxp.com
State New
Headers show
Series Allow syncing to multiple BISes from the same BIG | expand

Commit Message

Vlad Pruteanu Oct. 4, 2024, 12:35 p.m. UTC
For syncing to multiple BISes from the same BIG only one PA request
will be created and issued. But, for each stream (associated with a
BIS) there is a setup. To have all these setups in the PA request,
a queue of setups has been added to the structure. Thus, the old union
of setup and service has been removed.
---
 profiles/audio/bap.c | 43 +++++++++++++++++++++++++++++--------------
 1 file changed, 29 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index b48fe2c2f..94c7b7401 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -134,10 +134,8 @@  enum {
 struct bap_bcast_pa_req {
 	uint8_t type;
 	bool in_progress;
-	union {
-		struct btd_service *service;
-		struct bap_setup *setup;
-	} data;
+	struct btd_service *service;
+	struct queue *setups;
 	unsigned int io_id;	/* io_id for BIG Info watch */
 };
 
@@ -1021,7 +1019,10 @@  static int get_bis_from_stream(struct bt_bap_stream *stream)
 static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
 {
 	struct bap_bcast_pa_req *req = user_data;
-	struct bap_setup *setup = req->data.setup;
+	/* All confirm callbacks will arrive in the same order as the
+	 * setups were enqueued.
+	 */
+	struct bap_setup *setup = queue_pop_head(req->setups);
 	int fd;
 	struct bt_bap *bt_bap = bt_bap_stream_get_session(setup->stream);
 	struct btd_service *btd_service = bt_bap_get_user_data(bt_bap);
@@ -1041,6 +1042,7 @@  static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
 	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)) {
@@ -1273,7 +1275,7 @@  static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
 {
 	GError *err = NULL;
 	struct bap_bcast_pa_req *req = user_data;
-	struct bap_data *data = btd_service_get_user_data(req->data.service);
+	struct bap_data *data = btd_service_get_user_data(req->service);
 	struct bt_iso_base base;
 	struct bt_iso_qos qos;
 
@@ -1317,10 +1319,11 @@  static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
 	 */
 	parse_base(data, &base, &qos, bap_debug);
 
-	service_set_connecting(req->data.service);
+	service_set_connecting(req->service);
 
 	queue_remove(data->adapter->bcast_pa_requests, req);
 	req->io_id = 0;
+	queue_destroy(req->setups, NULL);
 	free(req);
 
 	return FALSE;
@@ -2291,6 +2294,9 @@  static void setup_accept_io_broadcast(struct bap_data *data,
 	struct bap_bcast_pa_req *req = new0(struct bap_bcast_pa_req, 1);
 	struct bap_adapter *adapter = data->adapter;
 
+	req->setups = queue_new();
+	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.
@@ -2306,7 +2312,6 @@  static void setup_accept_io_broadcast(struct bap_data *data,
 	 */
 	req->type = BAP_PA_BIG_SYNC_REQ;
 	req->in_progress = FALSE;
-	req->data.setup = setup;
 	queue_push_tail(adapter->bcast_pa_requests, req);
 }
 
@@ -3037,7 +3042,7 @@  static void bap_detached(struct bt_bap *bap, void *user_data)
 
 static int pa_sync(struct bap_bcast_pa_req *req)
 {
-	struct btd_service *service = req->data.service;
+	struct btd_service *service = req->service;
 	struct bap_data *data = btd_service_get_user_data(service);
 	GError *err = NULL;
 
@@ -3069,11 +3074,19 @@  static int pa_sync(struct bap_bcast_pa_req *req)
 	return 0;
 }
 
+static void setup_refresh_qos(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+
+	setup->qos = *bt_bap_stream_get_qos(setup->stream);
+}
+
 static void iso_do_big_sync(GIOChannel *io, void *user_data)
 {
 	GError *err = NULL;
 	struct bap_bcast_pa_req *req = user_data;
-	struct bap_setup *setup = req->data.setup;
+	/* Only the last setup in the queue will hold the listen io */
+	struct bap_setup *setup = queue_peek_tail(req->setups);
 	struct bt_bap *bt_bap = bt_bap_stream_get_session(setup->stream);
 	struct btd_service *btd_service = bt_bap_get_user_data(bt_bap);
 	struct bap_data *data = btd_service_get_user_data(btd_service);
@@ -3109,7 +3122,7 @@  static void iso_do_big_sync(GIOChannel *io, void *user_data)
 	iso_bc_addr.bc_num_bis = 1;
 
 	/* Refresh qos stored in setup */
-	setup->qos = *bt_bap_stream_get_qos(setup->stream);
+	queue_foreach(req->setups, setup_refresh_qos, NULL);
 	/* Set the user requested QOS */
 	memset(&qos, 0, sizeof(qos));
 	qos.bcast.big = setup->qos.bcast.big;
@@ -3151,7 +3164,8 @@  static void iso_do_big_sync(GIOChannel *io, void *user_data)
 static void pa_and_big_sync(struct bap_bcast_pa_req *req)
 {
 	GError *err = NULL;
-	struct bap_setup *setup = req->data.setup;
+	/* Only the last setup in the queue will hold the listen io */
+	struct bap_setup *setup = queue_peek_tail(req->setups);
 	struct bt_bap *bt_bap = bt_bap_stream_get_session(setup->stream);
 	struct btd_service *btd_service = bt_bap_get_user_data(bt_bap);
 	struct bap_data *bap_data = btd_service_get_user_data(btd_service);
@@ -3279,7 +3293,7 @@  static int bap_bcast_probe(struct btd_service *service)
 	req = new0(struct bap_bcast_pa_req, 1);
 	req->type = type;
 	req->in_progress = FALSE;
-	req->data.service = service;
+	req->service = service;
 	queue_push_tail(data->adapter->bcast_pa_requests, req);
 
 	return 0;
@@ -3289,7 +3303,7 @@  static bool match_service(const void *data, const void *match_data)
 {
 	struct bap_bcast_pa_req *req = (struct bap_bcast_pa_req *)data;
 
-	return req->data.service == match_data;
+	return req->service == match_data;
 }
 
 static void bap_bcast_remove(struct btd_service *service)
@@ -3317,6 +3331,7 @@  static void bap_bcast_remove(struct btd_service *service)
 		g_source_remove(req->io_id);
 		req->io_id = 0;
 	}
+	queue_destroy(req->setups, NULL);
 	free(req);
 
 	/* Notify the BASS plugin about the removed session. */