Subject: [PATCH v4 1/3] client/player.c: Add support for multiple BISes

Remove hardcoded base and QoS for broadcast and use presets instead.
Remove BIG, BIS, and context from the register endpoint
command for Broadcast.
Add Location and Metadata support for endpoint config for
broadcast source.

---
client/player.c | 301 ++++++++++++++++++++++++++++++++----------------
1 file changed, 201 insertions(+), 100 deletions(-)

diff --git a/client/player.c b/client/player.c
index dad243786..fc5ebd602 100644
--- a/client/player.c
+++ b/client/player.c
@@ -72,6 +72,17 @@
#define EP_SNK_CTXT 0x0fff
#define EP_SUPPORTED_SNK_CTXT EP_SNK_CTXT

+/* 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;
@@ -92,7 +103,7 @@ struct endpoint {
DBusMessage *msg;
struct preset *preset;
bool broadcast;
- struct iovec *bcode;
+ struct iovec bcode;
};

static DBusConnection *dbus_conn;
@@ -105,6 +116,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;
@@ -118,21 +130,7 @@ 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_set_metadata_cfg(const char *input, void *user_data);

static void endpoint_unregister(void *data)
{
@@ -1857,37 +1855,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,
@@ -1949,71 +1943,67 @@ 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");
- bt_shell_hexdump(cfg->ep->bcode->iov_base,
- cfg->ep->bcode->iov_len);
+ bt_shell_hexdump(cfg->ep->bcode.iov_base,
+ cfg->ep->bcode.iov_len);

g_dbus_dict_append_basic_array(iter, DBUS_TYPE_STRING,
&key, DBUS_TYPE_BYTE,
- &cfg->ep->bcode->iov_base,
- cfg->ep->bcode->iov_len);
+ &cfg->ep->bcode.iov_base,
+ cfg->ep->bcode.iov_len);
}

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

@@ -2758,9 +2748,6 @@ static void endpoint_iso_group(const char *input, void *user_data)
if (!ep->broadcast)
bt_shell_prompt_input(ep->path, "CIS (auto/value):",
endpoint_iso_stream, ep);
- else
- bt_shell_prompt_input(ep->path, "BIS (auto/value):",
- endpoint_iso_stream, ep);
}

static void endpoint_context(const char *input, void *user_data)
@@ -2778,12 +2765,8 @@ static void endpoint_context(const char *input, void *user_data)

ep->context = value;

- if (ep->broadcast)
- bt_shell_prompt_input(ep->path, "BIG (auto/value):",
- endpoint_iso_group, ep);
- else
- bt_shell_prompt_input(ep->path, "CIG (auto/value):",
- endpoint_iso_group, ep);
+ bt_shell_prompt_input(ep->path, "CIG (auto/value):",
+ endpoint_iso_group, ep);
}

static void endpoint_supported_context(const char *input, void *user_data)
@@ -2820,8 +2803,11 @@ static void endpoint_locations(const char *input, void *user_data)

ep->locations = value;

- bt_shell_prompt_input(ep->path, "Supported Context (value):",
- endpoint_supported_context, ep);
+ if (ep->broadcast)
+ endpoint_register(ep);
+ else
+ bt_shell_prompt_input(ep->path, "Supported Context (value):",
+ endpoint_supported_context, ep);
}

static void endpoint_max_transports(const char *input, void *user_data)
@@ -2850,13 +2836,6 @@ static void endpoint_auto_accept(const char *input, void *user_data)
{
struct endpoint *ep = user_data;

- if (!strcmp(ep->uuid, BCAA_SERVICE_UUID) ||
- !strcmp(ep->uuid, BAA_SERVICE_UUID)) {
- ep->broadcast = true;
- } else {
- ep->broadcast = false;
- }
-
if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) {
ep->auto_accept = true;
bt_shell_prompt_input(ep->path, "Max Transports (auto/value):",
@@ -2897,6 +2876,34 @@ done:
endpoint_auto_accept, ep);
}

+static void config_endpoint_channel_location(const char *input, void *user_data)
+{
+ struct endpoint_config *cfg = user_data;
+ char *endptr = NULL;
+ int value;
+ uint32_t location;
+
+ value = strtol(input, &endptr, 0);
+
+ if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
+ bt_shell_printf("Invalid argument: %s\n", input);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ /* Add Audio Allocation LTV in Capabilities */
+ {
+ uint8_t ltv[6] = { 0x05, LC3_CONFIG_CHAN_ALLOC };
+
+ location = cpu_to_le32(value);
+ memcpy(&ltv[2], &location, sizeof(location));
+ iov_append(&cfg->caps, ltv, sizeof(ltv));
+ }
+
+ /* Add metadata */
+ bt_shell_prompt_input(cfg->ep->path, "Enter Metadata (value/no):",
+ endpoint_set_metadata_cfg, cfg);
+}
+
static void endpoint_set_capabilities(const char *input, void *user_data)
{
struct endpoint *ep = user_data;
@@ -2974,6 +2981,13 @@ static void cmd_register_endpoint(int argc, char *argv[])
g_list_length(local_endpoints));
local_endpoints = g_list_append(local_endpoints, ep);

