This removes the bass_bcast_probe and bass_bcast_remove APIs, in order to decouple the BASS and BAP plugins. Instead, since the BASS Server (BAP Scan Delegator) implementation needs to reference the bap session, BASS registers bap attached/detached callbacks with shared/bap. - After receiving a request from a Broadcast Assistant, the BASS Server creates a device for the Broadcaster and adds the UUID to probe. - The service is probed inside the BAP plugin, where a new bt_bap session is attached. The service is set as user data beforehand. - The bt_bap session is notified in the BASS bap_attached callback. The reference to the service is accessible from the user data. - The BASS Server takes ownership for the service by setting its user data. This way, short-lived PA sync will be skipped inside BAP, and the BASS Server will handle long-lived PA sync and stream configuration. - When the bt_bap session is removed, it will be notified in the bap_detached callback. --- profiles/audio/bap.c | 53 ++++++++++++++++++++++++++++++------------- profiles/audio/bass.c | 46 +++++++++++++++++++++---------------- profiles/audio/bass.h | 5 +--- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 77df9455a..c503f250c 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -4,7 +4,7 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2022 Intel Corporation. All rights reserved. - * Copyright 2023-2024 NXP + * Copyright 2023-2025 NXP * * */ @@ -192,7 +192,7 @@ static void bap_data_free(struct bap_data *data) if (data->io_id) g_source_remove(data->io_id); - if (data->service) { + if (data->service && btd_service_get_user_data(data->service) == data) { btd_service_set_user_data(data->service, NULL); bt_bap_set_user_data(data->bap, NULL); } @@ -2751,7 +2751,7 @@ static void bap_data_add(struct bap_data *data) queue_push_tail(sessions, data); - if (data->service) + if (data->service && !btd_service_get_user_data(data->service)) btd_service_set_user_data(data->service, data); } @@ -3064,7 +3064,6 @@ static int bap_bcast_probe(struct btd_service *service) struct btd_adapter *adapter = device_get_adapter(device); struct btd_gatt_database *database = btd_adapter_get_database(adapter); struct bap_data *data; - int ret = 0; if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) { error("BAP requires ISO Socket which is not enabled"); @@ -3084,6 +3083,8 @@ static int bap_bcast_probe(struct btd_service *service) } data->bcast_snks = queue_new(); + bt_bap_set_user_data(data->bap, service); + if (!bt_bap_attach(data->bap, NULL)) { error("BAP unable to attach"); return -EINVAL; @@ -3098,13 +3099,18 @@ static int bap_bcast_probe(struct btd_service *service) data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast, pac_removed_broadcast, data, NULL); - bt_bap_set_user_data(data->bap, service); - - if (bass_bcast_probe(service, &ret)) - /* Return if probed device was handled inside BASS. */ - return ret; - - pa_sync(data); + if (btd_service_get_user_data(service) == data) + /* If the reference to the bap session has been set as service + * user data, it means the broadcaster was autonomously probed. + * Thus, the Broadcast Sink needs to create short lived PA sync + * to discover streams. + * + * If the service user data does not match the bap session, it + * means that the broadcaster was probed via a Broadcast + * Assistant from the BASS plugin, where stream discovery and + * configuration will also be handled. + */ + pa_sync(data); return 0; } @@ -3118,15 +3124,12 @@ static void bap_bcast_remove(struct btd_service *service) ba2str(device_get_address(device), addr); DBG("%s", addr); - data = btd_service_get_user_data(service); + data = queue_find(sessions, match_device, device); if (!data) { error("BAP service not handled by profile"); return; } - /* Notify the BASS plugin about the removed session. */ - bass_bcast_remove(device); - bap_data_remove(data); bass_remove_stream(device); @@ -3225,6 +3228,24 @@ static int bap_disconnect(struct btd_service *service) return 0; } +static int bap_bcast_disconnect(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct bap_data *data; + + data = queue_find(sessions, match_device, device); + if (!data) { + error("BAP service not handled by profile"); + return -EINVAL; + } + + bt_bap_detach(data->bap); + + btd_service_disconnecting_complete(service, 0); + + return 0; +} + static int bap_adapter_probe(struct btd_profile *p, struct btd_adapter *adapter) { struct btd_gatt_database *database = btd_adapter_get_database(adapter); @@ -3307,7 +3328,7 @@ static struct btd_profile bap_bcast_profile = { .remote_uuid = BCAAS_UUID_STR, .device_probe = bap_bcast_probe, .device_remove = bap_bcast_remove, - .disconnect = bap_disconnect, + .disconnect = bap_bcast_disconnect, .auto_connect = false, .experimental = true, }; diff --git a/profiles/audio/bass.c b/profiles/audio/bass.c index 3a37d6711..6c84fa1c3 100644 --- a/profiles/audio/bass.c +++ b/profiles/audio/bass.c @@ -3,7 +3,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright 2023-2024 NXP + * Copyright 2023-2025 NXP * */ @@ -557,26 +557,27 @@ static void confirm_cb(GIOChannel *io, void *user_data) dg->io_id = g_io_add_watch(io, G_IO_OUT, big_info_cb, dg); } -bool bass_bcast_probe(struct btd_service *service, int *ret) +static void bap_attached(struct bt_bap *bap, void *user_data) { + struct btd_service *service = bt_bap_get_user_data(bap); struct btd_device *device = btd_service_get_device(service); struct btd_adapter *adapter = device_get_adapter(device); struct bass_delegator *dg; GError *err = NULL; + DBG("%p", bap); + dg = queue_find(delegators, delegator_match_device, device); if (!dg) /* Only probe devices added via Broadcast Assistants */ - return false; + return; - if (dg->service) { + if (dg->service) /* Service has already been probed */ - *ret = -EINVAL; - return true; - } + return; dg->service = service; - dg->bap = bap_get_session(device); + dg->bap = bap; dg->io = bt_io_listen(NULL, confirm_cb, dg, NULL, &err, @@ -593,11 +594,12 @@ bool bass_bcast_probe(struct btd_service *service, int *ret) BT_IO_OPT_INVALID); if (!dg->io) { error("%s", err->message); - *ret = -err->code; g_error_free(err); + return; } - return true; + /* Take ownership for the service by setting the user data. */ + btd_service_set_user_data(service, dg); } static void setup_free(void *data) @@ -610,22 +612,23 @@ static void setup_free(void *data) util_iov_free(setup->meta, 1); util_iov_free(setup->config, 1); - if (setup->stream) { - uint8_t state = bt_bap_stream_get_state(setup->stream); - - if (state == BT_BAP_STREAM_STATE_STREAMING) - bt_bass_clear_bis_sync(setup->dg->src, - stream_get_bis(setup->stream)); - } + /* Clear bis index from the bis sync bitmask, if it + * has been previously set. + */ + bt_bass_clear_bis_sync(setup->dg->src, setup->bis); } -bool bass_bcast_remove(struct btd_device *device) +static void bap_detached(struct bt_bap *bap, void *user_data) { + struct btd_service *service = bt_bap_get_user_data(bap); + struct btd_device *device = btd_service_get_device(service); struct bass_delegator *dg; + DBG("%p", bap); + dg = queue_remove_if(delegators, delegator_match_device, device); if (!dg) - return false; + return; DBG("%p", dg); @@ -657,7 +660,7 @@ bool bass_bcast_remove(struct btd_device *device) free(dg); - return true; + btd_service_set_user_data(service, NULL); } static void assistant_set_state(struct bass_assistant *assistant, @@ -1649,6 +1652,7 @@ static struct btd_profile bass_service = { }; static unsigned int bass_id; +static unsigned int bap_id; static int bass_init(void) { @@ -1659,6 +1663,7 @@ static int bass_init(void) return err; bass_id = bt_bass_register(bass_attached, bass_detached, NULL); + bap_id = bt_bap_register(bap_attached, bap_detached, NULL); return 0; } @@ -1667,6 +1672,7 @@ static void bass_exit(void) { btd_profile_unregister(&bass_service); bt_bass_unregister(bass_id); + bt_bap_unregister(bap_id); } BLUETOOTH_PLUGIN_DEFINE(bass, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, diff --git a/profiles/audio/bass.h b/profiles/audio/bass.h index 678532168..99b755259 100644 --- a/profiles/audio/bass.h +++ b/profiles/audio/bass.h @@ -3,7 +3,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * */ @@ -12,9 +12,6 @@ void bass_add_stream(struct btd_device *device, struct iovec *meta, uint8_t sgrp, uint8_t bis); void bass_remove_stream(struct btd_device *device); -bool bass_bcast_probe(struct btd_service *service, int *ret); -bool bass_bcast_remove(struct btd_device *device); - typedef void (*bt_bass_bcode_func_t)(void *user_data, int err); void bass_req_bcode(struct bt_bap_stream *stream, -- 2.43.0