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 --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. */ -- 2.40.1