Subject: [PATCH BlueZ v4 0/3] Add code to support dynamically generated BASE

This removes hardcoded BASE from client/player and adds support to
dynamically generate BASE from preset provided when configuring
a broadcast source endpoint.

Silviu Florian Barbulescu (3):
shared/bap: Add code to support dynamically generated BASE from
presets
client/player:Remove hardcoded BASE for broadcast to use presets
bap: Use the information in SetConfiguration to generate BASE

client/player.c | 153 +++++++++---------
profiles/audio/bap.c | 21 +--
src/shared/bap.c | 364 +++++++++++++++++++++++++++++++++++++++++++
src/shared/bap.h | 2 +
4 files changed, 449 insertions(+), 91 deletions(-)


base-commit: a9d1f6f6a625607de6c3f5b7a40a3aac5f36c02b
--
2.39.2



Subject: [PATCH BlueZ v4 2/3] client/player: Remove hardcoded BASE from player

Remove hardcoded BASE and QoS for broadcast and use the information
from the preset instead.

---
client/player.c | 153 ++++++++++++++++++++++++------------------------
1 file changed, 75 insertions(+), 78 deletions(-)

diff --git a/client/player.c b/client/player.c
index 1bc64af3c..623519209 100644
--- a/client/player.c
+++ b/client/player.c
@@ -94,6 +94,17 @@ struct avdtp_media_codec_capability {
#error "Unknown byte order"
#endif

+/* BAP Broadcast parameters */
+#define BCAST_SYNC_FACTOR 24 /* PA params */
+#define BCAST_OPTIONS 0x00 /* PA Create Sync */
+#define BCAST_SKIP 0x0000 /* PA Create Sync */
+#define BCAST_SYNC_TIMEOUT 0x4000 /* PA Create Sync */
+#define BCAST_SYNC_CTE_TYPE 0x00 /* PA Create Sync */
+#define BCAST_MSE 0x00 /* BIG Create Sync */
+#define BCAST_TIMEOUT 0x4000 /* BIG Create Sync */
+#define BCAST_CODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
+ 0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
+
struct endpoint {
char *path;
char *uuid;
@@ -127,6 +138,7 @@ static GList *endpoints = NULL;
static GList *local_endpoints = NULL;
static GList *transports = NULL;
static struct queue *ios = NULL;
+static uint8_t bcast_code[] = BCAST_CODE;

struct transport {
GDBusProxy *proxy;
@@ -140,22 +152,6 @@ struct transport {
struct io *timer_io;
};

-static const uint8_t base_lc3_16_2_1[] = {
- 0x28, 0x00, 0x00, /* Presentation Delay */
- 0x01, /* Number of Subgroups */
- 0x01, /* Number of BIS */
- 0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
- 0x10, /* Codec Specific Configuration */
- 0x02, 0x01, 0x03, /* 16 KHZ */
- 0x02, 0x02, 0x01, /* 10 ms */
- 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* Front Left */
- 0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
- 0x04, /* Metadata */
- 0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
- 0x01, /* BIS */
- 0x00, /* Codec Specific Configuration */
-};
-
static void endpoint_unregister(void *data)
{
struct endpoint *ep = data;
@@ -1879,37 +1875,33 @@ static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
struct endpoint_config {
GDBusProxy *proxy;
struct endpoint *ep;
- struct iovec *caps;
- struct iovec *meta;
+ struct iovec *caps; /* Codec Specific Configuration LTVs */
+ struct iovec *meta; /* Metadata LTVs*/
uint8_t target_latency;
- struct codec_qos qos;
-};
-
-#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
- 0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
-
-static struct bt_iso_qos bcast_qos = {
- .bcast = {
- .big = BT_ISO_QOS_BIG_UNSET,
- .bis = BT_ISO_QOS_BIS_UNSET,
- .sync_factor = 24,
- .packing = 0x00,
- .framing = 0x00,
- .encryption = 0x00,
- .bcode = BCODE,
- .options = 0x00,
- .skip = 0x0000,
- .sync_timeout = 0x4000,
- .sync_cte_type = 0x00,
- .mse = 0x00,
- .timeout = 0x4000,
- }
+ struct codec_qos qos; /* BAP QOS configuration parameters */
+ uint8_t sync_factor; /* PA parameter */
+ uint8_t options; /* PA create sync parameter */
+ uint16_t skip; /* PA create sync parameter */
+ uint16_t sync_timeout; /* PA create sync parameter */
+ uint8_t sync_cte_type; /* PA create sync parameter */
+ uint8_t mse; /* BIG create sync parameter */
+ uint16_t timeout; /* BIG create sync parameter */
};

static void append_io_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
{
struct codec_qos *qos = &cfg->qos;

+ bt_shell_printf("Framing 0x%02x\n", qos->framing);
+
+ g_dbus_dict_append_entry(iter, "Framing", DBUS_TYPE_BYTE,
+ &qos->framing);
+
+ bt_shell_printf("PresentationDelay %u\n", qos->delay);
+
+ g_dbus_dict_append_entry(iter, "PresentationDelay",
+ DBUS_TYPE_UINT32, &qos->delay);
+
bt_shell_printf("Interval %u\n", qos->interval);

g_dbus_dict_append_entry(iter, "Interval", DBUS_TYPE_UINT32,
@@ -1971,59 +1963,54 @@ static void append_ucast_qos(DBusMessageIter *iter, struct endpoint_config *cfg)

static void append_bcast_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
{
- if (bcast_qos.bcast.big != BT_ISO_QOS_BIG_UNSET) {
- bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big);
+ if (cfg->ep->iso_group != BT_ISO_QOS_BIG_UNSET) {
+ bt_shell_printf("BIG 0x%2.2x\n", cfg->ep->iso_group);
g_dbus_dict_append_entry(iter, "BIG", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.big);
+ &cfg->ep->iso_group);
}

- if (bcast_qos.bcast.bis != BT_ISO_QOS_BIS_UNSET) {
- bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis);
+ if (cfg->ep->iso_stream != BT_ISO_QOS_BIS_UNSET) {
+ bt_shell_printf("BIS 0x%2.2x\n", cfg->ep->iso_stream);
g_dbus_dict_append_entry(iter, "BIS", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.bis);
+ &cfg->ep->iso_stream);
}

- bt_shell_printf("Framing 0x%02x\n", bcast_qos.bcast.framing);
-
- g_dbus_dict_append_entry(iter, "Framing", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.framing);
-
- bt_shell_printf("SyncFactor %u\n", bcast_qos.bcast.sync_factor);
+ bt_shell_printf("SyncFactor %u\n", cfg->sync_factor);

g_dbus_dict_append_entry(iter, "SyncFactor", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.sync_factor);
+ &cfg->sync_factor);

- bt_shell_printf("Options %u\n", bcast_qos.bcast.options);
+ bt_shell_printf("Options %u\n", cfg->options);

g_dbus_dict_append_entry(iter, "Options", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.options);
+ &cfg->options);

- bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip);
+ bt_shell_printf("Skip %u\n", cfg->skip);

g_dbus_dict_append_entry(iter, "Skip", DBUS_TYPE_UINT16,
- &bcast_qos.bcast.skip);
+ &cfg->skip);

- bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout);
+ bt_shell_printf("SyncTimeout %u\n", cfg->sync_timeout);