+ if (!strcmp(ep->uuid, BCAA_SERVICE_UUID) ||
+ !strcmp(ep->uuid, BAA_SERVICE_UUID)) {
+ ep->broadcast = true;
+ } else {
+ ep->broadcast = false;
+ }
+
if (strrchr(argv[2], ':')) {
ep->codec = 0xff;
parse_vendor_codec(argv[2], &ep->cid, &ep->vid);
@@ -3120,7 +3134,81 @@ static void endpoint_config(const char *input, void *user_data)
endpoint_set_config(cfg);
}

+
+static void endpoint_set_metadata_cfg(const char *input, void *user_data)
+{
+ struct endpoint_config *cfg = user_data;
+
+ if (!strcasecmp(input, "n") || !strcasecmp(input, "no"))
+ goto done;
+
+ if (!cfg->meta)
+ cfg->meta = g_new0(struct iovec, 1);
+
+ cfg->meta->iov_base = str2bytearray((char *) input,
+ &cfg->meta->iov_len);
+ if (!cfg->meta->iov_base) {
+ free(cfg->meta);
+ cfg->meta = NULL;
+ }
+
+done:
+ endpoint_set_config(cfg);
+}
+
+static void config_endpoint_iso_group(const char *input, void *user_data)
+{
+ struct endpoint_config *cfg = user_data;
+ char *endptr = NULL;
+ int value;
+ bool found = false;
+
+ value = strtol(input, &endptr, 0);
+
+ if (!endptr || *endptr != '\0' || value > UINT8_MAX) {
+ bt_shell_printf("Invalid argument: %s\n", input);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ cfg->ep->iso_group = value;
+
+ /* Check if Channel allocation is present in caps */
+ {
+ struct iovec iov;
+ int i;
+
+ iov.iov_base = (void *) cfg->caps->iov_base;
+ iov.iov_len = cfg->caps->iov_len;
+
+ for (i = 0; iov.iov_len; i++) {
+ uint8_t l, t;
+
+ util_iov_pull_u8(&iov, &l);
+ util_iov_pull_u8(&iov, &t);
+ l--;
+ (void *)util_iov_pull_mem(&iov, l);
+ if (t == LC3_CONFIG_CHAN_ALLOC) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ /* Add channel allocation if it is not present in caps */
+ if (!found) {
+ bt_shell_prompt_input(cfg->ep->path,
+ "Enter channel location (value):",
+ config_endpoint_channel_location, cfg);
+ } else {
+ /* Add metadata */
+ bt_shell_prompt_input(cfg->ep->path,
+ "Enter Metadata (value/no):",
+ endpoint_set_metadata_cfg, cfg);
+ }
+}
+
static struct endpoint *endpoint_new(const struct capabilities *cap);
+static void endpoint_init_defaults(struct endpoint *ep);

static void cmd_config_endpoint(int argc, char *argv[])
{
@@ -3154,6 +3242,7 @@ static void cmd_config_endpoint(int argc, char *argv[])
if (cap) {
broadcast = true;
cfg->ep = endpoint_new(cap);
+ endpoint_init_defaults(cfg->ep);
cfg->ep->preset = find_presets_name(uuid, argv[3]);
if (!cfg->ep->preset)
bt_shell_printf("Preset not found\n");
@@ -3174,22 +3263,34 @@ 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.iov_base = bcast_code;
+ cfg->ep->bcode.iov_len = 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;
+ if ((strcmp(cfg->ep->uuid, BCAA_SERVICE_UUID) == 0))
+ bt_shell_prompt_input(cfg->ep->path,
+ "BIG (value):",
+ config_endpoint_iso_group, cfg);
+ else
+ endpoint_set_config(cfg);
+ } else
+ endpoint_set_config(cfg);
return;
}

--
2.39.2



2024-01-10 17:33:29

by bluez.test.bot

[permalink] [raw]
Subject: RE: Add support for multiple BISes

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=815783

---Test result---

Test Summary:
CheckPatch FAIL 3.16 seconds
GitLint PASS 1.34 seconds
BuildEll PASS 24.52 seconds
BluezMake PASS 701.19 seconds
MakeCheck PASS 12.24 seconds
MakeDistcheck PASS 161.23 seconds
CheckValgrind PASS 222.82 seconds
CheckSmatch PASS 330.02 seconds
bluezmakeextell PASS 106.88 seconds
IncrementalBuild PASS 1989.15 seconds
ScanBuild PASS 945.08 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v4,2/3] bap.c: Add support for multiple BISes
ERROR:TRAILING_WHITESPACE: trailing whitespace
#319: FILE: profiles/audio/bap.c:537:
+^Istruct update_base_data update_data; $

/github/workspace/src/src/13516293.patch total: 1 errors, 0 warnings, 2441 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile

/github/workspace/src/src/13516293.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.




---
Regards,
Linux Bluetooth