2023-12-11 21:25:40

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v4 1/6] bap: Allow setup of multiple stream per endpoint

From: Luiz Augusto von Dentz <[email protected]>

Remote endpoints actually represents PAC records of the same codec and
their capabilities are merged together thus is should be possible to
create multiple streams depending on the AC configuration.
---
profiles/audio/bap.c | 613 ++++++++++++++++++++++++-------------------
1 file changed, 344 insertions(+), 269 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index c530799915f3..38eaea055ed2 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -62,22 +62,27 @@
#define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
#define MEDIA_INTERFACE "org.bluez.Media1"

-struct bap_ep {
- char *path;
- struct bap_data *data;
- struct bt_bap_pac *lpac;
- struct bt_bap_pac *rpac;
+struct bap_setup {
+ struct bap_ep *ep;
struct bt_bap_stream *stream;
+ struct bt_bap_qos qos;
GIOChannel *io;
unsigned int io_id;
bool recreate;
bool cig_active;
struct iovec *caps;
struct iovec *metadata;
- struct bt_bap_qos qos;
unsigned int id;
- DBusMessage *msg;
struct iovec *base;
+ DBusMessage *msg;
+};
+
+struct bap_ep {
+ char *path;
+ struct bap_data *data;
+ struct bt_bap_pac *lpac;
+ struct bt_bap_pac *rpac;
+ struct queue *setups;
};

struct bap_data {
@@ -728,84 +733,131 @@ fail:
static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason,
void *user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;
DBusMessage *reply;

DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason);

- ep->id = 0;
+ setup->id = 0;

- if (!ep->msg)
+ if (!setup->msg)
return;

if (!code)
- reply = dbus_message_new_method_return(ep->msg);
+ reply = dbus_message_new_method_return(setup->msg);
else
- reply = btd_error_failed(ep->msg, "Unable to configure");
+ reply = btd_error_failed(setup->msg, "Unable to configure");

g_dbus_send_message(btd_get_dbus_connection(), reply);

- dbus_message_unref(ep->msg);
- ep->msg = NULL;
+ dbus_message_unref(setup->msg);
+ setup->msg = NULL;
}

static void config_cb(struct bt_bap_stream *stream,
uint8_t code, uint8_t reason,
void *user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;
DBusMessage *reply;

DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason);

- ep->id = 0;
+ setup->id = 0;

if (!code)
return;

- if (!ep->msg)
+ if (!setup->msg)
return;

- reply = btd_error_failed(ep->msg, "Unable to configure");
+ reply = btd_error_failed(setup->msg, "Unable to configure");
g_dbus_send_message(btd_get_dbus_connection(), reply);

- dbus_message_unref(ep->msg);
- ep->msg = NULL;
+ dbus_message_unref(setup->msg);
+ setup->msg = NULL;
}

-static void bap_io_close(struct bap_ep *ep)
+static void setup_io_close(void *data, void *user_data)
{
+ struct bap_setup *setup = data;
int fd;

- if (ep->io_id) {
- g_source_remove(ep->io_id);
- ep->io_id = 0;
+ if (setup->io_id) {
+ g_source_remove(setup->io_id);
+ setup->io_id = 0;
}

- if (!ep->io)
+ if (!setup->io)
return;


- DBG("ep %p", ep);
+ DBG("setup %p", setup);

- fd = g_io_channel_unix_get_fd(ep->io);
+ fd = g_io_channel_unix_get_fd(setup->io);
close(fd);

- g_io_channel_unref(ep->io);
- ep->io = NULL;
- ep->cig_active = false;
+ g_io_channel_unref(setup->io);
+ setup->io = NULL;
+ setup->cig_active = false;
+
+ bt_bap_stream_io_connecting(setup->stream, -1);
+}
+
+static void ep_close(struct bap_ep *ep)
+{
+ if (!ep)
+ return;
+
+ queue_foreach(ep->setups, setup_io_close, NULL);
+}
+
+static struct bap_setup *setup_new(struct bap_ep *ep)
+{
+ struct bap_setup *setup;
+
+ setup = new0(struct bap_setup, 1);
+ setup->ep = ep;
+
+ if (!ep->setups)
+ ep->setups = queue_new();
+
+ queue_push_tail(ep->setups, setup);
+
+ DBG("ep %p setup %p", ep, setup);
+
+ return setup;
+}
+
+static void setup_free(void *data)
+{
+ struct bap_setup *setup = data;
+
+ DBG("%p", setup);
+
+ if (setup->ep)
+ queue_remove(setup->ep->setups, setup);
+
+ setup_io_close(setup, NULL);
+
+ util_iov_free(setup->caps, 1);
+ util_iov_free(setup->metadata, 1);
+ util_iov_free(setup->base, 1);
+
+ if (bt_bap_stream_get_type(setup->stream) == BT_BAP_STREAM_TYPE_BCAST)
+ util_iov_free(setup->qos.bcast.bcode, 1);
+
+ free(setup);
}

static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
void *data)
{
struct bap_ep *ep = data;
+ struct bap_setup *setup;
const char *path;
DBusMessageIter args, props;

- if (ep->msg)
- return btd_error_busy(msg);
-
dbus_message_iter_init(msg, &args);

dbus_message_iter_get_basic(&args, &path);
@@ -815,59 +867,55 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
return btd_error_invalid_args(msg);

- /* Disconnect IO if connecting since QoS is going to be reconfigured */
- if (bt_bap_stream_io_is_connecting(ep->stream, NULL)) {
- bap_io_close(ep);
- bt_bap_stream_io_connecting(ep->stream, -1);
- }
+ /* Disconnect IOs if connecting since QoS is going to be reconfigured */
+ ep_close(ep);
+
+ setup = setup_new(ep);

if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE) {
/* Mark BIG and BIS to be auto assigned */
- ep->qos.bcast.big = BT_ISO_QOS_BIG_UNSET;
- ep->qos.bcast.bis = BT_ISO_QOS_BIS_UNSET;
+ setup->qos.bcast.big = BT_ISO_QOS_BIG_UNSET;
+ setup->qos.bcast.bis = BT_ISO_QOS_BIS_UNSET;
} else {
/* Mark CIG and CIS to be auto assigned */
- ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
- ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
+ setup->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
+ setup->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
}

- if (parse_configuration(&props, &ep->caps, &ep->metadata,
- &ep->base, &ep->qos) < 0) {
+ if (parse_configuration(&props, &setup->caps, &setup->metadata,
+ &setup->base, &setup->qos) < 0) {
DBG("Unable to parse configuration");
+ setup_free(setup);
return btd_error_invalid_args(msg);
}

- /* TODO: Check if stream capabilities match add support for Latency
- * and PHY.
- */
- if (!ep->stream)
- ep->stream = bt_bap_stream_new(ep->data->bap, ep->lpac,
- ep->rpac, &ep->qos, ep->caps);
+ setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac,
+ &setup->qos, setup->caps);

- ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
- config_cb, ep);
- if (!ep->id) {
+ setup->id = bt_bap_stream_config(setup->stream, &setup->qos,
+ setup->caps, config_cb, ep);
+ if (!setup->id) {
DBG("Unable to config stream");
- free(ep->caps);
- ep->caps = NULL;
+ setup_free(setup);
return btd_error_invalid_args(msg);
}

- bt_bap_stream_set_user_data(ep->stream, ep->path);
+ bt_bap_stream_set_user_data(setup->stream, ep->path);

- if (ep->metadata && ep->metadata->iov_len)
- bt_bap_stream_metadata(ep->stream, ep->metadata, NULL, NULL);
+ if (setup->metadata && setup->metadata->iov_len)
+ bt_bap_stream_metadata(setup->stream, setup->metadata, NULL,
+ NULL);

- switch (bt_bap_stream_get_type(ep->stream)) {
+ switch (bt_bap_stream_get_type(setup->stream)) {
case BT_BAP_STREAM_TYPE_UCAST:
- ep->msg = dbus_message_ref(msg);
+ setup->msg = dbus_message_ref(msg);
break;
case BT_BAP_STREAM_TYPE_BCAST:
/* No message sent over the air for broadcast */
if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SINK)
- ep->msg = dbus_message_ref(msg);
+ setup->msg = dbus_message_ref(msg);
else
- ep->id = 0;
+ setup->id = 0;

return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
@@ -901,20 +949,14 @@ static void update_bcast_qos(struct bt_iso_qos *qos,
sizeof(qos->bcast.bcode));
}

-static bool match_ep_type(const void *data, const void *user_data)
-{
- const struct bap_ep *ep = data;
-
- return (bt_bap_pac_get_type(ep->lpac) == PTR_TO_INT(user_data));
-}
-
static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
{
- struct bap_data *data = user_data;
+ struct bap_setup *setup = user_data;
+ struct bap_ep *ep = setup->ep;
+ struct bap_data *data = ep->data;
struct bt_iso_qos qos;
struct bt_iso_base base;
char address[18];
- struct bap_ep *ep;
int fd;
struct iovec *base_io;
uint32_t presDelay;
@@ -938,32 +980,28 @@ static void iso_bcast_confirm_cb(GIOChannel *io, GError *err, void *user_data)
DBG("BCAST ISO: sync with %s (BIG 0x%02x BIS 0x%02x)",
address, qos.bcast.big, qos.bcast.bis);

- ep = queue_find(data->bcast, match_ep_type,
- INT_TO_PTR(BT_BAP_BCAST_SINK));
- if (!ep)
- return;
-
- update_bcast_qos(&qos, &ep->qos);
+ update_bcast_qos(&qos, &setup->qos);

base_io = new0(struct iovec, 1);
util_iov_memcpy(base_io, base.base, base.base_len);

parse_base(base_io->iov_base, base_io->iov_len, bap_debug,
&presDelay, &numSubgroups, &numBis,
- &codec, &ep->caps, &ep->metadata);
+ &codec, &setup->caps, &setup->metadata);

/* Update pac with BASE information */
- bt_bap_update_bcast_source(ep->rpac, &codec, ep->caps, ep->metadata);
- ep->id = bt_bap_stream_config(ep->stream, &ep->qos,
- ep->caps, NULL, NULL);
+ bt_bap_update_bcast_source(ep->rpac, &codec, setup->caps,
+ setup->metadata);
+ setup->id = bt_bap_stream_config(setup->stream, &setup->qos,
+ setup->caps, NULL, NULL);
data->listen_io = io;

- bt_bap_stream_set_user_data(ep->stream, ep->path);
+ bt_bap_stream_set_user_data(setup->stream, ep->path);

fd = g_io_channel_unix_get_fd(io);

- if (bt_bap_stream_set_io(ep->stream, fd)) {
- bt_bap_stream_enable(ep->stream, true, NULL, NULL, NULL);
+ if (bt_bap_stream_set_io(setup->stream, fd)) {
+ bt_bap_stream_enable(setup->stream, true, NULL, NULL, NULL);
g_io_channel_set_close_on_unref(io, FALSE);
return;
}
@@ -1008,16 +1046,10 @@ static const GDBusMethodTable ep_methods[] = {
static void ep_free(void *data)
{
struct bap_ep *ep = data;
+ struct queue *setups = ep->setups;

- if (ep->id)
- bt_bap_stream_cancel(ep->stream, ep->id);
-
- bap_io_close(ep);
-
- util_iov_free(ep->caps, 1);
- util_iov_free(ep->metadata, 1);
- if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BCAST)
- util_iov_free(ep->qos.bcast.bcode, 1);
+ ep->setups = NULL;
+ queue_destroy(setups, setup_free);
free(ep->path);
free(ep);
}
@@ -1077,12 +1109,10 @@ static struct bap_ep *ep_register_bcast(struct bap_data *data,
case BT_BAP_BCAST_SOURCE:
err = asprintf(&ep->path, "%s/pac_%s%d",
adapter_get_path(adapter), suffix, i);
- ep->base = new0(struct iovec, 1);
break;
case BT_BAP_BCAST_SINK:
err = asprintf(&ep->path, "%s/pac_%s%d",
device_get_path(device), suffix, i);
- ep->base = new0(struct iovec, 1);
break;
}

@@ -1181,33 +1211,38 @@ static struct bap_ep *ep_register(struct btd_service *service,
return ep;
}

-static void bap_config(void *data, void *user_data)
+static void setup_config(void *data, void *user_data)
{
- struct bap_ep *ep = data;
+ struct bap_setup *setup = data;
+ struct bap_ep *ep = setup->ep;

- DBG("ep %p caps %p metadata %p", ep, ep->caps, ep->metadata);
-
- if (!ep->caps)
- return;
+ DBG("setup %p caps %p metadata %p", setup, setup->caps,
+ setup->metadata);

/* TODO: Check if stream capabilities match add support for Latency
* and PHY.
*/
- if (!ep->stream)
- ep->stream = bt_bap_stream_new(ep->data->bap, ep->lpac,
- ep->rpac, &ep->qos, ep->caps);
+ if (!setup->stream)
+ setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac,
+ ep->rpac, &setup->qos,
+ setup->caps);

- ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
- config_cb, ep);
- if (!ep->id) {
+ setup->id = bt_bap_stream_config(setup->stream, &setup->qos,
+ setup->caps, config_cb, setup);
+ if (!setup->id) {
DBG("Unable to config stream");
- util_iov_free(ep->caps, 1);
- ep->caps = NULL;
- util_iov_free(ep->metadata, 1);
- ep->metadata = NULL;
+ setup_free(setup);
+ return;
}

- bt_bap_stream_set_user_data(ep->stream, ep->path);
+ bt_bap_stream_set_user_data(setup->stream, ep->path);
+}
+
+static void bap_config(void *data, void *user_data)
+{
+ struct bap_ep *ep = data;
+
+ queue_foreach(ep->setups, setup_config, NULL);
}

static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
@@ -1215,6 +1250,7 @@ static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
void *user_data)
{
struct bap_ep *ep = user_data;
+ struct bap_setup *setup;

if (err) {
error("err %d", err);
@@ -1222,15 +1258,10 @@ static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
goto done;
}

- util_iov_free(ep->caps, 1);
- ep->caps = util_iov_dup(caps, 1);
-
- if (metadata && metadata->iov_base && metadata->iov_len) {
- ep->metadata = util_iov_dup(metadata, 1);
- bt_bap_stream_metadata(ep->stream, ep->metadata, NULL, NULL);
- }
-
- ep->qos = *qos;
+ setup = setup_new(ep);
+ setup->caps = util_iov_dup(caps, 1);
+ setup->metadata = util_iov_dup(metadata, 1);
+ setup->qos = *qos;

DBG("selecting %d", ep->data->selecting);
ep->data->selecting--;
@@ -1293,28 +1324,41 @@ static void bap_ready(struct bt_bap *bap, void *user_data)
bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_found, service);
}

