diff mbox series

[BlueZ,v2,3/7] bap: Rework BASE parsing

Message ID 20241120102601.38415-4-iulia.tanasescu@nxp.com
State New
Headers show
Series [BlueZ,v2,1/7] shared/bap: Add helper to parse BASE | expand

Commit Message

Iulia Tanasescu Nov. 20, 2024, 10:25 a.m. UTC
This replaces the internal parse_base with bt_bap_parse_base from
shared/bap. A bis callback is added to handle parsed streams.

The Broadcast Assistant implementation in the BASS plugin is also
updated to use bap qos instead of iso qos, since the BISes are
now parsed along with bap qos structure.
---
 profiles/audio/bap.c  | 207 ++++++++----------------------------------
 profiles/audio/bass.c |  30 ++++--
 profiles/audio/bass.h |   2 +-
 3 files changed, 61 insertions(+), 178 deletions(-)
diff mbox series

Patch

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 6acb0895c..2a194d709 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -1034,13 +1034,6 @@  static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
 	}
 }
 
-static void print_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
-		void *user_data)
-{
-	util_debug(user_data, NULL, "CC #%zu: l:%u t:%u", i, l, t);
-	util_hexdump(' ', v, l, user_data, NULL);
-}
-
 void bap_qos_to_iso_qos(struct bt_bap_qos *bap_qos,
 				struct bt_iso_qos *iso_qos)
 {
@@ -1093,15 +1086,16 @@  void bap_iso_qos_to_bap_qos(struct bt_iso_qos *iso_qos,
 }
 
 static void create_stream_for_bis(struct bap_data *bap_data,
-		struct bt_bap_pac *lpac, struct bt_iso_qos *qos,
+		struct bt_bap_pac *lpac, struct bt_bap_qos *qos,
 		struct iovec *caps, struct iovec *meta, char *path)
 {
 	struct bap_setup *setup;
 
 	setup = setup_new(NULL);
+	setup->qos = *qos;
 
-	/* Create BAP QoS structure */
-	bap_iso_qos_to_bap_qos(qos, &setup->qos);
+	/* Create an internal copy for bcode */
+	setup->qos.bcast.bcode = util_iov_dup(qos->bcast.bcode, 1);
 
 	queue_push_tail(bap_data->bcast_snks, setup);
 
@@ -1116,170 +1110,37 @@  static void create_stream_for_bis(struct bap_data *bap_data,
 			NULL, NULL);
 }
 
-static bool parse_base(struct bap_data *bap_data, struct bt_iso_base *base,
-		struct bt_iso_qos *qos, util_debug_func_t func)
+static void bis_handler(uint8_t bis, uint8_t sgrp, struct iovec *caps,
+	struct iovec *meta, struct bt_bap_qos *qos, void *user_data)
 {
-	struct iovec iov = {
-		.iov_base = base->base,
-		.iov_len = base->base_len,
-	};
-	uint32_t pres_delay;
-	uint8_t num_subgroups;
-	bool ret = true;
-
-	util_debug(func, NULL, "BASE len: %ld", iov.iov_len);
-
-	if (!util_iov_pull_le24(&iov, &pres_delay))
-		return false;
-	util_debug(func, NULL, "PresentationDelay: %d", pres_delay);
-
-	if (!util_iov_pull_u8(&iov, &num_subgroups))
-		return false;
-	util_debug(func, NULL, "Number of Subgroups: %d", num_subgroups);
-
-	/* Loop subgroups */
-	for (int idx = 0; idx < num_subgroups; idx++) {
-		uint8_t num_bis;
-		struct bt_bap_codec codec;
-		struct iovec *l2_caps = NULL;
-		struct iovec *meta = NULL;
-
-		util_debug(func, NULL, "Subgroup #%d", idx);
-
-		if (!util_iov_pull_u8(&iov, &num_bis)) {
-			ret = false;
-			goto fail;
-		}
-		util_debug(func, NULL, "Number of BISes: %d", num_bis);
-
-		memcpy(&codec,
-				util_iov_pull_mem(&iov,
-						sizeof(struct bt_bap_codec)),
-				sizeof(struct bt_bap_codec));
-		util_debug(func, NULL, "Codec: ID %d CID 0x%2.2x VID 0x%2.2x",
-				codec.id, codec.cid, codec.vid);
-
-		/* Level 2 */
-		/* Read Codec Specific Configuration */
-		l2_caps = new0(struct iovec, 1);
-		if (!util_iov_pull_u8(&iov, (void *)&l2_caps->iov_len)) {
-			ret = false;
-			goto group_fail;
-		}
-
-		util_iov_memcpy(l2_caps, util_iov_pull_mem(&iov,
-				l2_caps->iov_len),
-				l2_caps->iov_len);
-
-		/* Print Codec Specific Configuration */
-		util_debug(func, NULL, "CC len: %ld", l2_caps->iov_len);
-		util_ltv_foreach(l2_caps->iov_base, l2_caps->iov_len, NULL,
-				print_ltv, func);
-
-		/* Read Metadata */
-		meta = new0(struct iovec, 1);
-		if (!util_iov_pull_u8(&iov, (void *)&meta->iov_len)) {
-			ret = false;
-			goto group_fail;
-		}
-
-		util_iov_memcpy(meta,
-				util_iov_pull_mem(&iov, meta->iov_len),
-				meta->iov_len);
-
-		/* Print Metadata */
-		util_debug(func, NULL, "Metadata len: %i",
-				(uint8_t)meta->iov_len);
-		util_hexdump(' ', meta->iov_base, meta->iov_len, func, NULL);
-
-		/* Level 3 */
-		for (; num_bis; num_bis--) {
-			uint8_t bis_index;
-			struct iovec *l3_caps;
-			struct iovec *merged_caps;
-			struct bt_bap_pac *matched_lpac;
-			char *path;
-			int err;
-
-			if (!util_iov_pull_u8(&iov, &bis_index)) {
-				ret = false;
-				goto group_fail;
-			}
-
-			util_debug(func, NULL, "BIS #%d", bis_index);
-			err = asprintf(&path, "%s/bis%d",
-					device_get_path(bap_data->device),
-					bis_index);
-			if (err < 0)
-				continue;
-
-			/* Read Codec Specific Configuration */
-			l3_caps = new0(struct iovec, 1);
-			if (!util_iov_pull_u8(&iov,
-						(void *)&l3_caps->iov_len)) {
-				free(l3_caps);
-				free(path);
-				ret = false;
-				goto group_fail;
-			}
-
-			util_iov_memcpy(l3_caps,
-					util_iov_pull_mem(&iov,
-							l3_caps->iov_len),
-					l3_caps->iov_len);
-
-			/* Print Codec Specific Configuration */
-			util_debug(func, NULL, "CC Len: %d",
-					(uint8_t)l3_caps->iov_len);
-			util_ltv_foreach(l3_caps->iov_base,
-					l3_caps->iov_len, NULL, print_ltv,
-					func);
-
-			merged_caps = bt_bap_merge_caps(l2_caps, l3_caps);
-			if (!merged_caps) {
-				free(path);
-				continue;
-			}
-
-			bass_add_stream(bap_data->device, meta, merged_caps,
-						qos, idx, bis_index);
-
-			if (!bass_check_bis(bap_data->device, bis_index)) {
-				/* If this Broadcast Sink is acting as a Scan
-				 * Delegator, only attempt to create streams
-				 * for the BISes required by the peer Broadcast
-				 * Assistant.
-				 */
-				continue;
-			}
+	struct bap_data *data = user_data;
+	struct bt_bap_pac *lpac;
+	char *path;
 
-			/* Check if this BIS matches any local PAC */
-			bt_bap_verify_bis(bap_data->bap, bis_index,
-					merged_caps, &matched_lpac);
+	bass_add_stream(data->device, meta, caps, qos, sgrp, bis);
 
-			if (matched_lpac == NULL) {
-				free(path);
-				continue;
-			}
+	if (!bass_check_bis(data->device, bis))
+		/* If this Broadcast Sink is acting as a Scan
+		 * Delegator, only attempt to create streams
+		 * for the BISes required by the peer Broadcast
+		 * Assistant.
+		 */
+		return;
 
-			create_stream_for_bis(bap_data, matched_lpac, qos,
-					merged_caps, meta, path);
-		}
+	/* Check if this BIS matches any local PAC */
+	bt_bap_verify_bis(data->bap, bis,
+			caps, &lpac);
 
-group_fail:
-		if (l2_caps != NULL)
-			free(l2_caps);
-		if (meta != NULL)
-			free(meta);
-		if (!ret)
-			break;
-	}
+	if (!lpac)
+		return;
 
-fail:
-	if (!ret)
-		util_debug(func, NULL, "Unable to parse Base");
+	if (asprintf(&path, "%s/bis%d",
+			device_get_path(data->device),
+			bis) < 0)
+		return;
 
-	return ret;
+	create_stream_for_bis(data, lpac, qos,
+			caps, meta, path);
 }
 
 static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
@@ -1290,6 +1151,8 @@  static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
 	struct bap_data *data = btd_service_get_user_data(req->data.service);
 	struct bt_iso_base base;
 	struct bt_iso_qos qos;
+	struct iovec iov;
+	struct bt_bap_qos bap_qos = {0};
 
 	DBG("BIG Info received");
 
@@ -1329,7 +1192,15 @@  static gboolean big_info_report_cb(GIOChannel *io, GIOCondition cond,
 	/* Analyze received BASE data and create remote media endpoints for each
 	 * BIS matching our capabilities
 	 */
-	parse_base(data, &base, &qos, bap_debug);
+	iov.iov_base = base.base;
+	iov.iov_len = base.base_len;
+
+	/* Create BAP QoS structure */
+	bap_iso_qos_to_bap_qos(&qos, &bap_qos);
+
+	bt_bap_parse_base(&iov, &bap_qos, bap_debug, bis_handler, data);
+
+	util_iov_free(bap_qos.bcast.bcode, 1);
 
 	service_set_connecting(req->data.service);
 
diff --git a/profiles/audio/bass.c b/profiles/audio/bass.c
index 6237f5acc..d3b35f62a 100644
--- a/profiles/audio/bass.c
+++ b/profiles/audio/bass.c
@@ -92,7 +92,7 @@  struct bass_assistant {
 	uint8_t sgrp;
 	uint8_t bis;
 	uint32_t bid;
-	struct bt_iso_qos qos;
+	struct bt_bap_qos qos;
 	struct iovec *meta;
 	struct iovec *caps;
 	enum assistant_state state;
@@ -399,8 +399,8 @@  static int assistant_parse_qos(struct bass_assistant *assistant,
 				return -EINVAL;
 			}
 
-			memcpy(assistant->qos.bcast.bcode, iov.iov_base,
-								iov.iov_len);
+			util_iov_free(assistant->qos.bcast.bcode, 1);
+			assistant->qos.bcast.bcode = util_iov_dup(&iov, 1);
 
 			return 0;
 		}
@@ -592,7 +592,12 @@  static gboolean get_qos(const GDBusPropertyTable *property,
 {
 	struct bass_assistant *assistant = data;
 	DBusMessageIter dict;
-	uint8_t *bcode = assistant->qos.bcast.bcode;
+	uint8_t arr[BT_BASS_BCAST_CODE_SIZE] = {0};
+	uint8_t *bcode = arr;
+
+	if (assistant->qos.bcast.bcode)
+		memcpy(arr, assistant->qos.bcast.bcode->iov_base,
+						BT_BASS_BCAST_CODE_SIZE);
 
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
 					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -648,7 +653,7 @@  static void src_ad_search_bid(void *data, void *user_data)
 
 static struct bass_assistant *assistant_new(struct btd_adapter *adapter,
 		struct btd_device *device, struct bass_data *data,
-		uint8_t sgrp, uint8_t bis, struct bt_iso_qos *qos,
+		uint8_t sgrp, uint8_t bis, struct bt_bap_qos *qos,
 		struct iovec *meta, struct iovec *caps)
 {
 	struct bass_assistant *assistant;
@@ -666,6 +671,10 @@  static struct bass_assistant *assistant_new(struct btd_adapter *adapter,
 	assistant->sgrp = sgrp;
 	assistant->bis = bis;
 	assistant->qos = *qos;
+
+	/* Create an internal copy for bcode */
+	assistant->qos.bcast.bcode = util_iov_dup(qos->bcast.bcode, 1);
+
 	assistant->meta = util_iov_dup(meta, 1);
 	assistant->caps = util_iov_dup(caps, 1);
 
@@ -689,7 +698,7 @@  static struct bass_assistant *assistant_new(struct btd_adapter *adapter,
 }
 
 void bass_add_stream(struct btd_device *device, struct iovec *meta,
-			struct iovec *caps, struct bt_iso_qos *qos,
+			struct iovec *caps, struct bt_bap_qos *qos,
 			uint8_t sgrp, uint8_t bis)
 {
 	const struct queue_entry *entry;
@@ -998,7 +1007,7 @@  static void bass_attached(struct bt_bass *bass, void *user_data)
 static void bass_handle_bcode_req(struct bass_assistant *assistant, int id)
 {
 	struct bt_bass_bcast_audio_scan_cp_hdr hdr;
-	struct bt_bass_set_bcast_code_params params;
+	struct bt_bass_set_bcast_code_params params = {0};
 	struct iovec iov = {0};
 	int err;
 
@@ -1007,8 +1016,11 @@  static void bass_handle_bcode_req(struct bass_assistant *assistant, int id)
 	hdr.op = BT_BASS_SET_BCAST_CODE;
 
 	params.id = id;
-	memcpy(params.bcast_code, assistant->qos.bcast.bcode,
-					BT_BASS_BCAST_CODE_SIZE);
+
+	if (assistant->qos.bcast.bcode)
+		memcpy(params.bcast_code,
+			assistant->qos.bcast.bcode->iov_base,
+			BT_BASS_BCAST_CODE_SIZE);
 
 	iov.iov_base = malloc0(sizeof(params));
 	if (!iov.iov_base)
diff --git a/profiles/audio/bass.h b/profiles/audio/bass.h
index 257346374..845949117 100644
--- a/profiles/audio/bass.h
+++ b/profiles/audio/bass.h
@@ -8,7 +8,7 @@ 
  */
 
 void bass_add_stream(struct btd_device *device, struct iovec *meta,
-			struct iovec *caps, struct bt_iso_qos *qos,
+			struct iovec *caps, struct bt_bap_qos *qos,
 			uint8_t sgrp, uint8_t bis);
 void bass_remove_stream(struct btd_device *device);