g_dbus_dict_append_entry(iter, "SyncTimeout", DBUS_TYPE_UINT16,
- &bcast_qos.bcast.sync_timeout);
+ &cfg->sync_timeout);

- bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type);
+ bt_shell_printf("SyncCteType %u\n", cfg->sync_cte_type);

g_dbus_dict_append_entry(iter, "SyncType", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.sync_cte_type);
+ &cfg->sync_cte_type);

- bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse);
+ bt_shell_printf("MSE %u\n", cfg->mse);

g_dbus_dict_append_entry(iter, "MSE", DBUS_TYPE_BYTE,
- &bcast_qos.bcast.mse);
+ &cfg->mse);

- bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout);
+ bt_shell_printf("Timeout %u\n", cfg->timeout);

g_dbus_dict_append_entry(iter, "Timeout", DBUS_TYPE_UINT16,
- &bcast_qos.bcast.timeout);
+ &cfg->timeout);

- if (cfg->ep->bcode) {
+ if (cfg->ep->bcode->iov_len != 0) {
const char *key = "BCode";

bt_shell_printf("BCode:\n");
@@ -2036,6 +2023,7 @@ static void append_bcast_qos(DBusMessageIter *iter, struct endpoint_config *cfg)
cfg->ep->bcode->iov_len);
}