-static bool match_ep_by_stream(const void *data, const void *user_data)
+static bool match_setup_stream(const void *data, const void *user_data)
+{
+ const struct bap_setup *setup = data;
+ const struct bt_bap_stream *stream = user_data;
+
+ return setup->stream == stream;
+}
+
+static bool match_ep_stream(const void *data, const void *user_data)
{
const struct bap_ep *ep = data;
const struct bt_bap_stream *stream = user_data;

- return ep->stream == stream;
+ return queue_find(ep->setups, match_setup_stream, stream);
}

-static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data,
+static struct bap_setup *bap_find_setup_by_stream(struct bap_data *data,
struct bt_bap_stream *stream)
{
struct bap_ep *ep;

switch (bt_bap_stream_get_type(stream)) {
case BT_BAP_STREAM_TYPE_UCAST:
- ep = queue_find(data->snks, match_ep_by_stream, stream);
+ ep = queue_find(data->snks, match_ep_stream, stream);
if (ep)
- return ep;
+ return queue_find(ep->setups, match_setup_stream,
+ stream);

- return queue_find(data->srcs, match_ep_by_stream, stream);
+ ep = queue_find(data->srcs, match_ep_stream, stream);
+ if (ep)
+ return queue_find(ep->setups, match_setup_stream,
+ stream);
+ break;
case BT_BAP_STREAM_TYPE_BCAST:
- return queue_find(data->bcast, match_ep_by_stream, stream);
+ return queue_find(data->bcast, match_ep_stream, stream);
}

return NULL;
@@ -1435,8 +1479,9 @@ drop:
g_io_channel_shutdown(io, TRUE, NULL);
}

-static void bap_accept_io(struct bap_ep *ep, struct bt_bap_stream *stream,
- int fd, int defer)
+static void setup_accept_io(struct bap_setup *setup,
+ struct bt_bap_stream *stream,
+ int fd, int defer)
{
char c;
struct pollfd pfd;
@@ -1472,7 +1517,7 @@ static void bap_accept_io(struct bap_ep *ep, struct bt_bap_stream *stream,
}
}

- ep->cig_active = true;
+ setup->cig_active = true;

return;

@@ -1485,12 +1530,20 @@ struct cig_busy_data {
uint8_t cig;
};

+static bool match_cig_active(const void *data, const void *match_data)
+{
+ const struct bap_setup *setup = data;
+ const struct cig_busy_data *info = match_data;
+
+ return (setup->qos.ucast.cig_id == info->cig) && setup->cig_active;
+}
+
static bool cig_busy_ep(const void *data, const void *match_data)
{
const struct bap_ep *ep = data;
const struct cig_busy_data *info = match_data;

- return (ep->qos.ucast.cig_id == info->cig) && ep->cig_active;
+ return queue_find(ep->setups, match_cig_active, info);
}

static bool cig_busy_session(const void *data, const void *match_data)
@@ -1518,32 +1571,40 @@ static bool is_cig_busy(struct bap_data *data, uint8_t cig)
return queue_find(sessions, cig_busy_session, &info);
}

-static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
+static void setup_create_io(struct bap_data *data, struct bap_setup *setup,
struct bt_bap_stream *stream, int defer);

-static gboolean bap_io_recreate(void *user_data)
+static gboolean setup_io_recreate(void *user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;

- DBG("ep %p", ep);
+ DBG("%p", setup);

- ep->io_id = 0;
+ setup->io_id = 0;

- bap_create_io(ep->data, ep, ep->stream, true);
+ setup_create_io(setup->ep->data, setup, setup->stream, true);

return FALSE;
}

-static void recreate_cig_ep(void *data, void *match_data)
+static void setup_recreate(void *data, void *match_data)
{
- struct bap_ep *ep = (struct bap_ep *)data;
+ struct bap_setup *setup = data;
struct cig_busy_data *info = match_data;

- if (ep->qos.ucast.cig_id != info->cig || !ep->recreate || ep->io_id)
+ if (setup->qos.ucast.cig_id != info->cig || !setup->recreate ||
+ setup->io_id)
return;

- ep->recreate = false;
- ep->io_id = g_idle_add(bap_io_recreate, ep);
+ setup->recreate = false;
+ setup->io_id = g_idle_add(setup_io_recreate, setup);
+}
+
+static void recreate_cig_ep(void *data, void *match_data)
+{
+ struct bap_ep *ep = data;
+
+ queue_foreach(ep->setups, setup_recreate, match_data);
}

static void recreate_cig_session(void *data, void *match_data)
@@ -1558,38 +1619,39 @@ static void recreate_cig_session(void *data, void *match_data)
queue_foreach(session->srcs, recreate_cig_ep, match_data);
}

-static void recreate_cig(struct bap_ep *ep)
+static void recreate_cig(struct bap_setup *setup)
{
- struct bap_data *data = ep->data;
+ struct bap_data *data = setup->ep->data;
struct cig_busy_data info;

info.adapter = device_get_adapter(data->device);
- info.cig = ep->qos.ucast.cig_id;
+ info.cig = setup->qos.ucast.cig_id;

- DBG("adapter %p ep %p recreate CIG %d", info.adapter, ep, info.cig);
+ DBG("adapter %p setup %p recreate CIG %d", info.adapter, setup,
+ info.cig);

- if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET) {
- recreate_cig_ep(ep, &info);
+ if (setup->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET) {
+ recreate_cig_ep(setup->ep, &info);
return;
}

queue_foreach(sessions, recreate_cig_session, &info);
}

-static gboolean bap_io_disconnected(GIOChannel *io, GIOCondition cond,
+static gboolean setup_io_disconnected(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;

- DBG("ep %p recreate %s", ep, ep->recreate ? "true" : "false");
+ DBG("%p recreate %s", setup, setup->recreate ? "true" : "false");

- ep->io_id = 0;
+ setup->io_id = 0;

- bap_io_close(ep);
+ setup_io_close(setup, NULL);

/* Check if connecting recreate IO */
- if (!is_cig_busy(ep->data, ep->qos.ucast.cig_id))
- recreate_cig(ep);
+ if (!is_cig_busy(setup->ep->data, setup->qos.ucast.cig_id))
+ recreate_cig(setup);

return FALSE;
}
@@ -1597,25 +1659,25 @@ static gboolean bap_io_disconnected(GIOChannel *io, GIOCondition cond,
static void bap_connect_bcast_io_cb(GIOChannel *chan, GError *err,
gpointer user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;

- if (!ep->stream)
+ if (!setup->stream)
return;

- iso_connect_bcast_cb(chan, err, ep->stream);
+ iso_connect_bcast_cb(chan, err, setup->stream);
}

static void bap_connect_io_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_setup *setup = user_data;

- if (!ep->stream)
+ if (!setup->stream)
return;

- iso_connect_cb(chan, err, ep->stream);
+ iso_connect_cb(chan, err, setup->stream);
}

-static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
+static void setup_connect_io(struct bap_data *data, struct bap_setup *setup,
struct bt_bap_stream *stream,
struct bt_iso_qos *qos, int defer)
{
@@ -1626,39 +1688,40 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,

/* If IO already set skip creating it again */
if (bt_bap_stream_get_io(stream)) {
- DBG("ep %p stream %p has existing io", ep, stream);
+ DBG("setup %p stream %p has existing io", setup, stream);
return;
}

if (bt_bap_stream_io_is_connecting(stream, &fd)) {
- bap_accept_io(ep, stream, fd, defer);
+ setup_accept_io(setup, stream, fd, defer);
return;
}

/* If IO channel still up or CIG is busy, wait for it to be
* disconnected and then recreate.
*/
- if (ep->io || is_cig_busy(data, ep->qos.ucast.cig_id)) {
- DBG("ep %p stream %p defer %s wait recreate", ep, stream,
+ if (setup->io || is_cig_busy(data, setup->qos.ucast.cig_id)) {
+ DBG("setup %p stream %p defer %s wait recreate", setup, stream,
defer ? "true" : "false");
- ep->recreate = true;
+ setup->recreate = true;
return;
}

- if (ep->io_id) {
- g_source_remove(ep->io_id);
- ep->io_id = 0;
+ if (setup->io_id) {
+ g_source_remove(setup->io_id);
+ setup->io_id = 0;
}

- DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
+ DBG("setup %p stream %p defer %s", setup, stream,
+ defer ? "true" : "false");

- io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err,
+ io = bt_io_connect(bap_connect_io_cb, setup, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR,
btd_adapter_get_address(adapter),
BT_IO_OPT_DEST_BDADDR,
- device_get_address(ep->data->device),
+ device_get_address(data->device),
BT_IO_OPT_DEST_TYPE,
- device_get_le_address_type(ep->data->device),
+ device_get_le_address_type(data->device),
BT_IO_OPT_MODE, BT_IO_MODE_ISO,
BT_IO_OPT_QOS, qos,
BT_IO_OPT_DEFER_TIMEOUT, defer,
@@ -1669,18 +1732,19 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
return;
}

- ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- bap_io_disconnected, ep);
+ setup->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_io_disconnected, setup);

- ep->io = io;
- ep->cig_active = !defer;
+ setup->io = io;
+ setup->cig_active = !defer;

bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
}

-static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
- struct bt_bap_stream *stream,
- struct bt_iso_qos *qos)
+static void setup_connect_io_broadcast(struct bap_data *data,
+ struct bap_setup *setup,
+ struct bt_bap_stream *stream,
+ struct bt_iso_qos *qos)
{
struct btd_adapter *adapter = data->user_data;
GIOChannel *io = NULL;
@@ -1695,18 +1759,19 @@ static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
if (bt_bap_stream_get_io(stream))
return;

- if (ep->io_id) {
- g_source_remove(ep->io_id);
- ep->io_id = 0;
+ if (setup->io_id) {
+ g_source_remove(setup->io_id);
+ setup->io_id = 0;
}
- base.base_len = ep->base->iov_len;
+ base.base_len = setup->base->iov_len;

memset(base.base, 0, 248);
- memcpy(base.base, ep->base->iov_base, ep->base->iov_len);
- DBG("ep %p stream %p ", ep, stream);
+ memcpy(base.base, setup->base->iov_base, setup->base->iov_len);
ba2str(btd_adapter_get_address(adapter), addr);

- io = bt_io_connect(bap_connect_bcast_io_cb, ep, NULL, &err,
+ DBG("setup %p stream %p", setup, stream);
+
+ io = bt_io_connect(bap_connect_bcast_io_cb, setup, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR,
btd_adapter_get_address(adapter),
BT_IO_OPT_DEST_BDADDR,
@@ -1725,15 +1790,15 @@ static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
return;
}

- ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- bap_io_disconnected, ep);
+ setup->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_io_disconnected, setup);

- ep->io = io;
+ setup->io = io;

bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
}

-static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
+static void setup_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
struct bt_iso_qos *qos)
{
struct btd_adapter *adapter = device_get_adapter(data->device);
@@ -1765,8 +1830,10 @@ static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
data->listen_io = io;
}

