Diff between 7280f4357cf6c72bf51ebe52739143e0b9203de2 and b907befc2d801f1a7607cd651369a67cceef8d33

Changed Files

File Additions Deletions Status
src/shared/bap.c +62 -3 modified

Full Patch

diff --git a/src/shared/bap.c b/src/shared/bap.c
index f4812a4..59ef81d 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -262,6 +262,12 @@ static bool bap_db_match(const void *data, const void *match_data)
 	return (bdb->db == db);
 }
 
+static void *iov_append(struct iovec *iov, size_t len, const void *d)
+{
+	iov->iov_base = realloc(iov->iov_base, iov->iov_len + len);
+	return util_iov_push_mem(iov, len, d);
+}
+
 unsigned int bt_bap_pac_register(bt_bap_pac_func_t added,
 				bt_bap_pac_func_t removed, void *user_data,
 				bt_bap_destroy_func_t destroy)
@@ -2236,6 +2242,52 @@ static struct bt_ascs *bap_get_ascs(struct bt_bap *bap)
 	return bap->rdb->ascs;
 }
 
+static bool match_codec(const void *data, const void *user_data)
+{
+	const struct bt_bap_pac *pac = data;
+	const struct bt_bap_codec *codec = user_data;
+
+	return bap_codec_equal(&pac->codec, codec);
+}
+
+static struct bt_bap_pac *bap_pac_find(struct bt_bap_db *bdb, uint8_t type,
+					struct bt_bap_codec *codec)
+{
+	switch (type) {
+	case BT_BAP_SOURCE:
+		return queue_find(bdb->sources, match_codec, codec);
+	case BT_BAP_SINK:
+		return queue_find(bdb->sinks, match_codec, codec);
+	}
+
+	return NULL;
+}
+
+static void *ltv_merge(struct iovec *data, struct iovec *cont)
+{
+	uint8_t delimiter = 0;
+
+	iov_append(data, sizeof(delimiter), &delimiter);
+
+	return iov_append(data, cont->iov_len, cont->iov_base);
+}
+
+static void bap_pac_merge(struct bt_bap_pac *pac, struct iovec *data,
+					struct iovec *metadata)
+{
+	/* Merge data into existing record */
+	if (pac->data)
+		ltv_merge(pac->data, data);
+	else
+		pac->data = util_iov_dup(data, 1);
+
+	/* Merge metadata into existing record */
+	if (pac->metadata)
+		ltv_merge(pac->metadata, metadata);
+	else
+		pac->metadata = util_iov_dup(metadata, 1);
+}
+
 static struct bt_bap_pac *bap_pac_new(struct bt_bap_db *bdb, const char *name,
 					uint8_t type,
 					struct bt_bap_codec *codec,
@@ -2742,14 +2794,21 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
 
 		util_iov_pull_mem(&iov, meta->len);
 
+		DBG(bap, "PAC #%u: type %u codec 0x%02x cc_len %u meta_len %u",
+			i, type, p->codec.id, p->cc_len, meta->len);
+
+		/* Check if there is already a PAC record for the codec */
+		pac = bap_pac_find(bap->rdb, type, &p->codec);
+		if (pac) {
+			bap_pac_merge(pac, &data, &metadata);
+			continue;
+		}
+
 		pac = bap_pac_new(bap->rdb, NULL, type, &p->codec, NULL, &data,
 								&metadata);
 		if (!pac)
 			continue;
 
-		DBG(bap, "PAC #%u: type %u codec 0x%02x cc_len %u meta_len %u",
-			i, type, p->codec.id, p->cc_len, meta->len);
-
 		queue_push_tail(queue, pac);
 	}
 }