+ /* Add BAP codec QOS configuration */
append_io_qos(iter, cfg);
}

@@ -3667,22 +3655,31 @@ static void cmd_config_endpoint(int argc, char *argv[])
goto fail;
}

- if (cfg->ep->broadcast) {
- iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode,
- sizeof(bcast_qos.bcast.bcode));
- /* Copy capabilities for broadcast*/
- iov_append(&cfg->caps, base_lc3_16_2_1,
- sizeof(base_lc3_16_2_1));
- } else {
- /* Copy capabilities */
- iov_append(&cfg->caps, preset->data.iov_base,
- preset->data.iov_len);
- }
+ /* Copy capabilities */
+ iov_append(&cfg->caps, preset->data.iov_base,
+ preset->data.iov_len);

/* Set QoS parameters */
cfg->qos = preset->qos;

- endpoint_set_config(cfg);
+ if (cfg->ep->broadcast) {
+ cfg->ep->bcode = g_new0(struct iovec, 1);
+ iov_append(&cfg->ep->bcode, bcast_code,
+ sizeof(bcast_code));
+
+ /* Add periodic advertisement parameters */
+ cfg->sync_factor = BCAST_SYNC_FACTOR;
+ cfg->options = BCAST_OPTIONS;
+ cfg->skip = BCAST_SKIP;
+ cfg->sync_timeout = BCAST_SYNC_TIMEOUT;
+ cfg->sync_cte_type = BCAST_SYNC_CTE_TYPE;
+ /* Add BIG create sync parameters */
+ cfg->mse = BCAST_MSE;
+ cfg->timeout = BCAST_TIMEOUT;
+
+ endpoint_set_config(cfg);
+ } else
+ endpoint_set_config(cfg);
return;
}

--
2.39.2


Subject: [PATCH BlueZ v4 3/3] bap: Use SetConfiguration info to generate BASE

Use the preset information provided by SetConfiguration to generate
the source's BASE and not receive the BASE over D-BUS.
---
profiles/audio/bap.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 8d44e48fe..63bdbb52a 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -610,6 +610,11 @@ static int setup_parse_bcast_qos(struct bap_setup *setup, const char *key,
return -EINVAL;

dbus_message_iter_get_basic(iter, &qos->bcast.timeout);
+ } else if (!strcasecmp(key, "PresentationDelay")) {
+ if (var != DBUS_TYPE_UINT32)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(iter, &qos->bcast.delay);
} else if (!strcasecmp(key, "BCode")) {
struct iovec iov;

@@ -666,18 +671,6 @@ static int setup_parse_qos(struct bap_setup *setup, DBusMessageIter *iter)
dbus_message_iter_next(&array);
}

- if (queue_find(setup->ep->data->bcast, NULL, setup->ep)) {
- uint32_t presDelay;
- uint8_t numSubgroups, numBis;
- struct bt_bap_codec codec;
-
- util_iov_free(setup->base, 1);
- setup->base = util_iov_dup(setup->caps, 1);
- parse_base(setup->base->iov_base, setup->base->iov_len,
- bap_debug, &presDelay, &numSubgroups, &numBis,
- &codec, &setup->caps, &setup->metadata);
- }
-
return 0;
}

@@ -924,8 +917,10 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
/* No message sent over the air for broadcast */
if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SINK)
setup->msg = dbus_message_ref(msg);
- else
+ else {
+ setup->base = bt_bap_stream_get_base(setup->stream);
setup->id = 0;
+ }

return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
--
2.39.2


Subject: [PATCH BlueZ v4 1/3] shared/bap: Code to generate bcast source BASE

Add code to support dynamically generated BASE from
endpoint configuration.

---
src/shared/bap.c | 364 +++++++++++++++++++++++++++++++++++++++++++++++
src/shared/bap.h | 2 +
2 files changed, 366 insertions(+)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 49eb8d057..d56911e6b 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -255,6 +255,26 @@ struct bt_pacs_context {
uint16_t src;
} __packed;