-static void bap_listen_io_broadcast(struct bap_data *data, struct bap_ep *ep,
- struct bt_bap_stream *stream, struct bt_iso_qos *qos)
+static void setup_listen_io_broadcast(struct bap_data *data,
+ struct bap_setup *setup,
+ struct bt_bap_stream *stream,
+ struct bt_iso_qos *qos)
{
GIOChannel *io;
GError *err = NULL;
@@ -1784,9 +1851,9 @@ static void bap_listen_io_broadcast(struct bap_data *data, struct bap_ep *ep,
if (bt_bap_stream_get_io(stream) || data->listen_io)
return;

- io = bt_io_listen(NULL, iso_pa_sync_confirm_cb, ep->data, NULL, &err,
+ io = bt_io_listen(NULL, iso_pa_sync_confirm_cb, setup, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR,
- btd_adapter_get_address(ep->data->adapter),
+ btd_adapter_get_address(data->adapter),
BT_IO_OPT_DEST_BDADDR,
device_get_address(data->device),
BT_IO_OPT_DEST_TYPE,
@@ -1800,12 +1867,14 @@ static void bap_listen_io_broadcast(struct bap_data *data, struct bap_ep *ep,
error("%s", err->message);
g_error_free(err);
}
- ep->io = io;
- ep->data->listen_io = io;
+ setup->io = io;
+ data->listen_io = io;

}
-static void bap_create_ucast_io(struct bap_data *data, struct bap_ep *ep,
- struct bt_bap_stream *stream, int defer)
+static void setup_create_ucast_io(struct bap_data *data,
+ struct bap_setup *setup,
+ struct bt_bap_stream *stream,
+ int defer)
{
struct bt_bap_qos *qos[2] = {};
struct bt_iso_qos iso_qos;
@@ -1825,14 +1894,15 @@ static void bap_create_ucast_io(struct bap_data *data, struct bap_ep *ep,
bap_iso_qos(qos[0], &iso_qos.ucast.in);
bap_iso_qos(qos[1], &iso_qos.ucast.out);

- if (ep)
- bap_connect_io(data, ep, stream, &iso_qos, defer);
+ if (setup)
+ setup_connect_io(data, setup, stream, &iso_qos, defer);
else
- bap_listen_io(data, stream, &iso_qos);
+ setup_listen_io(data, stream, &iso_qos);
}

-static void bap_create_bcast_io(struct bap_data *data, struct bap_ep *ep,
- struct bt_bap_stream *stream, int defer)
+static void setup_create_bcast_io(struct bap_data *data,
+ struct bap_setup *setup,
+ struct bt_bap_stream *stream, int defer)
{
struct bt_iso_qos iso_qos;

@@ -1841,33 +1911,35 @@ static void bap_create_bcast_io(struct bap_data *data, struct bap_ep *ep,
if (!defer)
goto done;

- iso_qos.bcast.big = ep->qos.bcast.big;
- iso_qos.bcast.bis = ep->qos.bcast.bis;
- iso_qos.bcast.sync_factor = ep->qos.bcast.sync_factor;
- iso_qos.bcast.packing = ep->qos.bcast.packing;
- iso_qos.bcast.framing = ep->qos.bcast.framing;
- iso_qos.bcast.encryption = ep->qos.bcast.encryption;
- if (ep->qos.bcast.bcode)
- memcpy(iso_qos.bcast.bcode, ep->qos.bcast.bcode->iov_base, 16);
- iso_qos.bcast.options = ep->qos.bcast.options;
- iso_qos.bcast.skip = ep->qos.bcast.skip;
- iso_qos.bcast.sync_timeout = ep->qos.bcast.sync_timeout;
- iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;
- iso_qos.bcast.mse = ep->qos.bcast.mse;
- iso_qos.bcast.timeout = ep->qos.bcast.timeout;
- memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos,
+ iso_qos.bcast.big = setup->qos.bcast.big;
+ iso_qos.bcast.bis = setup->qos.bcast.bis;
+ iso_qos.bcast.sync_factor = setup->qos.bcast.sync_factor;
+ iso_qos.bcast.packing = setup->qos.bcast.packing;
+ iso_qos.bcast.framing = setup->qos.bcast.framing;
+ iso_qos.bcast.encryption = setup->qos.bcast.encryption;
+ if (setup->qos.bcast.bcode)
+ memcpy(iso_qos.bcast.bcode, setup->qos.bcast.bcode->iov_base,
+ 16);
+ iso_qos.bcast.options = setup->qos.bcast.options;
+ iso_qos.bcast.skip = setup->qos.bcast.skip;
+ iso_qos.bcast.sync_timeout = setup->qos.bcast.sync_timeout;
+ iso_qos.bcast.sync_cte_type = setup->qos.bcast.sync_cte_type;
+ iso_qos.bcast.mse = setup->qos.bcast.mse;
+ iso_qos.bcast.timeout = setup->qos.bcast.timeout;
+ memcpy(&iso_qos.bcast.out, &setup->qos.bcast.io_qos,
sizeof(struct bt_iso_io_qos));
done:
- if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE)
- bap_connect_io_broadcast(data, ep, stream, &iso_qos);
+ if (bt_bap_pac_get_type(setup->ep->lpac) == BT_BAP_BCAST_SOURCE)
+ setup_connect_io_broadcast(data, setup, stream, &iso_qos);
else
- bap_listen_io_broadcast(data, ep, stream, &iso_qos);
+ setup_listen_io_broadcast(data, setup, stream, &iso_qos);
}

-static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
+static void setup_create_io(struct bap_data *data, struct bap_setup *setup,
struct bt_bap_stream *stream, int defer)
{
- DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
+ DBG("setup %p stream %p defer %s", setup, stream,
+ defer ? "true" : "false");

if (!data->streams)
data->streams = queue_new();
@@ -1877,10 +1949,10 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep,

switch (bt_bap_stream_get_type(stream)) {
case BT_BAP_STREAM_TYPE_UCAST:
- bap_create_ucast_io(data, ep, stream, defer);
+ setup_create_ucast_io(data, setup, stream, defer);
break;
case BT_BAP_STREAM_TYPE_BCAST:
- bap_create_bcast_io(data, ep, stream, defer);
+ setup_create_bcast_io(data, setup, stream, defer);
break;
}
}
@@ -1889,7 +1961,7 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
uint8_t new_state, void *user_data)
{
struct bap_data *data = user_data;
- struct bap_ep *ep;
+ struct bap_setup *setup;

DBG("stream %p: %s(%u) -> %s(%u)", stream,
bt_bap_stream_statestr(old_state), old_state,
@@ -1902,21 +1974,20 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
if (new_state == old_state && new_state != BT_BAP_STREAM_STATE_CONFIG)
return;

- ep = bap_find_ep_by_stream(data, stream);
+ setup = bap_find_setup_by_stream(data, stream);

switch (new_state) {
case BT_BAP_STREAM_STATE_IDLE:
/* Release stream if idle */
- if (ep) {
- bap_io_close(ep);
- ep->stream = NULL;
- } else
+ if (setup)
+ setup_free(setup);
+ else
queue_remove(data->streams, stream);
break;
case BT_BAP_STREAM_STATE_CONFIG:
- if (ep && !ep->id) {
- bap_create_io(data, ep, stream, true);
- if (!ep->io) {
+ if (setup && !setup->id) {
+ setup_create_io(data, setup, stream, true);
+ if (!setup->io) {
error("Unable to create io");
if (old_state != BT_BAP_STREAM_STATE_RELEASING)
bt_bap_stream_release(stream, NULL,
@@ -1927,9 +1998,10 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
if (bt_bap_stream_get_type(stream) ==
BT_BAP_STREAM_TYPE_UCAST) {
/* Wait QoS response to respond */
- ep->id = bt_bap_stream_qos(stream, &ep->qos,
- qos_cb, ep);
- if (!ep->id) {
+ setup->id = bt_bap_stream_qos(stream,
+ &setup->qos,
+ qos_cb, setup);
+ if (!setup->id) {
error("Failed to Configure QoS");
bt_bap_stream_release(stream,
NULL, NULL);
@@ -1940,12 +2012,12 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
case BT_BAP_STREAM_STATE_QOS:
if (bt_bap_stream_get_type(stream) ==
BT_BAP_STREAM_TYPE_UCAST) {
- bap_create_io(data, ep, stream, true);
+ setup_create_io(data, setup, stream, true);
}
break;
case BT_BAP_STREAM_STATE_ENABLING:
- if (ep)
- bap_create_io(data, ep, stream, false);
+ if (setup)
+ setup_create_io(data, setup, stream, false);
break;
case BT_BAP_STREAM_STATE_STREAMING:
break;
@@ -2117,66 +2189,69 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
void *user_data)
{
struct bap_data *data = user_data;
- struct bap_ep *ep;
+ struct bap_setup *setup;
+ struct bt_bap_qos *qos;
GIOChannel *io;

if (!state)
return;

- ep = bap_find_ep_by_stream(data, stream);
- if (!ep)
+ setup = bap_find_setup_by_stream(data, stream);
+ if (!setup)
return;

- ep->recreate = false;
+ setup->recreate = false;
+ qos = &setup->qos;

- if (!ep->io) {
+ if (!setup->io) {
io = g_io_channel_unix_new(fd);
- ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- bap_io_disconnected, ep);
- ep->io = io;
+ setup->io_id = g_io_add_watch(io,
+ G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_io_disconnected, setup);
+ setup->io = io;
} else
- io = ep->io;
+ io = setup->io;

g_io_channel_set_close_on_unref(io, FALSE);

- switch (bt_bap_stream_get_type(ep->stream)) {
+ switch (bt_bap_stream_get_type(setup->stream)) {
case BT_BAP_STREAM_TYPE_UCAST:
/* Attempt to get CIG/CIS if they have not been set */
- if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
- ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
- struct bt_iso_qos qos;
+ if (qos->ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
+ qos->ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
+ struct bt_iso_qos iso_qos;

- if (!io_get_qos(io, &qos)) {
+ if (!io_get_qos(io, &iso_qos)) {
g_io_channel_unref(io);
return;
}

- ep->qos.ucast.cig_id = qos.ucast.cig;
- ep->qos.ucast.cis_id = qos.ucast.cis;
+ qos->ucast.cig_id = iso_qos.ucast.cig;
+ qos->ucast.cis_id = iso_qos.ucast.cis;
}

DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
- ep->qos.ucast.cig_id, ep->qos.ucast.cis_id);
+ qos->ucast.cig_id, qos->ucast.cis_id);
break;
case BT_BAP_STREAM_TYPE_BCAST:
/* Attempt to get BIG/BIS if they have not been set */
- if (ep->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
- ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
- struct bt_iso_qos qos;
+ if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
+ setup->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
+ struct bt_iso_qos iso_qos;

- if (!io_get_qos(io, &qos)) {
+ if (!io_get_qos(io, &iso_qos)) {
g_io_channel_unref(io);
return;
}

- ep->qos.bcast.big = qos.bcast.big;
- ep->qos.bcast.bis = qos.bcast.bis;
- bt_bap_stream_config(ep->stream, &ep->qos,
- ep->caps, NULL, NULL);
+ qos->bcast.big = iso_qos.bcast.big;
+ qos->bcast.bis = iso_qos.bcast.bis;
+ bt_bap_stream_config(setup->stream, qos, setup->caps,
+ NULL, NULL);
}

DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
- ep->qos.bcast.big, ep->qos.bcast.bis);
+ qos->bcast.big, qos->bcast.bis);
}
}

--
2.43.0



2023-12-11 21:25:43

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v4 4/6] shared/bap: Make bt_bap_select select a location

From: Luiz Augusto von Dentz <[email protected]>

This makes bt_bap_select select a location based on the PAC channel
count and PACS locations, this is then passed to the Endpoint as a
recommended ChannelAllocation.
---
profiles/audio/media.c | 6 ++-
src/shared/bap.c | 88 +++++++++++++++++++++++++++---------------
src/shared/bap.h | 2 +-
3 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 62f53defa7af..b17c555b63e4 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -921,7 +921,7 @@ done:
}

static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
- struct bt_bap_pac_qos *qos,
+ uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
bt_bap_pac_select_t cb, void *cb_data, void *user_data)
{
struct media_endpoint *endpoint = user_data;
@@ -969,6 +969,10 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
g_dbus_dict_append_entry(&dict, "Locations", DBUS_TYPE_UINT32,
&loc);

+ if (chan_alloc)
+ g_dbus_dict_append_entry(&dict, "ChannelAllocation",
+ DBUS_TYPE_UINT32, &chan_alloc);
+
if (metadata) {
key = "Metadata";
g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
diff --git a/src/shared/bap.c b/src/shared/bap.c
index cb505d1564d6..e1dad95aca99 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -177,6 +177,11 @@ struct bt_bap {
void *user_data;
};

+struct bt_bap_chan {
+ uint8_t count;
+ uint32_t location;
+};
+
struct bt_bap_pac {
struct bt_bap_db *bdb;
char *name;
@@ -185,7 +190,7 @@ struct bt_bap_pac {
struct bt_bap_pac_qos qos;
struct iovec *data;
struct iovec *metadata;
- struct queue *chan_map;
+ struct queue *channels;
struct bt_bap_pac_ops *ops;
void *user_data;
};
@@ -2422,19 +2427,22 @@ static void bap_pac_foreach_channel(size_t i, uint8_t l, uint8_t t, uint8_t *v,
void *user_data)
{
struct bt_bap_pac *pac = user_data;
+ struct bt_bap_chan *chan;

if (!v)
return;

- if (!pac->chan_map)
- pac->chan_map = queue_new();
+ if (!pac->channels)
+ pac->channels = queue_new();

- printf("PAC %p chan_map 0x%02x\n", pac, *v);
+ chan = new0(struct bt_bap_chan, 1);
+ chan->count = *v;
+ chan->location = bt_bap_pac_get_locations(pac) ? : pac->qos.location;

- queue_push_tail(pac->chan_map, UINT_TO_PTR(*v));
+ queue_push_tail(pac->channels, chan);
}

-static void bap_pac_update_chan_map(struct bt_bap_pac *pac, struct iovec *data)
+static void bap_pac_update_channels(struct bt_bap_pac *pac, struct iovec *data)
{
uint8_t type = 0x03;

@@ -2454,8 +2462,8 @@ static void bap_pac_merge(struct bt_bap_pac *pac, struct iovec *data,
else
pac->data = util_iov_dup(data, 1);

- /* Update channel map */
- bap_pac_update_chan_map(pac, data);
+ /* Update channels */
+ bap_pac_update_channels(pac, data);

/* Merge metadata into existing record */
if (pac->metadata)
@@ -2495,7 +2503,7 @@ static void bap_pac_free(void *data)
free(pac->name);
util_iov_free(pac->metadata, 1);
util_iov_free(pac->data, 1);
- queue_destroy(pac->chan_map, NULL);
+ queue_destroy(pac->channels, free);
free(pac);
}

@@ -4677,34 +4685,52 @@ int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
if (!lpac->ops || !lpac->ops->select)
return -EOPNOTSUPP;

- for (lchan = queue_get_entries(lpac->chan_map); lchan;
+ for (lchan = queue_get_entries(lpac->channels); lchan;
lchan = lchan->next) {
- uint8_t lmap = PTR_TO_UINT(lchan->data);
+ struct bt_bap_chan *lc = lchan->data;
+ uint8_t lmap = lc->count;
+ int i;

- for (rchan = queue_get_entries(rpac->chan_map); rchan;
- rchan = rchan->next) {
- uint8_t rmap = PTR_TO_UINT(rchan->data);
+ printf("lmap 0x%02x\n", lmap);

- printf("lmap 0x%02x rmap 0x%02x\n", lmap, rmap);
+ for (i = 0, rchan = queue_get_entries(rpac->channels); rchan;
+ rchan = rchan->next, i++) {
+ struct bt_bap_chan *rc = rchan->data;

- /* Try matching the channel mapping */
- if (lmap & rmap) {
- lpac->ops->select(lpac, rpac, &rpac->qos,
- func, user_data,
- lpac->user_data);
- if (count)
- (*count)++;
+ printf("rc->count 0x%02x\n", rc->count);

- /* Check if there are any channels left */
- lmap &= ~(lmap & rmap);
- if (!lmap)
- break;
-
- /* Check if device require AC*(i) settings */
- if (rmap == 0x01)
- lmap = lmap >> 1;
- } else
+ /* Try matching the channel count */
+ if (!(lmap & rc->count))
break;
+
+ /* Check if location was set otherwise attempt to
+ * assign one based on the number of channels it
+ * supports.
+ */
+ if (!rc->location) {
+ rc->location = bt_bap_pac_get_locations(rpac);
+ /* If channel count is 1 use a single
+ * location
+ */
+ if (rc->count == 0x01)
+ rc->location &= BIT(i);
+ }
+
+ lpac->ops->select(lpac, rpac, lc->location &
+ rc->location, &rpac->qos,
+ func, user_data,
+ lpac->user_data);
+ if (count)
+ (*count)++;
+
+ /* Check if there are any channels left to select */
+ lmap &= ~(lmap & rc->count);
+ if (!lmap)
+ break;
+
+ /* Check if device require AC*(i) settings */
+ if (rc->count == 0x01)
+ lmap = lmap >> 1;
}
}

diff --git a/src/shared/bap.h b/src/shared/bap.h
index 470313e66fc0..9be198cec72c 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -151,7 +151,7 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,

struct bt_bap_pac_ops {
int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
- struct bt_bap_pac_qos *qos,
+ uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
bt_bap_pac_select_t cb, void *cb_data, void *user_data);
int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
--
2.43.0


2023-12-11 21:25:47

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v4 5/6] shared/bap: Fix stream IO linking

From: Luiz Augusto von Dentz <[email protected]>

IO linking shall only be possible once, for the oposite direction as ISO
channels are bidirection, and not many times as that means multiplexing
would be used which is done within the transport payload, so this get rid
of queue links list and just use single link point instead.
---
profiles/audio/media.c | 6 +-
profiles/audio/transport.c | 43 +++++++----
src/shared/bap.c | 149 ++++++++++++-------------------------
src/shared/bap.h | 2 +-
4 files changed, 77 insertions(+), 123 deletions(-)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index b17c555b63e4..1faa1c28969f 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -921,7 +921,7 @@ done:
}

static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
- uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
+ uint32_t location, struct bt_bap_pac_qos *qos,
bt_bap_pac_select_t cb, void *cb_data, void *user_data)
{
struct media_endpoint *endpoint = user_data;
@@ -969,9 +969,9 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
g_dbus_dict_append_entry(&dict, "Locations", DBUS_TYPE_UINT32,
&loc);

- if (chan_alloc)
+ if (location)
g_dbus_dict_append_entry(&dict, "ChannelAllocation",
- DBUS_TYPE_UINT32, &chan_alloc);
+ DBUS_TYPE_UINT32, &location);

if (metadata) {
key = "Metadata";
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 23ea267f6446..e2073451cc7a 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -312,9 +312,12 @@ static void media_transport_remove_owner(struct media_transport *transport)
media_request_reply(owner->pending, EIO);

transport->owner = NULL;
- if (bap->linked)
- queue_foreach(bt_bap_stream_io_get_links(bap->stream),
- linked_transport_remove_owner, owner);
+ if (bap->linked) {
+ struct bt_bap_stream *link;
+
+ link = bt_bap_stream_io_get_link(bap->stream);
+ linked_transport_remove_owner(link, owner);
+ }

if (owner->watch)
g_dbus_remove_watch(btd_get_dbus_connection(), owner->watch);
@@ -496,9 +499,12 @@ static void media_transport_set_owner(struct media_transport *transport,
DBG("Transport %s Owner %s", transport->path, owner->name);
transport->owner = owner;

- if (bap->linked)
- queue_foreach(bt_bap_stream_io_get_links(bap->stream),
- linked_transport_set_owner, owner);
+ if (bap->linked) {
+ struct bt_bap_stream *link;
+
+ link = bt_bap_stream_io_get_link(bap->stream);
+ linked_transport_set_owner(link, owner);
+ }

owner->transport = transport;
owner->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
@@ -962,12 +968,15 @@ static gboolean links_exists(const GDBusPropertyTable *property, void *data)
return bap->linked;
}

-static void append_links(void *data, void *user_data)
+static void append_link(void *data, void *user_data)
{
struct bt_bap_stream *stream = data;
DBusMessageIter *array = user_data;
struct media_transport *transport;

+ if (!stream)
+ return;
+
transport = find_transport_by_bap_stream(stream);
if (!transport) {
error("Unable to find transport");
@@ -983,14 +992,14 @@ static gboolean get_links(const GDBusPropertyTable *property,
{
struct media_transport *transport = data;
struct bap_transport *bap = transport->data;
- struct queue *links = bt_bap_stream_io_get_links(bap->stream);
+ struct bt_bap_stream *link = bt_bap_stream_io_get_link(bap->stream);
DBusMessageIter array;

dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_TYPE_OBJECT_PATH_AS_STRING,
&array);

- queue_foreach(links, append_links, &array);
+ append_link(link, &array);

dbus_message_iter_close_container(iter, &array);

@@ -1280,15 +1289,15 @@ static bool match_link_transport(const void *data, const void *user_data)
static void bap_update_links(const struct media_transport *transport)
{
struct bap_transport *bap = transport->data;
- struct queue *links = bt_bap_stream_io_get_links(bap->stream);
+ struct bt_bap_stream *link = bt_bap_stream_io_get_link(bap->stream);

- if (bap->linked == !queue_isempty(links))
+ if (bap->linked == (!!link))
return;

- bap->linked = !queue_isempty(links);
+ bap->linked = link ? true : false;

/* Check if the links transport has been create yet */
- if (bap->linked && !queue_find(links, match_link_transport, NULL)) {
+ if (bap->linked && !match_link_transport(link, NULL)) {
bap->linked = false;
return;
}
@@ -1456,13 +1465,15 @@ static void set_state_bap(struct media_transport *transport,
transport_state_t state)
{
struct bap_transport *bap = transport->data;
+ struct bt_bap_stream *link;

if (!bap->linked)
return;

- /* Update links */
- queue_foreach(bt_bap_stream_io_get_links(bap->stream), link_set_state,
- UINT_TO_PTR(state));
+ link = bt_bap_stream_io_get_link(bap->stream);
+
+ /* Update link */
+ link_set_state(link, UINT_TO_PTR(state));
}

static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
diff --git a/src/shared/bap.c b/src/shared/bap.c
index e1dad95aca99..8add1348ec3c 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -222,7 +222,7 @@ struct bt_bap_stream {
struct iovec *cc;
struct iovec *meta;
struct bt_bap_qos qos;
- struct queue *links;
+ struct bt_bap_stream *link;
struct bt_bap_stream_io *io;
bool client;
void *user_data;
@@ -1010,14 +1010,6 @@ static void stream_io_unref(struct bt_bap_stream_io *io)
stream_io_free(io);
}

-static void bap_stream_unlink(void *data, void *user_data)
-{
- struct bt_bap_stream *link = data;
- struct bt_bap_stream *stream = user_data;
-
- queue_remove(link->links, stream);
-}
-
static void bap_stream_free(void *data)
{
struct bt_bap_stream *stream = data;
@@ -1025,8 +1017,9 @@ static void bap_stream_free(void *data)
if (stream->ep)
stream->ep->stream = NULL;

- queue_foreach(stream->links, bap_stream_unlink, stream);
- queue_destroy(stream->links, NULL);
+ if (stream->link)
+ stream->link->link = NULL;
+
stream_io_unref(stream->io);
util_iov_free(stream->cc, 1);
util_iov_free(stream->meta, 1);
@@ -1050,12 +1043,12 @@ static void bap_stream_detach(struct bt_bap_stream *stream)
bap_stream_free(stream);
}

-static void bap_stream_io_link(void *data, void *user_data)
+static bool bap_stream_io_link(const void *data, const void *user_data)
{
- struct bt_bap_stream *stream = data;
- struct bt_bap_stream *link = user_data;
+ struct bt_bap_stream *stream = (void *)data;
+ struct bt_bap_stream *link = (void *)user_data;

- bt_bap_stream_io_link(stream, link);
+ return !bt_bap_stream_io_link(stream, link);
}

static void bap_stream_update_io_links(struct bt_bap_stream *stream)
@@ -1064,7 +1057,7 @@ static void bap_stream_update_io_links(struct bt_bap_stream *stream)

DBG(bap, "stream %p", stream);

- queue_foreach(bap->streams, bap_stream_io_link, stream);
+ queue_find(bap->streams, bap_stream_io_link, stream);
}

static struct bt_bap_stream_io *stream_io_ref(struct bt_bap_stream_io *io)
@@ -1095,31 +1088,18 @@ static struct bt_bap_stream_io *stream_io_new(struct bt_bap *bap, int fd)
return stream_io_ref(sio);
}

-static void stream_find_io(void *data, void *user_data)
-{
- struct bt_bap_stream *stream = data;
- struct bt_bap_stream_io **io = user_data;
-
- if (*io)
- return;
-
- *io = stream->io;
-}
-
static struct bt_bap_stream_io *stream_get_io(struct bt_bap_stream *stream)
{
- struct bt_bap_stream_io *io;
-
if (!stream)
return NULL;

if (stream->io)
return stream->io;

- io = NULL;
- queue_foreach(stream->links, stream_find_io, &io);
+ if (stream->link)
+ return stream->link->io;

- return io;
+ return NULL;
}

static bool stream_io_disconnected(struct io *io, void *user_data);
@@ -1157,17 +1137,6 @@ static bool bap_stream_io_attach(struct bt_bap_stream *stream, int fd,
return true;
}

-static bool match_stream_io(const void *data, const void *user_data)
-{
- const struct bt_bap_stream *stream = data;
- const struct bt_bap_stream_io *io = user_data;
-
- if (!stream->io)
- return false;
-
- return stream->io == io;
-}
-
static bool bap_stream_io_detach(struct bt_bap_stream *stream)
{
struct bt_bap_stream *link;
@@ -1181,7 +1150,7 @@ static bool bap_stream_io_detach(struct bt_bap_stream *stream)
io = stream->io;
stream->io = NULL;

- link = queue_find(stream->links, match_stream_io, io);
+ link = stream->link;
if (link) {
/* Detach link if in QoS state */
if (link->ep->state == BT_ASCS_ASE_STATE_QOS)
@@ -2485,14 +2454,15 @@ static struct bt_bap_pac *bap_pac_new(struct bt_bap_db *bdb, const char *name,
pac->bdb = bdb;
pac->name = name ? strdup(name) : NULL;
pac->type = type;
+
if (codec)
pac->codec = *codec;

- bap_pac_merge(pac, data, metadata);
-
if (qos)
pac->qos = *qos;

+ bap_pac_merge(pac, data, metadata);
+
return pac;
}

@@ -4692,6 +4662,7 @@ int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
int i;

printf("lmap 0x%02x\n", lmap);
+ printf("lc->location 0x%02x\n", lc->location);

for (i = 0, rchan = queue_get_entries(rpac->channels); rchan;
rchan = rchan->next, i++) {
@@ -4714,6 +4685,8 @@ int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
*/
if (rc->count == 0x01)
rc->location &= BIT(i);
+
+ printf("rc->location 0x%02x\n", rc->location);
}

lpac->ops->select(lpac, rpac, lc->location &
@@ -4940,14 +4913,6 @@ static int bap_stream_metadata(struct bt_bap_stream *stream, uint8_t op,
return req->id;
}

-static void bap_stream_enable_link(void *data, void *user_data)
-{
- struct bt_bap_stream *stream = data;
- struct iovec *metadata = user_data;
-
- bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, NULL, NULL);
-}
-
unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
bool enable_links,
struct iovec *metadata,
@@ -4969,7 +4934,9 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
if (!ret || !enable_links)
return ret;

- queue_foreach(stream->links, bap_stream_enable_link, metadata);
+ if (stream->link)
+ bap_stream_metadata(stream->link, BT_ASCS_ENABLE,
+ metadata, NULL, NULL);
break;
case BT_BAP_STREAM_TYPE_BCAST:
if (!bt_bap_stream_io_dir(stream))
@@ -5032,26 +4999,6 @@ unsigned int bt_bap_stream_start(struct bt_bap_stream *stream,
return 0;
}

-static void bap_stream_disable_link(void *data, void *user_data)
-{
- struct bt_bap_stream *stream = data;
- struct bt_bap_req *req;
- struct iovec iov;
- struct bt_ascs_disable disable;
-
- memset(&disable, 0, sizeof(disable));
-
- disable.ase = stream->ep->id;
-
- iov.iov_base = &disable;
- iov.iov_len = sizeof(disable);
-
- req = bap_req_new(stream, BT_ASCS_DISABLE, &iov, 1, NULL, NULL);
-
- if (!bap_queue_req(stream->bap, req))
- bap_req_free(req);
-}
-
unsigned int bt_bap_stream_disable(struct bt_bap_stream *stream,
bool disable_links,
bt_bap_stream_func_t func,
@@ -5087,8 +5034,7 @@ unsigned int bt_bap_stream_disable(struct bt_bap_stream *stream,
}

if (disable_links)
- queue_foreach(stream->links, bap_stream_disable_link,
- NULL);
+ bt_bap_stream_disable(stream->link, false, NULL, NULL);

return req->id;

@@ -5295,7 +5241,8 @@ bool bt_bap_stream_set_io(struct bt_bap_stream *stream, int fd)

bap_stream_set_io(stream, INT_TO_PTR(fd));

- queue_foreach(stream->links, bap_stream_set_io, INT_TO_PTR(fd));
+ if (stream->link)
+ bap_stream_set_io(stream, INT_TO_PTR(fd));

return true;
}
@@ -5348,22 +5295,17 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
if (!stream || !link || stream == link)
return -EINVAL;

- if (queue_find(stream->links, NULL, link))
+ if (stream->link || link->link)
return -EALREADY;

if (stream->client != link->client ||
stream->qos.ucast.cig_id != link->qos.ucast.cig_id ||
- stream->qos.ucast.cis_id != link->qos.ucast.cis_id)
+ stream->qos.ucast.cis_id != link->qos.ucast.cis_id ||
+ stream->ep->dir == link->ep->dir)
return -EINVAL;

- if (!stream->links)
- stream->links = queue_new();
-
- if (!link->links)
- link->links = queue_new();
-
- queue_push_tail(stream->links, link);
- queue_push_tail(link->links, stream);
+ stream->link = link;
+ link->link = stream;

/* Link IOs if already set on stream/link */
if (stream->io && !link->io)
@@ -5376,12 +5318,12 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
return 0;
}

-struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream)
+struct bt_bap_stream *bt_bap_stream_io_get_link(struct bt_bap_stream *stream)
{
if (!stream)
return NULL;

- return stream->links;
+ return stream->link;
}

static void bap_stream_get_in_qos(void *data, void *user_data)
@@ -5389,6 +5331,9 @@ static void bap_stream_get_in_qos(void *data, void *user_data)
struct bt_bap_stream *stream = data;
struct bt_bap_qos **qos = user_data;

+ if (!stream)
+ return;
+
if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
!stream->qos.ucast.io_qos.sdu)
return;
@@ -5401,6 +5346,9 @@ static void bap_stream_get_out_qos(void *data, void *user_data)
struct bt_bap_stream *stream = data;
struct bt_bap_qos **qos = user_data;

+ if (!stream)
+ return;
+
if (!qos || *qos || stream->ep->dir != BT_BAP_SINK ||
!stream->qos.ucast.io_qos.sdu)
return;
@@ -5418,11 +5366,11 @@ bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
switch (stream->ep->dir) {
case BT_BAP_SOURCE:
bap_stream_get_in_qos(stream, in);
- queue_foreach(stream->links, bap_stream_get_out_qos, out);
+ bap_stream_get_out_qos(stream->link, out);
break;
case BT_BAP_SINK:
bap_stream_get_out_qos(stream, out);
- queue_foreach(stream->links, bap_stream_get_in_qos, in);
+ bap_stream_get_in_qos(stream->link, in);
break;
default:
return false;
@@ -5433,14 +5381,6 @@ bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
return in && out;
}

-static void bap_stream_get_dir(void *data, void *user_data)
-{
- struct bt_bap_stream *stream = data;
- uint8_t *dir = user_data;
-
- *dir |= stream->ep->dir;
-}
-
uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream)
{
uint8_t dir;
@@ -5450,7 +5390,8 @@ uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream)

dir = stream->ep->dir;

- queue_foreach(stream->links, bap_stream_get_dir, &dir);
+ if (stream->link)
+ dir |= stream->link->ep->dir;

return dir;
}
@@ -5461,6 +5402,9 @@ static void bap_stream_io_connecting(void *data, void *user_data)
int fd = PTR_TO_INT(user_data);
const struct queue_entry *entry;

+ if (!stream)
+ return;
+
if (fd >= 0)
bap_stream_io_attach(stream, fd, true);
else
@@ -5482,8 +5426,7 @@ int bt_bap_stream_io_connecting(struct bt_bap_stream *stream, int fd)
return -EINVAL;

bap_stream_io_connecting(stream, INT_TO_PTR(fd));
-
- queue_foreach(stream->links, bap_stream_io_connecting, INT_TO_PTR(fd));
+ bap_stream_io_connecting(stream->link, INT_TO_PTR(fd));

return 0;
}
diff --git a/src/shared/bap.h b/src/shared/bap.h
index 9be198cec72c..51edc08ab1ac 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -303,7 +303,7 @@ int bt_bap_stream_cancel(struct bt_bap_stream *stream, unsigned int id);

int bt_bap_stream_io_link(struct bt_bap_stream *stream,
struct bt_bap_stream *link);
-struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream);
+struct bt_bap_stream *bt_bap_stream_io_get_link(struct bt_bap_stream *stream);
bool bt_bap_stream_io_get_qos(struct bt_bap_stream *stream,
struct bt_bap_qos **in,
struct bt_bap_qos **out);
--
2.43.0


2023-12-11 21:26:03

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v4 6/6] client/player: Use ChannelAllocation given on SelectProperties

From: Luiz Augusto von Dentz <[email protected]>

This makes use of ChannelAllocation when present on SelectProperties
dictionary which is then passed on to bluetoothd and send over as part
of Codec Configuration:

< ACL Data TX: Handle 2048 flags 0x00 dlen 109
ATT: Write Command (0x52) len 104
Handle: 0x0098 Type: ASE Control Point (0x2bc6)
Data: 0104050202060000000010020103020201030428000503010000000
6020206000000001002010302020103042800050302000000010202060000
0000100201030202010304280005030100000002020206000000001002010
302020103042800050302000000
Opcode: Codec Configuration (0x01)
Number of ASE(s): 4
ASE: #0
ASE ID: 0x05
Target Latency: Balance Latency/Reliability (0x02)
PHY: 0x02
LE 2M PHY (0x02)
Codec: LC3 (0x06)
Codec Specific Configuration: #0: len 0x02 type 0x01
Sampling Frequency: 16 Khz (0x03)
Codec Specific Configuration: #1: len 0x02 type 0x02
Frame Duration: 10 ms (0x01)
Codec Specific Configuration: #2: len 0x03 type 0x04
Frame Length: 40 (0x0028)
Codec Specific Configuration: #3: len 0x05 type 0x03
Location: 0x00000001
Front Left (0x00000001)
ASE: #1
ASE ID: 0x06
Target Latency: Balance Latency/Reliability (0x02)
PHY: 0x02
LE 2M PHY (0x02)
Codec: LC3 (0x06)
Codec Specific Configuration: #0: len 0x02 type 0x01
Sampling Frequency: 16 Khz (0x03)
Codec Specific Configuration: #1: len 0x02 type 0x02
Frame Duration: 10 ms (0x01)
Codec Specific Configuration: #2: len 0x03 type 0x04
Frame Length: 40 (0x0028)
Codec Specific Configuration: #3: len 0x05 type 0x03
Location: 0x00000002
Front Right (0x00000002)
ASE: #2
ASE ID: 0x01
Target Latency: Balance Latency/Reliability (0x02)
PHY: 0x02
LE 2M PHY (0x02)
Codec: LC3 (0x06)
Codec Specific Configuration: #0: len 0x02 type 0x01
Sampling Frequency: 16 Khz (0x03)
Codec Specific Configuration: #1: len 0x02 type 0x02
Frame Duration: 10 ms (0x01)
Codec Specific Configuration: #2: len 0x03 type 0x04
Frame Length: 40 (0x0028)
Codec Specific Configuration: #3: len 0x05 type 0x03
Location: 0x00000001
Front Left (0x00000001)
ASE: #3
ASE ID: 0x02
Target Latency: Balance Latency/Reliability (0x02)
PHY: 0x02
LE 2M PHY (0x02)
Codec: LC3 (0x06)
Codec Specific Configuration: #0: len 0x02 type 0x01
Sampling Frequency: 16 Khz (0x03)
Codec Specific Configuration: #1: len 0x02 type 0x02
Frame Duration: 10 ms (0x01)
Codec Specific Configuration: #2: len 0x03 type 0x04
Frame Length: 40 (0x0028)
Codec Specific Configuration: #3: len 0x05 type 0x03
Location: 0x00000002
Front Right (0x00000002)
---
client/player.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/client/player.c b/client/player.c
index 4d49602c70d7..92fc91f920f3 100644
--- a/client/player.c
+++ b/client/player.c
@@ -64,7 +64,7 @@
#define SEC_USEC(_t) (_t * 1000000L)
#define TS_USEC(_ts) (SEC_USEC((_ts)->tv_sec) + NSEC_USEC((_ts)->tv_nsec))

-#define EP_SRC_LOCATIONS 0x00000001
+#define EP_SRC_LOCATIONS 0x00000003
#define EP_SNK_LOCATIONS 0x00000003

#define EP_SRC_CTXT 0x000f
@@ -2104,13 +2104,42 @@ static struct iovec *iov_append(struct iovec **iov, const void *data,
return *iov;
}

+static int parse_chan_alloc(DBusMessageIter *iter, uint32_t *location)
+{
+ while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
+ const char *key;
+ DBusMessageIter value, entry;
+ int var;
+
+ dbus_message_iter_recurse(iter, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ var = dbus_message_iter_get_arg_type(&value);
+
+ if (!strcasecmp(key, "ChannelAllocation")) {
+ if (var != DBUS_TYPE_UINT32)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, location);
+ return 0;
+ }
+
+ dbus_message_iter_next(iter);
+ }
+
+ return -EINVAL;
+}
+
static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
DBusMessage *msg,
struct codec_preset *preset)
{
DBusMessage *reply;
- DBusMessageIter iter;
+ DBusMessageIter iter, props;
struct endpoint_config *cfg;
+ uint32_t location = 0;

if (!preset)
return NULL;
@@ -2126,6 +2155,18 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
cfg->target_latency = preset->target_latency;

+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_recurse(&iter, &props);
+
+ if (!parse_chan_alloc(&props, &location)) {
+ uint8_t chan_alloc_ltv[] = {
+ 0x05, LC3_CONFIG_CHAN_ALLOC, location & 0xff,
+ location >> 8, location >> 16, location >> 24
+ };
+
+ iov_append(&cfg->caps, &chan_alloc_ltv, sizeof(chan_alloc_ltv));
+ }
+
/* Copy metadata */
if (ep->meta)
iov_append(&cfg->meta, ep->meta->iov_base, ep->meta->iov_len);
--
2.43.0


2023-12-11 23:31:31

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per endpoint

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

---Test result---

Test Summary:
CheckPatch PASS 2.70 seconds
GitLint FAIL 1.73 seconds
BuildEll PASS 24.71 seconds
BluezMake PASS 780.94 seconds
MakeCheck PASS 12.60 seconds
MakeDistcheck PASS 164.82 seconds
CheckValgrind PASS 225.11 seconds
CheckSmatch PASS 330.30 seconds
bluezmakeextell PASS 103.81 seconds
IncrementalBuild PASS 4181.08 seconds
ScanBuild WARNING 990.81 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v4,2/6] shared/bap: Make bt_bap_select match the channel map

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
13: B3 Line contains hard tab characters (\t): " 0000a0201030202010304280001020206000000000a020103020201030428"
14: B3 Line contains hard tab characters (\t): " 0002020206000000000a02010302020103042800"
[BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (81>80): "[BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties"
[BlueZ,v4,6/6] client/player: Use ChannelAllocation given on SelectProperties

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
13: B3 Line contains hard tab characters (\t): " 6020206000000001002010302020103042800050302000000010202060000"
14: B3 Line contains hard tab characters (\t): " 0000100201030202010304280005030100000002020206000000001002010"
15: B3 Line contains hard tab characters (\t): " 302020103042800050302000000"
##############################
Test: ScanBuild - WARNING
Desc: Run Scan Build
Output:
src/shared/bap.c:4766:23: warning: Access to field 'type' results in a dereference of a null pointer (loaded from variable 'lpac')
if (!match.rpac && (lpac->type != BT_BAP_BCAST_SOURCE))
^~~~~~~~~~
1 warning generated.
In file included from tools/mesh-gatt/crypto.c:32:
./src/shared/util.h:228:9: warning: 1st function call argument is an uninitialized value
return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
#define be32_to_cpu(val) bswap_32(val)
^~~~~~~~~~~~~
/usr/include/byteswap.h:34:21: note: expanded from macro 'bswap_32'
#define bswap_32(x) __bswap_32 (x)
^~~~~~~~~~~~~~
In file included from tools/mesh-gatt/crypto.c:32:
./src/shared/util.h:238:9: warning: 1st function call argument is an uninitialized value
return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
#define be64_to_cpu(val) bswap_64(val)
^~~~~~~~~~~~~
/usr/include/byteswap.h:37:21: note: expanded from macro 'bswap_64'
#define bswap_64(x) __bswap_64 (x)
^~~~~~~~~~~~~~
2 warnings generated.



---
Regards,
Linux Bluetooth

2023-12-12 17:54:38

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per endpoint

Hi,

On Mon, Dec 11, 2023 at 6:31 PM <[email protected]> wrote:
>
> 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=808938

Could one of you guys please verify that this set doesn't break
anything related to broadcast.

> ---Test result---
>
> Test Summary:
> CheckPatch PASS 2.70 seconds
> GitLint FAIL 1.73 seconds
> BuildEll PASS 24.71 seconds
> BluezMake PASS 780.94 seconds
> MakeCheck PASS 12.60 seconds
> MakeDistcheck PASS 164.82 seconds
> CheckValgrind PASS 225.11 seconds
> CheckSmatch PASS 330.30 seconds
> bluezmakeextell PASS 103.81 seconds
> IncrementalBuild PASS 4181.08 seconds
> ScanBuild WARNING 990.81 seconds
>
> Details
> ##############################
> Test: GitLint - FAIL
> Desc: Run gitlint
> Output:
> [BlueZ,v4,2/6] shared/bap: Make bt_bap_select match the channel map
>
> WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
> 13: B3 Line contains hard tab characters (\t): " 0000a0201030202010304280001020206000000000a020103020201030428"
> 14: B3 Line contains hard tab characters (\t): " 0002020206000000000a02010302020103042800"
> [BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties
>
> WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
> 1: T1 Title exceeds max length (81>80): "[BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties"
> [BlueZ,v4,6/6] client/player: Use ChannelAllocation given on SelectProperties
>
> WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
> 13: B3 Line contains hard tab characters (\t): " 6020206000000001002010302020103042800050302000000010202060000"
> 14: B3 Line contains hard tab characters (\t): " 0000100201030202010304280005030100000002020206000000001002010"
> 15: B3 Line contains hard tab characters (\t): " 302020103042800050302000000"
> ##############################
> Test: ScanBuild - WARNING
> Desc: Run Scan Build
> Output:
> src/shared/bap.c:4766:23: warning: Access to field 'type' results in a dereference of a null pointer (loaded from variable 'lpac')
> if (!match.rpac && (lpac->type != BT_BAP_BCAST_SOURCE))
> ^~~~~~~~~~
> 1 warning generated.
> In file included from tools/mesh-gatt/crypto.c:32:
> ./src/shared/util.h:228:9: warning: 1st function call argument is an uninitialized value
> return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
> #define be32_to_cpu(val) bswap_32(val)
> ^~~~~~~~~~~~~
> /usr/include/byteswap.h:34:21: note: expanded from macro 'bswap_32'
> #define bswap_32(x) __bswap_32 (x)
> ^~~~~~~~~~~~~~
> In file included from tools/mesh-gatt/crypto.c:32:
> ./src/shared/util.h:238:9: warning: 1st function call argument is an uninitialized value
> return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
> #define be64_to_cpu(val) bswap_64(val)
> ^~~~~~~~~~~~~
> /usr/include/byteswap.h:37:21: note: expanded from macro 'bswap_64'
> #define bswap_64(x) __bswap_64 (x)
> ^~~~~~~~~~~~~~
> 2 warnings generated.
>
>
>
> ---
> Regards,
> Linux Bluetooth
>


--
Luiz Augusto von Dentz

2023-12-13 15:56:29

by Iulia Tanasescu

[permalink] [raw]
Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per endpoint

Hi Luiz,

> -----Original Message-----
> From: Luiz Augusto von Dentz <[email protected]>
> Sent: Tuesday, December 12, 2023 7:54 PM
> To: [email protected]
> Cc: Iulia Tanasescu <[email protected]>; Silviu Florian Barbulescu
> <[email protected]>; Claudia Cristina Draghicescu
> <[email protected]>
> Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per
> endpoint
>
> Hi,
>
> On Mon, Dec 11, 2023 at 6:31 PM <[email protected]> wrote:
> >
> > 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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> >
> Fpatchwork.kernel.org%2Fproject%2Fbluetooth%2Flist%2F%3Fseries%3D808
> 93
> >
> 8&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67
> d08dbf
> >
> b3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800
> 0462083582
> >
> 0%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiL
> CJBTiI6
> >
> Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=aKuHEA2BNmk3B%
> 2BztdPJ2Mhl
> > X1443Ki34d5537bCZuhE%3D&reserved=0
>
> Could one of you guys please verify that this set doesn't break anything
> related to broadcast.
>

I tested this patch series for broadcast and I found two issues:

First, in bap_find_setup_by_stream, for the BT_BAP_STREAM_TYPE_BCAST
case, the function returns a pointer to an endpoint, although it's
expected to return a pointer to the setup matching the stream.
So it should be something similar to the unicast case:

ep = queue_find(data->bcast, match_ep_stream, stream);
if (ep)
return queue_find(ep->setups, match_setup_stream,
stream);

Second, in set_configuration, after allocating a setup using
setup_new, you should also allocate setup->base:

setup->base = new0(struct iovec, 1).

Otherwise, the configuration will not be parsed correctly for
broadcast.

We have also prepared a patch series for broadcast multiple BISes
support, but we will have to update our implementation based on
these patches.

> > ---Test result---
> >
> > Test Summary:
> > CheckPatch PASS 2.70 seconds
> > GitLint FAIL 1.73 seconds
> > BuildEll PASS 24.71 seconds
> > BluezMake PASS 780.94 seconds
> > MakeCheck PASS 12.60 seconds
> > MakeDistcheck PASS 164.82 seconds
> > CheckValgrind PASS 225.11 seconds
> > CheckSmatch PASS 330.30 seconds
> > bluezmakeextell PASS 103.81 seconds
> > IncrementalBuild PASS 4181.08 seconds
> > ScanBuild WARNING 990.81 seconds
> >
> > Details
> > ##############################
> > Test: GitLint - FAIL
> > Desc: Run gitlint
> > Output:
> > [BlueZ,v4,2/6] shared/bap: Make bt_bap_select match the channel map
> >
> > WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python
> regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> Please review your ignore-body-lines.regex option accordingly. To remove
> this warning, set general.regex-style-search=True. More details:
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisro
> overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447d
> be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&res
> erved=0
> > 13: B3 Line contains hard tab characters (\t): "
> 0000a0201030202010304280001020206000000000a02010302020103042
> 8"
> > 14: B3 Line contains hard tab characters (\t): "
> 0002020206000000000a02010302020103042800"
> > [BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to
> > SelectProperties
> >
> > WARNING: I3 - ignore-body-lines: gitlint will be switching from using
> > Python regex 'match' (match beginning) to 'search' (match anywhere)
> > semantics. Please review your ignore-body-lines.regex option
> > accordingly. To remove this warning, set
> > general.regex-style-search=True. More details:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjori
> > sroovers.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-search&d
> >
> ata=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67d08
> dbfb3b
> >
> 5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800046
> 20835820%7
> >
> CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBT
> iI6Ik1
> >
> haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=GaHyvhsb4TOR1ksh3K
> cJ7f%2BLCN
> > 4JynFFoQdFs1cd2d8%3D&reserved=0
> > 1: T1 Title exceeds max length (81>80): "[BlueZ,v4,3/6]
> org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties"
> > [BlueZ,v4,6/6] client/player: Use ChannelAllocation given on
> > SelectProperties
> >
> > WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python
> regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> Please review your ignore-body-lines.regex option accordingly. To remove
> this warning, set general.regex-style-search=True. More details:
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisro
> overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447d
> be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&res
> erved=0
> > 13: B3 Line contains hard tab characters (\t): "
> 602020600000000100201030202010304280005030200000001020206000
> 0"
> > 14: B3 Line contains hard tab characters (\t): "
> 000010020103020201030428000503010000000202020600000000100201
> 0"
> > 15: B3 Line contains hard tab characters (\t): "
> 302020103042800050302000000"
> > ##############################
> > Test: ScanBuild - WARNING
> > Desc: Run Scan Build
> > Output:
> > src/shared/bap.c:4766:23: warning: Access to field 'type' results in a
> dereference of a null pointer (loaded from variable 'lpac')
> > if (!match.rpac && (lpac->type != BT_BAP_BCAST_SOURCE))
> > ^~~~~~~~~~
> > 1 warning generated.
> > In file included from tools/mesh-gatt/crypto.c:32:
> > ./src/shared/util.h:228:9: warning: 1st function call argument is an
> uninitialized value
> > return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
> > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > ./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
> > #define be32_to_cpu(val) bswap_32(val)
> > ^~~~~~~~~~~~~
> > /usr/include/byteswap.h:34:21: note: expanded from macro 'bswap_32'
> > #define bswap_32(x) __bswap_32 (x)
> > ^~~~~~~~~~~~~~
> > In file included from tools/mesh-gatt/crypto.c:32:
> > ./src/shared/util.h:238:9: warning: 1st function call argument is an
> uninitialized value
> > return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
> > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > ./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
> > #define be64_to_cpu(val) bswap_64(val)
> > ^~~~~~~~~~~~~
> > /usr/include/byteswap.h:37:21: note: expanded from macro 'bswap_64'
> > #define bswap_64(x) __bswap_64 (x)
> > ^~~~~~~~~~~~~~
> > 2 warnings generated.
> >
> >
> >
> > ---
> > Regards,
> > Linux Bluetooth
> >
>
>
> --
> Luiz Augusto von Dentz


Regards,
Iulia


2023-12-13 16:08:18

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per endpoint

Hi Iulia,

On Wed, Dec 13, 2023 at 10:56 AM Iulia Tanasescu
<[email protected]> wrote:
>
> Hi Luiz,
>
> > -----Original Message-----
> > From: Luiz Augusto von Dentz <[email protected]>
> > Sent: Tuesday, December 12, 2023 7:54 PM
> > To: [email protected]
> > Cc: Iulia Tanasescu <[email protected]>; Silviu Florian Barbulescu
> > <[email protected]>; Claudia Cristina Draghicescu
> > <[email protected]>
> > Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per
> > endpoint
> >
> > Hi,
> >
> > On Mon, Dec 11, 2023 at 6:31 PM <[email protected]> wrote:
> > >
> > > 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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> > >
> > Fpatchwork.kernel.org%2Fproject%2Fbluetooth%2Flist%2F%3Fseries%3D808
> > 93
> > >
> > 8&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67
> > d08dbf
> > >
> > b3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800
> > 0462083582
> > >
> > 0%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiL
> > CJBTiI6
> > >
> > Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=aKuHEA2BNmk3B%
> > 2BztdPJ2Mhl
> > > X1443Ki34d5537bCZuhE%3D&reserved=0
> >
> > Could one of you guys please verify that this set doesn't break anything
> > related to broadcast.
> >
>
> I tested this patch series for broadcast and I found two issues:
>
> First, in bap_find_setup_by_stream, for the BT_BAP_STREAM_TYPE_BCAST
> case, the function returns a pointer to an endpoint, although it's
> expected to return a pointer to the setup matching the stream.
> So it should be something similar to the unicast case:
>
> ep = queue_find(data->bcast, match_ep_stream, stream);
> if (ep)
> return queue_find(ep->setups, match_setup_stream,
> stream);

Ok, I will fix that.

> Second, in set_configuration, after allocating a setup using
> setup_new, you should also allocate setup->base:
>
> setup->base = new0(struct iovec, 1).

Doesn't the base use util_iov_dup? Perhaps we need an update to code
to start using that.

> Otherwise, the configuration will not be parsed correctly for
> broadcast.
>
> We have also prepared a patch series for broadcast multiple BISes
> support, but we will have to update our implementation based on
> these patches.

While at it, perhaps it would be great to create a sample script to
test broadcast with bluetoothctl.

> > > ---Test result---
> > >
> > > Test Summary:
> > > CheckPatch PASS 2.70 seconds
> > > GitLint FAIL 1.73 seconds
> > > BuildEll PASS 24.71 seconds
> > > BluezMake PASS 780.94 seconds
> > > MakeCheck PASS 12.60 seconds
> > > MakeDistcheck PASS 164.82 seconds
> > > CheckValgrind PASS 225.11 seconds
> > > CheckSmatch PASS 330.30 seconds
> > > bluezmakeextell PASS 103.81 seconds
> > > IncrementalBuild PASS 4181.08 seconds
> > > ScanBuild WARNING 990.81 seconds
> > >
> > > Details
> > > ##############################
> > > Test: GitLint - FAIL
> > > Desc: Run gitlint
> > > Output:
> > > [BlueZ,v4,2/6] shared/bap: Make bt_bap_select match the channel map
> > >
> > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python
> > regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> > Please review your ignore-body-lines.regex option accordingly. To remove
> > this warning, set general.regex-style-search=True. More details:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisro
> > overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> > search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447d
> > be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> > AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> > C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&res
> > erved=0
> > > 13: B3 Line contains hard tab characters (\t): "
> > 0000a0201030202010304280001020206000000000a02010302020103042
> > 8"
> > > 14: B3 Line contains hard tab characters (\t): "
> > 0002020206000000000a02010302020103042800"
> > > [BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to
> > > SelectProperties
> > >
> > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using
> > > Python regex 'match' (match beginning) to 'search' (match anywhere)
> > > semantics. Please review your ignore-body-lines.regex option
> > > accordingly. To remove this warning, set
> > > general.regex-style-search=True. More details:
> > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjori
> > > sroovers.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-search&d
> > >
> > ata=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67d08
> > dbfb3b
> > >
> > 5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800046
> > 20835820%7
> > >
> > CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBT
> > iI6Ik1
> > >
> > haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=GaHyvhsb4TOR1ksh3K
> > cJ7f%2BLCN
> > > 4JynFFoQdFs1cd2d8%3D&reserved=0
> > > 1: T1 Title exceeds max length (81>80): "[BlueZ,v4,3/6]
> > org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties"
> > > [BlueZ,v4,6/6] client/player: Use ChannelAllocation given on
> > > SelectProperties
> > >
> > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python
> > regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> > Please review your ignore-body-lines.regex option accordingly. To remove
> > this warning, set general.regex-style-search=True. More details:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisro
> > overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> > search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447d
> > be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> > AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> > C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&res
> > erved=0
> > > 13: B3 Line contains hard tab characters (\t): "
> > 602020600000000100201030202010304280005030200000001020206000
> > 0"
> > > 14: B3 Line contains hard tab characters (\t): "
> > 000010020103020201030428000503010000000202020600000000100201
> > 0"
> > > 15: B3 Line contains hard tab characters (\t): "
> > 302020103042800050302000000"
> > > ##############################
> > > Test: ScanBuild - WARNING
> > > Desc: Run Scan Build
> > > Output:
> > > src/shared/bap.c:4766:23: warning: Access to field 'type' results in a
> > dereference of a null pointer (loaded from variable 'lpac')
> > > if (!match.rpac && (lpac->type != BT_BAP_BCAST_SOURCE))
> > > ^~~~~~~~~~
> > > 1 warning generated.
> > > In file included from tools/mesh-gatt/crypto.c:32:
> > > ./src/shared/util.h:228:9: warning: 1st function call argument is an
> > uninitialized value
> > > return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
> > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
> > > #define be32_to_cpu(val) bswap_32(val)
> > > ^~~~~~~~~~~~~
> > > /usr/include/byteswap.h:34:21: note: expanded from macro 'bswap_32'
> > > #define bswap_32(x) __bswap_32 (x)
> > > ^~~~~~~~~~~~~~
> > > In file included from tools/mesh-gatt/crypto.c:32:
> > > ./src/shared/util.h:238:9: warning: 1st function call argument is an
> > uninitialized value
> > > return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
> > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
> > > #define be64_to_cpu(val) bswap_64(val)
> > > ^~~~~~~~~~~~~
> > > /usr/include/byteswap.h:37:21: note: expanded from macro 'bswap_64'
> > > #define bswap_64(x) __bswap_64 (x)
> > > ^~~~~~~~~~~~~~
> > > 2 warnings generated.
> > >
> > >
> > >
> > > ---
> > > Regards,
> > > Linux Bluetooth
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
>
>
> Regards,
> Iulia
>


--
Luiz Augusto von Dentz

2023-12-14 16:24:51

by Iulia Tanasescu

[permalink] [raw]
Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per endpoint

Hi Luiz,

> -----Original Message-----
> From: Luiz Augusto von Dentz <[email protected]>
> Sent: Wednesday, December 13, 2023 6:08 PM
> To: Iulia Tanasescu <[email protected]>
> Cc: Claudia Cristina Draghicescu <[email protected]>; linux-
> [email protected]; Silviu Florian Barbulescu
> <[email protected]>
> Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per
> endpoint
>
> Hi Iulia,
>
> On Wed, Dec 13, 2023 at 10:56 AM Iulia Tanasescu
> <[email protected]> wrote:
> >
> > Hi Luiz,
> >
> > > -----Original Message-----
> > > From: Luiz Augusto von Dentz <[email protected]>
> > > Sent: Tuesday, December 12, 2023 7:54 PM
> > > To: [email protected]
> > > Cc: Iulia Tanasescu <[email protected]>; Silviu Florian
> Barbulescu
> > > <[email protected]>; Claudia Cristina Draghicescu
> > > <[email protected]>
> > > Subject: Re: [BlueZ,v4,1/6] bap: Allow setup of multiple stream per
> > > endpoint
> > >
> > > Hi,
> > >
> > > On Mon, Dec 11, 2023 at 6:31 PM <[email protected]> wrote:
> > > >
> > > > 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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> > > >
> > >
> Fpatchwork.kernel.org%2Fproject%2Fbluetooth%2Flist%2F%3Fseries%3D808
> > > 93
> > > >
> > >
> 8&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67
> > > d08dbf
> > > >
> > >
> b3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800
> > > 0462083582
> > > >
> > >
> 0%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIi
> L
> > > CJBTiI6
> > > >
> > >
> Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=aKuHEA2BNmk3B%
> > > 2BztdPJ2Mhl
> > > > X1443Ki34d5537bCZuhE%3D&reserved=0
> > >
> > > Could one of you guys please verify that this set doesn't break anything
> > > related to broadcast.
> > >
> >
> > I tested this patch series for broadcast and I found two issues:
> >
> > First, in bap_find_setup_by_stream, for the
> BT_BAP_STREAM_TYPE_BCAST
> > case, the function returns a pointer to an endpoint, although it's
> > expected to return a pointer to the setup matching the stream.
> > So it should be something similar to the unicast case:
> >
> > ep = queue_find(data->bcast, match_ep_stream, stream);
> > if (ep)
> > return queue_find(ep->setups, match_setup_stream,
> > stream);
>
> Ok, I will fix that.
>
> > Second, in set_configuration, after allocating a setup using
> > setup_new, you should also allocate setup->base:
> >
> > setup->base = new0(struct iovec, 1).
>
> Doesn't the base use util_iov_dup? Perhaps we need an update to code
> to start using that.

Our patch for multiple bis support will include updates regarding
base processing, so this will be updated soon.

>
> > Otherwise, the configuration will not be parsed correctly for
> > broadcast.
> >
> > We have also prepared a patch series for broadcast multiple BISes
> > support, but we will have to update our implementation based on
> > these patches.
>
> While at it, perhaps it would be great to create a sample script to
> test broadcast with bluetoothctl.
>
> > > > ---Test result---
> > > >
> > > > Test Summary:
> > > > CheckPatch PASS 2.70 seconds
> > > > GitLint FAIL 1.73 seconds
> > > > BuildEll PASS 24.71 seconds
> > > > BluezMake PASS 780.94 seconds
> > > > MakeCheck PASS 12.60 seconds
> > > > MakeDistcheck PASS 164.82 seconds
> > > > CheckValgrind PASS 225.11 seconds
> > > > CheckSmatch PASS 330.30 seconds
> > > > bluezmakeextell PASS 103.81 seconds
> > > > IncrementalBuild PASS 4181.08 seconds
> > > > ScanBuild WARNING 990.81 seconds
> > > >
> > > > Details
> > > > ##############################
> > > > Test: GitLint - FAIL
> > > > Desc: Run gitlint
> > > > Output:
> > > > [BlueZ,v4,2/6] shared/bap: Make bt_bap_select match the channel
> map
> > > >
> > > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using
> Python
> > > regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> > > Please review your ignore-body-lines.regex option accordingly. To
> remove
> > > this warning, set general.regex-style-search=True. More details:
> > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisr
> o%2F&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7Ca4106b62fbbc421
> ba8b408dbfbf5aeb3%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7
> C638380804836966878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw
> MDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%
> 7C&sdata=XrUOmCiSuOT8hJl4%2BSDQDcFReZKgwEzLJOIls5n18J0%3D&reserv
> ed=0
> > > overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> > >
> search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447
> d
> > > be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > > %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4
> wLj
> > >
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> > >
> C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&re
> s
> > > erved=0
> > > > 13: B3 Line contains hard tab characters (\t): "
> > > 0000a0201030202010304280001020206000000000a02010302020103042
> > > 8"
> > > > 14: B3 Line contains hard tab characters (\t): "
> > > 0002020206000000000a02010302020103042800"
> > > > [BlueZ,v4,3/6] org.bluez.MediaEndpoint: Add ChannelAllocation to
> > > > SelectProperties
> > > >
> > > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using
> > > > Python regex 'match' (match beginning) to 'search' (match anywhere)
> > > > semantics. Please review your ignore-body-lines.regex option
> > > > accordingly. To remove this warning, set
> > > > general.regex-style-search=True. More details:
> > > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjori%
> 2F&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7Ca4106b62fbbc421ba8
> b408dbfbf5aeb3%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638
> 380804836966878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAi
> LCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&s
> data=5dVv5DQNrxG9SDq5M3hdYZA0w4zglb08FgIHpo0yfag%3D&reserved=0
> > > > sroovers.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> search&d
> > > >
> > >
> ata=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447dbe67d08
> > > dbfb3b
> > > >
> > >
> 5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6383800046
> > > 20835820%7
> > > >
> > >
> CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJB
> T
> > > iI6Ik1
> > > >
> > >
> haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=GaHyvhsb4TOR1ksh3
> K
> > > cJ7f%2BLCN
> > > > 4JynFFoQdFs1cd2d8%3D&reserved=0
> > > > 1: T1 Title exceeds max length (81>80): "[BlueZ,v4,3/6]
> > > org.bluez.MediaEndpoint: Add ChannelAllocation to SelectProperties"
> > > > [BlueZ,v4,6/6] client/player: Use ChannelAllocation given on
> > > > SelectProperties
> > > >
> > > > WARNING: I3 - ignore-body-lines: gitlint will be switching from using
> Python
> > > regex 'match' (match beginning) to 'search' (match anywhere) semantics.
> > > Please review your ignore-body-lines.regex option accordingly. To
> remove
> > > this warning, set general.regex-style-search=True. More details:
> > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fjorisr
> o%2F&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7Ca4106b62fbbc421
> ba8b408dbfbf5aeb3%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7
> C638380804836966878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw
> MDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%
> 7C&sdata=XrUOmCiSuOT8hJl4%2BSDQDcFReZKgwEzLJOIls5n18J0%3D&reserv
> ed=0
> > > overs.github.io%2Fgitlint%2Fconfiguration%2F%23regex-style-
> > >
> search&data=05%7C02%7Ciulia.tanasescu%40nxp.com%7C75f2033d3e9447
> d
> > > be67d08dbfb3b5e2e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > > %7C638380004620835820%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4
> wLj
> > >
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7
> > >
> C%7C&sdata=GaHyvhsb4TOR1ksh3KcJ7f%2BLCN4JynFFoQdFs1cd2d8%3D&re
> s
> > > erved=0
> > > > 13: B3 Line contains hard tab characters (\t): "
> > > 602020600000000100201030202010304280005030200000001020206000
> > > 0"
> > > > 14: B3 Line contains hard tab characters (\t): "
> > > 000010020103020201030428000503010000000202020600000000100201
> > > 0"
> > > > 15: B3 Line contains hard tab characters (\t): "
> > > 302020103042800050302000000"
> > > > ##############################
> > > > Test: ScanBuild - WARNING
> > > > Desc: Run Scan Build
> > > > Output:
> > > > src/shared/bap.c:4766:23: warning: Access to field 'type' results in a
> > > dereference of a null pointer (loaded from variable 'lpac')
> > > > if (!match.rpac && (lpac->type != BT_BAP_BCAST_SOURCE))
> > > > ^~~~~~~~~~
> > > > 1 warning generated.
> > > > In file included from tools/mesh-gatt/crypto.c:32:
> > > > ./src/shared/util.h:228:9: warning: 1st function call argument is an
> > > uninitialized value
> > > > return be32_to_cpu(get_unaligned((const uint32_t *) ptr));
> > > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > > ./src/shared/util.h:33:26: note: expanded from macro 'be32_to_cpu'
> > > > #define be32_to_cpu(val) bswap_32(val)
> > > > ^~~~~~~~~~~~~
> > > > /usr/include/byteswap.h:34:21: note: expanded from macro
> 'bswap_32'
> > > > #define bswap_32(x) __bswap_32 (x)
> > > > ^~~~~~~~~~~~~~
> > > > In file included from tools/mesh-gatt/crypto.c:32:
> > > > ./src/shared/util.h:238:9: warning: 1st function call argument is an
> > > uninitialized value
> > > > return be64_to_cpu(get_unaligned((const uint64_t *) ptr));
> > > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > > ./src/shared/util.h:34:26: note: expanded from macro 'be64_to_cpu'
> > > > #define be64_to_cpu(val) bswap_64(val)
> > > > ^~~~~~~~~~~~~
> > > > /usr/include/byteswap.h:37:21: note: expanded from macro
> 'bswap_64'
> > > > #define bswap_64(x) __bswap_64 (x)
> > > > ^~~~~~~~~~~~~~
> > > > 2 warnings generated.
> > > >
> > > >
> > > >
> > > > ---
> > > > Regards,
> > > > Linux Bluetooth
> > > >
> > >
> > >
> > > --
> > > Luiz Augusto von Dentz
> >
> >
> > Regards,
> > Iulia
> >
>
>
> --
> Luiz Augusto von Dentz


Regards,
Iulia


2023-12-14 16:55:37

by Pauli Virtanen

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 4/6] shared/bap: Make bt_bap_select select a location

Hi,

ma, 2023-12-11 kello 16:25 -0500, Luiz Augusto von Dentz kirjoitti:
> > From: Luiz Augusto von Dentz <[email protected]>
> >
> > This makes bt_bap_select select a location based on the PAC channel
> > count and PACS locations, this is then passed to the Endpoint as a
> > recommended ChannelAllocation.
> > ---
> > profiles/audio/media.c | 6 ++-
> > src/shared/bap.c | 88 +++++++++++++++++++++++++++---------------
> > src/shared/bap.h | 2 +-
> > 3 files changed, 63 insertions(+), 33 deletions(-)
> >
> > diff --git a/profiles/audio/media.c b/profiles/audio/media.c
> > index 62f53defa7af..b17c555b63e4 100644
> > --- a/profiles/audio/media.c
> > +++ b/profiles/audio/media.c
> > @@ -921,7 +921,7 @@ done:
> > }
> >
> > static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> > - struct bt_bap_pac_qos *qos,
> > + uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
> > bt_bap_pac_select_t cb, void *cb_data, void *user_data)
> > {
> > struct media_endpoint *endpoint = user_data;
> > @@ -969,6 +969,10 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> > g_dbus_dict_append_entry(&dict, "Locations", DBUS_TYPE_UINT32,
> > &loc);
> >
> > + if (chan_alloc)
> > + g_dbus_dict_append_entry(&dict, "ChannelAllocation",
> > + DBUS_TYPE_UINT32, &chan_alloc);
> > +
> > if (metadata) {
> > key = "Metadata";
> > g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key,
> > diff --git a/src/shared/bap.c b/src/shared/bap.c
> > index cb505d1564d6..e1dad95aca99 100644
> > --- a/src/shared/bap.c
> > +++ b/src/shared/bap.c
> > @@ -177,6 +177,11 @@ struct bt_bap {
> > void *user_data;
> > };
> >
> > +struct bt_bap_chan {
> > + uint8_t count;
> > + uint32_t location;
> > +};
> > +
> > struct bt_bap_pac {
> > struct bt_bap_db *bdb;
> > char *name;
> > @@ -185,7 +190,7 @@ struct bt_bap_pac {
> > struct bt_bap_pac_qos qos;
> > struct iovec *data;
> > struct iovec *metadata;
> > - struct queue *chan_map;
> > + struct queue *channels;
> > struct bt_bap_pac_ops *ops;
> > void *user_data;
> > };
> > @@ -2422,19 +2427,22 @@ static void bap_pac_foreach_channel(size_t i, uint8_t l, uint8_t t, uint8_t *v,
> > void *user_data)
> > {
> > struct bt_bap_pac *pac = user_data;
> > + struct bt_bap_chan *chan;
> >
> > if (!v)
> > return;
> >
> > - if (!pac->chan_map)
> > - pac->chan_map = queue_new();
> > + if (!pac->channels)
> > + pac->channels = queue_new();
> >
> > - printf("PAC %p chan_map 0x%02x\n", pac, *v);
> > + chan = new0(struct bt_bap_chan, 1);
> > + chan->count = *v;
> > + chan->location = bt_bap_pac_get_locations(pac) ? : pac->qos.location;
> >
> > - queue_push_tail(pac->chan_map, UINT_TO_PTR(*v));
> > + queue_push_tail(pac->channels, chan);
> > }
> >
> > -static void bap_pac_update_chan_map(struct bt_bap_pac *pac, struct iovec *data)
> > +static void bap_pac_update_channels(struct bt_bap_pac *pac, struct iovec *data)
> > {
> > uint8_t type = 0x03;
> >
> > @@ -2454,8 +2462,8 @@ static void bap_pac_merge(struct bt_bap_pac *pac, struct iovec *data,
> > else
> > pac->data = util_iov_dup(data, 1);
> >
> > - /* Update channel map */
> > - bap_pac_update_chan_map(pac, data);
> > + /* Update channels */
> > + bap_pac_update_channels(pac, data);
> >
> > /* Merge metadata into existing record */
> > if (pac->metadata)
> > @@ -2495,7 +2503,7 @@ static void bap_pac_free(void *data)
> > free(pac->name);
> > util_iov_free(pac->metadata, 1);
> > util_iov_free(pac->data, 1);
> > - queue_destroy(pac->chan_map, NULL);
> > + queue_destroy(pac->channels, free);
> > free(pac);
> > }
> >
> > @@ -4677,34 +4685,52 @@ int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> > if (!lpac->ops || !lpac->ops->select)
> > return -EOPNOTSUPP;
> >
> > - for (lchan = queue_get_entries(lpac->chan_map); lchan;
> > + for (lchan = queue_get_entries(lpac->channels); lchan;
> > lchan = lchan->next) {
> > - uint8_t lmap = PTR_TO_UINT(lchan->data);
> > + struct bt_bap_chan *lc = lchan->data;
> > + uint8_t lmap = lc->count;
> > + int i;
> >
> > - for (rchan = queue_get_entries(rpac->chan_map); rchan;
> > - rchan = rchan->next) {
> > - uint8_t rmap = PTR_TO_UINT(rchan->data);
> > + printf("lmap 0x%02x\n", lmap);
> >
> > - printf("lmap 0x%02x rmap 0x%02x\n", lmap, rmap);
> > + for (i = 0, rchan = queue_get_entries(rpac->channels); rchan;
> > + rchan = rchan->next, i++) {
> > + struct bt_bap_chan *rc = rchan->data;
> >
> > - /* Try matching the channel mapping */
> > - if (lmap & rmap) {
> > - lpac->ops->select(lpac, rpac, &rpac->qos,
> > - func, user_data,
> > - lpac->user_data);
> > - if (count)
> > - (*count)++;
> > + printf("rc->count 0x%02x\n", rc->count);
> >
> > - /* Check if there are any channels left */
> > - lmap &= ~(lmap & rmap);
> > - if (!lmap)
> > - break;
> > -
> > - /* Check if device require AC*(i) settings */
> > - if (rmap == 0x01)
> > - lmap = lmap >> 1;
> > - } else
> > + /* Try matching the channel count */
> > + if (!(lmap & rc->count))
> > break;
> > +
> > + /* Check if location was set otherwise attempt to
> > + * assign one based on the number of channels it
> > + * supports.
> > + */
> > + if (!rc->location) {
> > + rc->location = bt_bap_pac_get_locations(rpac);
> > + /* If channel count is 1 use a single
> > + * location
> > + */
> > + if (rc->count == 0x01)
> > + rc->location &= BIT(i);
> > + }
> > +
> > + lpac->ops->select(lpac, rpac, lc->location &
> > + rc->location, &rpac->qos,
> > + func, user_data,
> > + lpac->user_data);
> > + if (count)
> > + (*count)++;

If sound server PAC supports both 1 and 2 channels, and remote PAC only
support 1 channel, and two streams are set up: then it looks like sound
server would be called two times with same ChannelAllocation so it'd
likely set up two left channels.

This code perhaps should first decide the bitmask of locations that
will be set up, and then in each call to select() pass only the so far
unallocated location bits.

I'll try to find some time to set things up to test this in Pipewire,
where we need some changes to enable multiple streams per device but it
should be straightforward.

> > +
> > + /* Check if there are any channels left to select */
> > + lmap &= ~(lmap & rc->count);
> > + if (!lmap)
> > + break;
> > +
> > + /* Check if device require AC*(i) settings */
> > + if (rc->count == 0x01)
> > + lmap = lmap >> 1;
> > }
> > }
> >
> > diff --git a/src/shared/bap.h b/src/shared/bap.h
> > index 470313e66fc0..9be198cec72c 100644
> > --- a/src/shared/bap.h
> > +++ b/src/shared/bap.h
> > @@ -151,7 +151,7 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
> >
> > struct bt_bap_pac_ops {
> > int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> > - struct bt_bap_pac_qos *qos,
> > + uint32_t chan_alloc, struct bt_bap_pac_qos *qos,
> > bt_bap_pac_select_t cb, void *cb_data, void *user_data);
> > int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
> > struct bt_bap_qos *qos, bt_bap_pac_config_t cb,

--
Pauli Virtanen