summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-10-20 16:53:12 -0700
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-12-02 11:20:07 -0800
commitb907befc2d801f1a7607cd651369a67cceef8d33 (patch)
treea940d30c003d3409117531f950189430c75e8bc1 /src
parent7280f4357cf6c72bf51ebe52739143e0b9203de2 (diff)
downloadbluez-b907befc2d801f1a7607cd651369a67cceef8d33.tar.gz
shared/bap: Merge PAC records of the same type/codec
This attempts to merge PAC records which contain the same type and codec to simplify the matching with client endpoints so all capabilities and metadata are match at once instead of for each PAC record.
Diffstat (limited to 'src')
-rw-r--r--src/shared/bap.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/src/shared/bap.c b/src/shared/bap.c
index f4812a4b9..59ef81d11 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);
}
}