+struct bt_base {
+ uint8_t big_id;
+ uint32_t pres_delay;
+ uint8_t next_bis_index;
+ struct queue *subgroups;
+};
+
+struct bt_subgroup {
+ uint8_t index;
+ struct bt_bap_codec codec;
+ struct iovec *caps;
+ struct iovec *meta;
+ struct queue *bises;
+};
+
+struct bt_bis {
+ uint8_t index;
+ struct iovec *caps;
+};
+
/* Contains local bt_bap_db */
static struct queue *bap_db;
static struct queue *bap_cbs;
@@ -5492,3 +5512,347 @@ void bt_bap_update_bcast_source(struct bt_bap_pac *pac,
bap_pac_merge(pac, data, metadata);
pac->codec = *codec;
}
+
+static void destroy_base_bis(void *data)
+{
+ struct bt_bis *bis = data;
+
+ if (!bis)
+ return;
+
+ if (bis->caps)
+ util_iov_free(bis->caps, 1);
+
+ free(bis);
+}
+
+static void generate_bis_base(void *data, void *user_data)
+{
+ struct bt_bis *bis = data;
+ struct iovec *base_iov = user_data;
+ uint8_t cc_length = bis->caps->iov_len;
+
+ if (!util_iov_push_u8(base_iov, bis->index))
+ return;
+
+ if (!util_iov_push_u8(base_iov, cc_length))
+ return;
+
+ if (cc_length)
+ util_iov_push_mem(base_iov, bis->caps->iov_len,
+ bis->caps->iov_base);
+}
+
+static void generate_subgroup_base(void *data, void *user_data)
+{
+ struct bt_subgroup *sgrp = data;
+ struct iovec *base_iov = user_data;
+
+ if (!util_iov_push_u8(base_iov, queue_length(sgrp->bises)))
+ return;
+
+ if (!util_iov_push_u8(base_iov, sgrp->codec.id))
+ return;
+
+ if (!util_iov_push_le16(base_iov, sgrp->codec.cid))
+ return;
+
+ if (!util_iov_push_le16(base_iov, sgrp->codec.vid))
+ return;
+
+ if (sgrp->caps) {
+ if (!util_iov_push_u8(base_iov, sgrp->caps->iov_len))
+ return;
+
+ if (sgrp->caps->iov_len)
+ util_iov_push_mem(base_iov, sgrp->caps->iov_len,
+ sgrp->caps->iov_base);
+ } else if (!util_iov_push_u8(base_iov, 0))
+ return;
+
+ if (sgrp->meta) {
+ if (!util_iov_push_u8(base_iov, sgrp->meta->iov_len))
+ return;
+
+ if (sgrp->meta->iov_len)
+ util_iov_push_mem(base_iov, sgrp->meta->iov_len,
+ sgrp->meta->iov_base);
+ } else if (!util_iov_push_u8(base_iov, 0))
+ return;
+
+ queue_foreach(sgrp->bises, generate_bis_base, base_iov);
+}
+
+static struct iovec *generate_base(struct bt_base *base)
+{
+ struct iovec *base_iov = new0(struct iovec, 0x1);
+
+ base_iov->iov_base = util_malloc(BASE_MAX_LENGTH);
+
+ if (!util_iov_push_le24(base_iov, base->pres_delay))
+ return NULL;
+
+ if (!util_iov_push_u8(base_iov,
+ queue_length(base->subgroups)))
+ return NULL;
+
+ queue_foreach(base->subgroups, generate_subgroup_base,
+ base_iov);
+
+ return base_iov;
+}
+
+static void add_new_bis(struct bt_subgroup *subgroup,
+ uint8_t bis_index, struct iovec *caps)
+{
+ struct bt_bis *bis = new0(struct bt_bis, 1);
+
+ bis->index = bis_index;
+
+ if (caps)
+ bis->caps = caps;
+ else
+ bis->caps = new0(struct iovec, 1);
+
+ queue_push_tail(subgroup->bises, bis);
+}
+
+static void add_new_subgroup(struct bt_base *base,
+ struct bt_bap_stream *stream)
+{
+ struct bt_bap_pac *lpac = stream->lpac;
+ struct bt_subgroup *sgrp = new0(
+ struct bt_subgroup, 1);
+ uint16_t cid = 0;
+ uint16_t vid = 0;
+
+ bt_bap_pac_get_vendor_codec(lpac, &sgrp->codec.id, &cid,
+ &vid, NULL, NULL);
+ sgrp->codec.cid = cid;
+ sgrp->codec.vid = vid;
+ sgrp->caps = util_iov_dup(stream->cc, 1);
+ sgrp->meta = util_iov_dup(stream->meta, 1);
+ sgrp->bises = queue_new();
+
+ stream->qos.bcast.bis = base->next_bis_index++;
+ add_new_bis(sgrp, stream->qos.bcast.bis,
+ NULL);
+ queue_push_tail(base->subgroups, sgrp);
+}
+
+struct bt_ltv_match {
+ uint8_t l;
+ uint8_t *v;
+ bool found;
+};
+
+struct bt_ltv_search {
+ struct iovec *iov;
+ bool found;
+};
+
+static void match_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+ void *user_data)
+{
+ struct bt_ltv_match *ltv_match = user_data;
+
+ if (ltv_match->found == true)
+ return;
+
+ if (ltv_match->l != l)
+ return;
+
+ if (!memcmp(v, ltv_match->v, l))
+ ltv_match->found = true;
+}
+
+static void search_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+ void *user_data)
+{
+ struct bt_ltv_search *ltv_search = user_data;
+ struct bt_ltv_match ltv_match;
+
+ ltv_match.found = false;
+ ltv_match.l = l;
+ ltv_match.v = v;
+
+ util_ltv_foreach(ltv_search->iov->iov_base,
+ ltv_search->iov->iov_len, &t,
+ match_ltv, &ltv_match);
+
+ /* Once "found" has been updated to "false",
+ * do not overwrite it anymore.
+ * It means that an ltv was not found in the search list,
+ * and this should be detected back in the parent function.
+ */
+ if (ltv_search->found)
+ ltv_search->found = ltv_match.found;
+}
+
+static bool compare_ltv(struct iovec *iov1,
+ struct iovec *iov2)
+{
+ struct bt_ltv_search ltv_search;
+
+ if ((!iov1) && (!iov2))
+ return true;
+
+ if ((!iov1) || (!iov2))
+ return false;
+
+ /* Compare metadata length */
+ if (iov1->iov_len != iov2->iov_len)
+ return false;
+
+ ltv_search.found = true;
+ ltv_search.iov = iov2;
+
+ util_ltv_foreach(iov1->iov_base,
+ iov1->iov_len, NULL,
+ search_ltv, &ltv_search);
+
+ return ltv_search.found;
+}
+
+struct bt_ltv_extract {
+ struct iovec *result;
+ struct iovec *src;
+};
+
+static void extract_ltv(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+ void *user_data)
+{
+ struct bt_ltv_extract *ext_data = user_data;
+ struct bt_ltv_match ltv_match;
+ uint8_t ltv_len = 0;
+
+ ltv_match.found = false;
+ ltv_match.l = l;
+ ltv_match.v = v;
+
+ /* Search each BIS caps ltv in subgroup caps
+ * to extract the one that are BIS specific
+ */
+ util_ltv_foreach(ext_data->src->iov_base,
+ ext_data->src->iov_len, &t,
+ match_ltv, &ltv_match);
+
+ if (!ltv_match.found) {
+ ltv_len = l + 1;
+ iov_append(ext_data->result, 1, &ltv_len);
+ iov_append(ext_data->result, 1, &t);
+ iov_append(ext_data->result, l, &v);
+ }
+}
+
+static struct iovec *extract_diff_caps(
+ struct iovec *subgroup_caps, struct iovec *bis_caps)
+{
+ struct bt_ltv_extract ext_data;
+
+ ext_data.src = subgroup_caps;
+ ext_data.result = new0(struct iovec, 1);
+
+ util_ltv_foreach(bis_caps->iov_base,
+ bis_caps->iov_len, NULL,
+ extract_ltv, &ext_data);
+
+ return ext_data.result;
+}
+
+static void set_base_subgroup(void *data, void *user_data)
+{
+ struct bt_bap_stream *stream = data;
+ struct bt_base *base = user_data;
+ /* BIS specific codec capabilities */
+ struct iovec *bis_caps;
+
+ if (bt_bap_pac_get_type(stream->lpac) != BT_BAP_BCAST_SOURCE)
+ return;
+
+ if (stream->qos.bcast.big != base->big_id)
+ return;
+
+ if (base->pres_delay < stream->qos.bcast.delay)
+ base->pres_delay = stream->qos.bcast.delay;
+
+ if (queue_isempty(base->subgroups)) {
+ add_new_subgroup(base, stream);
+ } else {
+ /* Verify if a subgroup has the same metadata */
+ const struct queue_entry *entry;
+ struct bt_subgroup *subgroup = NULL;
+ bool same_meta = false;
+
+ for (entry = queue_get_entries(base->subgroups);
+ entry; entry = entry->next) {
+ subgroup = entry->data;
+ same_meta = compare_ltv(subgroup->meta, stream->meta);
+ if (same_meta)
+ break;
+ }
+
+ if (!same_meta) {
+ /* No subgroup with the same metadata found.
+ * Create a new one.
+ */
+ add_new_subgroup(base, stream);
+ } else {
+ /* Subgroup found with the same metadata.
+ * Extract different codec capabilities.
+ */
+ bis_caps = extract_diff_caps(
+ subgroup->caps,
+ stream->cc);
+
+ stream->qos.bcast.bis = base->next_bis_index++;
+ add_new_bis(subgroup,
+ stream->qos.bcast.bis,
+ bis_caps);
+ }
+ }
+}
+
+static void destroy_base_subgroup(void *data)
+{
+ struct bt_subgroup *subgroup = data;
+
+ if (!subgroup)
+ return;
+
+ if (subgroup->caps)
+ util_iov_free(subgroup->caps, 1);
+
+ if (subgroup->meta)
+ util_iov_free(subgroup->meta, 1);
+
+ queue_destroy(subgroup->bises, destroy_base_bis);
+
+ free(subgroup);
+}
+
+/*
+ * Function to update the BASE using configuration data
+ * from each BIS belonging to the same BIG
+ */
+struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream)
+{
+ struct bt_base base;
+ struct iovec *base_iov;
+
+ base.subgroups = queue_new();
+ base.next_bis_index = 1;
+ base.big_id = stream->qos.bcast.big;
+
+ /*
+ * Create subgroups with each different Metadata and Codec
+ * Specific Configuration from all streams having the same BIG ID.
+ */
+ queue_foreach(stream->bap->streams, set_base_subgroup, &base);
+
+ base_iov = generate_base(&base);
+
+ queue_destroy(base.subgroups, destroy_base_subgroup);
+
+ return base_iov;
+}
diff --git a/src/shared/bap.h b/src/shared/bap.h
index 51edc08ab..2c3550921 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -88,6 +88,7 @@ struct bt_bap_bcast_qos {
uint16_t timeout;
uint8_t pa_sync;
struct bt_bap_io_qos io_qos;
+ uint32_t delay; /* Presentation Delay */
};

