[PATCH BlueZ 1/1] bass: Register bap attached/detached callbacks

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

 



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





[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