diff mbox series

[BlueZ,6/7] bap: Set the generated BASE on all setups from the same BIG

Message ID 20240201152835.196617-7-silviu.barbulescu@nxp.com (mailing list archive)
State Superseded
Headers show
Series Add support for multiple BISes on the bcast source | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/CheckPatch success CheckPatch PASS
tedd_an/GitLint success Gitlint PASS
tedd_an/IncrementalBuild success Incremental Build PASS

Commit Message

Silviu Florian Barbulescu Feb. 1, 2024, 3:28 p.m. UTC
Set the BASE generated in BlueZ on all setups from the same BIG,
and use defer to inform the kernel when to create the BIG.

---
 profiles/audio/bap.c | 69 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 57 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 7d7a3ce02..729860fbd 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -916,6 +916,35 @@  static void setup_free(void *data)
 	free(setup);
 }
 
+static void update_stream(void *data, void *user_data)
+{
+	struct bap_setup *setup = data;
+	struct bap_setup *data_setup = user_data;
+
+	if ((setup->stream != data_setup->stream) &&
+		(setup->qos.bcast.big == data_setup->qos.bcast.big)) {
+
+		if (setup->base)
+			util_iov_free(setup->base, 1);
+
+		setup->base = util_iov_dup(data_setup->base, 1);
+	}
+}
+
+static void update_setup(void *data, void *user_data)
+{
+	struct bap_ep *ep = data;
+	struct bap_setup *setup = user_data;
+
+	queue_foreach(ep->setups, update_stream, setup);
+}
+
+static void update_base(struct bap_setup *setup,
+			struct bap_data *data)
+{
+	queue_foreach(data->bcast, update_setup, setup);
+}
+
 static struct bap_ep *ep_register_bcast(struct bap_data *data,
 					struct bt_bap_pac *lpac,
 					struct bt_bap_pac *rpac);
@@ -975,6 +1004,10 @@  static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
 			setup->msg = dbus_message_ref(msg);
 		else {
 			setup->base = bt_bap_stream_get_base(setup->stream);
+			/* Set the generated BASE on all setups
+			 * from the same BIG.
+			 */
+			update_base(setup, ep->data);
 			setup->id = 0;
 			/* Create a new endpoint for a new BIS */
 			if (!ep_register_bcast(ep->data, ep->lpac, ep->rpac))
@@ -1847,7 +1880,7 @@  static void setup_connect_io(struct bap_data *data, struct bap_setup *setup,
 static void setup_connect_io_broadcast(struct bap_data *data,
 					struct bap_setup *setup,
 					struct bt_bap_stream *stream,
-					struct bt_iso_qos *qos)
+					struct bt_iso_qos *qos, int defer)
 {
 	struct btd_adapter *adapter = data->user_data;
 	GIOChannel *io = NULL;
@@ -1884,7 +1917,7 @@  static void setup_connect_io_broadcast(struct bap_data *data,
 			BT_IO_OPT_MODE, BT_IO_MODE_ISO,
 			BT_IO_OPT_QOS, qos,
 			BT_IO_OPT_BASE, &base,
-			BT_IO_OPT_DEFER_TIMEOUT, false,
+			BT_IO_OPT_DEFER_TIMEOUT, defer,
 			BT_IO_OPT_INVALID);
 
 	if (!io) {
@@ -2013,9 +2046,6 @@  static void setup_create_bcast_io(struct bap_data *data,
 
 	memset(&iso_qos, 0, sizeof(iso_qos));
 
-	if (!defer)
-		goto done;
-
 	iso_qos.bcast.big = setup->qos.bcast.big;
 	iso_qos.bcast.bis = setup->qos.bcast.bis;
 	iso_qos.bcast.sync_factor = setup->qos.bcast.sync_factor;
@@ -2032,9 +2062,10 @@  static void setup_create_bcast_io(struct bap_data *data,
 	iso_qos.bcast.timeout = setup->qos.bcast.timeout;
 	memcpy(&iso_qos.bcast.out, &setup->qos.bcast.io_qos,
 				sizeof(struct bt_iso_io_qos));
-done:
+
 	if (bt_bap_pac_get_type(setup->ep->lpac) == BT_BAP_BCAST_SOURCE)
-		setup_connect_io_broadcast(data, setup, stream, &iso_qos);
+		setup_connect_io_broadcast(data, setup, stream, &iso_qos,
+			defer);
 	else
 		setup_listen_io_broadcast(data, setup, stream, &iso_qos);
 }
@@ -2127,6 +2158,7 @@  static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
 {
 	struct bap_data *data = user_data;
 	struct bap_setup *setup;
+	bool defer = false;
 
 	DBG("stream %p: %s(%u) -> %s(%u)", stream,
 			bt_bap_stream_statestr(old_state), old_state,
@@ -2148,13 +2180,26 @@  static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
 		break;
 	case BT_BAP_STREAM_STATE_CONFIG:
 		if (setup && !setup->id) {
-			setup_create_io(data, setup, stream, true);
+			/* If the BIG ID was explicitly set, keep creating each
+			 * stream io with defer setup until all streams
+			 * belonging to the BIG have been configured
+			 * (i.e. transport acquire received on appropriate
+			 * transport). If the BIG id was left unset, just
+			 * create the io without defer, and a BIG with an
+			 * arbitrary handle will be created in kernel space.
+			 */
+			if (setup->qos.bcast.big != 0xFF)
+				defer = !bt_bap_test_bcast_streams_state(
+						setup->stream,
+						BT_BAP_STREAM_STATE_CONFIG);
+
+			setup_create_io(data, setup, stream, defer);
 			if (!setup->io) {
 				error("Unable to create io");
-				if (old_state != BT_BAP_STREAM_STATE_RELEASING)
-					bt_bap_stream_release(stream, NULL,
-								NULL);
-				return;
+				if (old_state !=
+					BT_BAP_STREAM_STATE_RELEASING)
+					bt_bap_stream_release(stream,
+							NULL, NULL);
 			}
 		}
 		break;