struct bt_bap_qos {
@@ -321,3 +322,4 @@ void bt_bap_update_bcast_source(struct bt_bap_pac *pac,

bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac);

+struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream);
--
2.39.2


2024-01-23 14:56:05

by bluez.test.bot

[permalink] [raw]
Subject: RE: Add code to support dynamically generated BASE

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=819102

---Test result---

Test Summary:
CheckPatch PASS 1.57 seconds
GitLint PASS 0.74 seconds
BuildEll PASS 23.90 seconds
BluezMake PASS 714.78 seconds
MakeCheck PASS 11.36 seconds
MakeDistcheck PASS 163.74 seconds
CheckValgrind PASS 223.96 seconds
CheckSmatch PASS 326.28 seconds
bluezmakeextell PASS 105.60 seconds
IncrementalBuild PASS 2063.35 seconds
ScanBuild PASS 965.19 seconds



---
Regards,
Linux Bluetooth

2024-01-23 18:41:33

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 0/3] Add code to support dynamically generated BASE

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Tue, 23 Jan 2024 14:51:42 +0200 you wrote:
> This removes hardcoded BASE from client/player and adds support to
> dynamically generate BASE from preset provided when configuring
> a broadcast source endpoint.
>
> Silviu Florian Barbulescu (3):
> shared/bap: Add code to support dynamically generated BASE from
> presets
> client/player:Remove hardcoded BASE for broadcast to use presets
> bap: Use the information in SetConfiguration to generate BASE
>
> [...]

Here is the summary with links:
- [BlueZ,v4,1/3] shared/bap: Code to generate bcast source BASE
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=e4a35bc1e2cd
- [BlueZ,v4,2/3] client/player: Remove hardcoded BASE from player
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=ba943aadd0e2
- [BlueZ,v4,3/3] bap: Use SetConfiguration info to generate BASE
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=15e7d5a4d24a

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html