Subject: [PATCH BlueZ v3 0/7] Add support for multiple BISes on the bcast source

This patch adds support for multiple BISes in broadcast sources.

Example commands:
Create a local endpoint and an endpoint for BIS1:
endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06
[/local/endpoint/ep0] Auto Accept (yes/no): y
[/local/endpoint/ep0] Max Transports (auto/value): a
[/local/endpoint/ep0] Locations: 0x03
[/local/endpoint/ep0] Supported Context (value): 0

Configure BIS1, create BIS1 transport and endpoint for BIS2:
endpoint.config /org/bluez/hci0/pac_bcast0 /local/endpoint/ep0 48_4_1
[/local/endpoint/ep0] BIG (auto/value): 0x01
[/local/endpoint/ep0] Enter channel location (value/no): 0x01
[/local/endpoint/ep0] Enter Metadata (value/no): n

Configure BIS2, create BIS2 transport and endpoint for BIS3:
endpoint.config /org/bluez/hci0/pac_bcast0 /local/endpoint/ep0 48_4_1
[/local/endpoint/ep0] BIG (auto/value): 0x01
[/local/endpoint/ep0] Enter channel location (value/no): 0x02
[/local/endpoint/ep0] Enter Metadata (value/no): n

For multiple BISes acquire must be called on all transports
before the BIG is created:
transport.acquire /org/bluez/hci0/pac_bcast0/fd0
transport.acquire /org/bluez/hci0/pac_bcast0/fd1
.....
transport.release /org/bluez/hci0/pac_bcast0/fd0
transport.release /org/bluez/hci0/pac_bcast0/fd1

Silviu Florian Barbulescu (7):
bap: Remove set lpac user data at bcast ep register
bap: Split bap_state and bap_connecting in two functions
shared/bap: Generate single BIS BASE for a config with BIG ID 0xFF
shared/bap: Add state in the stream struct for broadcast source
shared/bap: Check the state of all the streams with the same BIG ID
shared/bap: Add support to create a stream for broadcast source
bap: Set the generated BASE on all setups from the same BIG

profiles/audio/bap.c | 307 ++++++++++++++++++++++++++++++++++---------
src/shared/bap.c | 87 +++++++++---
src/shared/bap.h | 2 +
3 files changed, 314 insertions(+), 82 deletions(-)


base-commit: ee880bee85864b0e691370197c9de8d2f7ba0af2
--
2.39.2



Subject: [PATCH BlueZ v3 2/7] bap: Split bap_state and bap_connecting in two functions

Split bap_state and bap_connecting in two specific functions
for unicast (bap_state, bap_connecting) and broadcast
(bap_state_bcast, bap_connecting_bcast).
---
profiles/audio/bap.c | 157 +++++++++++++++++++++++++++++--------------
1 file changed, 107 insertions(+), 50 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 38ee42894..b4acdd9ef 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -2098,25 +2098,19 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
return;
}

- if (bt_bap_stream_get_type(stream) ==
- BT_BAP_STREAM_TYPE_UCAST) {
- /* Wait QoS response to respond */
- 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);
- }
+ /* Wait QoS response to respond */
+ 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);
}
}
break;
case BT_BAP_STREAM_STATE_QOS:
- if (bt_bap_stream_get_type(stream) ==
- BT_BAP_STREAM_TYPE_UCAST) {
setup_create_io(data, setup, stream, true);
- }
break;
case BT_BAP_STREAM_STATE_ENABLING:
if (setup)
@@ -2127,6 +2121,45 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
}
}

+static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
+ uint8_t new_state, void *user_data)
+{
+ struct bap_data *data = user_data;
+ struct bap_setup *setup;
+
+ DBG("stream %p: %s(%u) -> %s(%u)", stream,
+ bt_bap_stream_statestr(old_state), old_state,
+ bt_bap_stream_statestr(new_state), new_state);
+
+ /* Ignore transitions back to same state */
+ if (new_state == old_state)
+ return;
+
+ setup = bap_find_setup_by_stream(data, stream);
+
+ switch (new_state) {
+ case BT_BAP_STREAM_STATE_IDLE:
+ /* Release stream if idle */
+ if (setup)
+ setup_free(setup);
+ else
+ queue_remove(data->streams, stream);
+ break;
+ case BT_BAP_STREAM_STATE_CONFIG:
+ 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,
+ NULL);
+ return;
+ }
+ }
+ break;
+ }
+}
+
static void pac_added(struct bt_bap_pac *pac, void *user_data)
{
struct btd_service *service = user_data;
@@ -2320,45 +2353,69 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,

g_io_channel_set_close_on_unref(io, FALSE);

- 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 (qos->ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
- qos->ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
- struct bt_iso_qos iso_qos;
+ /* Attempt to get CIG/CIS if they have not been set */
+ 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, &iso_qos)) {
- g_io_channel_unref(io);
- return;
- }
-
- qos->ucast.cig_id = iso_qos.ucast.cig;
- qos->ucast.cis_id = iso_qos.ucast.cis;
+ if (!io_get_qos(io, &iso_qos)) {
+ g_io_channel_unref(io);
+ return;
}

- DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
- 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 (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
- setup->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
- struct bt_iso_qos iso_qos;
+ qos->ucast.cig_id = iso_qos.ucast.cig;
+ qos->ucast.cis_id = iso_qos.ucast.cis;
+ }

- if (!io_get_qos(io, &iso_qos)) {
- g_io_channel_unref(io);
- return;
- }
+ DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
+ qos->ucast.cig_id, qos->ucast.cis_id);
+}

- 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);
+static void bap_connecting_bcast(struct bt_bap_stream *stream, bool state,
+ int fd, void *user_data)
+{
+ struct bap_data *data = user_data;
+ struct bap_setup *setup;
+ GIOChannel *io;
+
+ if (!state)
+ return;
+
+ setup = bap_find_setup_by_stream(data, stream);
+ if (!setup)
+ return;
+
+ setup->recreate = false;
+
+ if (!setup->io) {
+ io = g_io_channel_unix_new(fd);
+ 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 = setup->io;
+
+ g_io_channel_set_close_on_unref(io, FALSE);
+
+ /* Attempt to get BIG/BIS if they have not been set */
+ 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, &iso_qos)) {
+ g_io_channel_unref(io);
+ return;
}

- DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
- qos->bcast.big, qos->bcast.bis);
+ setup->qos.bcast.big = iso_qos.bcast.big;
+ setup->qos.bcast.bis = iso_qos.bcast.bis;
+ bt_bap_stream_config(setup->stream, &setup->qos, setup->caps,
+ NULL, NULL);
}
+
+ DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
+ setup->qos.bcast.big, setup->qos.bcast.bis);
}

static void bap_attached(struct bt_bap *bap, void *user_data)
@@ -2456,10 +2513,10 @@ static int bap_bcast_probe(struct btd_service *service)

data->ready_id = bt_bap_ready_register(data->bap, bap_ready, service,
NULL);
- data->state_id = bt_bap_state_register(data->bap, bap_state,
- bap_connecting, data, NULL);
+ data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
+ bap_connecting_bcast, data, NULL);
data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
- pac_removed_broadcast, data, NULL);
+ pac_removed_broadcast, data, NULL);

bt_bap_set_user_data(data->bap, service);

@@ -2611,8 +2668,8 @@ static int bap_adapter_probe(struct btd_profile *p,
return -EINVAL;
}

- data->state_id = bt_bap_state_register(data->bap, bap_state,
- bap_connecting, data, NULL);
+ data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
+ bap_connecting_bcast, data, NULL);
data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
pac_removed_broadcast, data, NULL);

--
2.39.2


Subject: [PATCH BlueZ v3 4/7] shared/bap: Add state in stream struct for bcast source

Add state support in the stream struct for broadcast source.
---
src/shared/bap.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index a39b95407..524bfa058 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -251,6 +251,8 @@ struct bt_bap_stream {
struct bt_bap_stream *link;
struct bt_bap_stream_io *io;
const struct bt_bap_stream_ops *ops;
+ uint8_t bcast_old_state;
+ uint8_t bcast_state;
bool client;
void *user_data;
};
@@ -1271,7 +1273,6 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)

static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
{
- struct bt_bap_endpoint *ep = stream->ep;
struct bt_bap *bap = stream->bap;

/* Check if ref_count is already 0 which means detaching is in
@@ -1283,14 +1284,6 @@ static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
return;
}

- ep->old_state = ep->state;
- ep->state = state;
-
- DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
- bt_bap_stream_get_dir(stream),
- bt_bap_stream_statestr(stream->ep->old_state),
- bt_bap_stream_statestr(stream->ep->state));
-
if (stream->ops && stream->ops->set_state)
stream->ops->set_state(stream, state);

@@ -1527,6 +1520,14 @@ static void bap_ucast_set_state(struct bt_bap_stream *stream, uint8_t state)
{
struct bt_bap_endpoint *ep = stream->ep;

+ ep->old_state = ep->state;
+ ep->state = state;
+
+ DBG(stream->bap, "stream %p dir 0x%02x: %s -> %s", stream,
+ bt_bap_stream_get_dir(stream),
+ bt_bap_stream_statestr(stream->ep->old_state),
+ bt_bap_stream_statestr(stream->ep->state));
+
if (stream->lpac->type == BT_BAP_BCAST_SINK || stream->client)
goto done;

@@ -1942,22 +1943,25 @@ static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
struct bt_bap *bap = stream->bap;
const struct queue_entry *entry;

+ stream->bcast_old_state = stream->bcast_state;
+ stream->bcast_state = state;
+
DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
bt_bap_stream_get_dir(stream),
- bt_bap_stream_statestr(stream->ep->old_state),
- bt_bap_stream_statestr(stream->ep->state));
+ bt_bap_stream_statestr(stream->bcast_old_state),
+ bt_bap_stream_statestr(stream->bcast_state));

for (entry = queue_get_entries(bap->state_cbs); entry;
entry = entry->next) {
struct bt_bap_state *state = entry->data;

if (state->func)
- state->func(stream, stream->ep->old_state,
- stream->ep->state, state->data);
+ state->func(stream, stream->bcast_old_state,
+ stream->bcast_state, state->data);
}

/* Post notification updates */
- switch (stream->ep->state) {
+ switch (stream->bcast_state) {
case BT_ASCS_ASE_STATE_IDLE:
bap_stream_detach(stream);
break;
--
2.39.2


Subject: [PATCH BlueZ v3 5/7] shared/bap: Check state of all streams with same BIG ID

The function is used to verify if all the streams from a BIG are in the
same state, and if so it returns the number of BISes in the BIG.
Else, return 0.

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

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 524bfa058..49d9838fb 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -6115,3 +6115,36 @@ struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream)

return base_iov;
}
+
+/*
+ * Check the state of all streams with the same BIG ID.
+ * If all the streams are in the checked state, return
+ * number of this streams. Else, return 0.
+ */
+uint8_t bt_bap_get_streams_by_state(struct bt_bap_stream *stream,
+ uint8_t test_state)
+{
+ const struct queue_entry *entry;
+ struct bt_bap_stream *ent_stream;
+ uint8_t nb = 0;
+
+ for (entry = queue_get_entries(stream->bap->streams);
+ entry; entry = entry->next) {
+ ent_stream = entry->data;
+
+ if (ent_stream == stream) {
+ nb++;
+ continue;
+ }
+
+ if (ent_stream->qos.bcast.big != stream->qos.bcast.big)
+ continue;
+
+ if (ent_stream->bcast_state != test_state)
+ return 0;
+
+ nb++;
+ }
+
+ return nb;
+}
diff --git a/src/shared/bap.h b/src/shared/bap.h
index 2c3550921..a37e1528e 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -323,3 +323,5 @@ void bt_bap_update_bcast_source(struct bt_bap_pac *pac,
bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac);

struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream);
+uint8_t bt_bap_get_streams_by_state(struct bt_bap_stream *stream,
+ uint8_t test_state);
--
2.39.2


Subject: [PATCH BlueZ v3 6/7] shared/bap: Add support to create stream for bcast source

Add support to create stream for bcast source

---
src/shared/bap.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 49d9838fb..97bf65c24 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -5038,6 +5038,10 @@ static bool find_ep_pacs(const void *data, const void *user_data)
case BT_BAP_STREAM_STATE_CONFIG:
case BT_BAP_STREAM_STATE_QOS:
return true;
+ default:
+ if (ep->stream->lpac->type ==
+ BT_BAP_BCAST_SOURCE)
+ return true;
}

return false;
@@ -5159,7 +5163,7 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
struct bt_bap_qos *pqos,
struct iovec *data)
{
- struct bt_bap_stream *stream;
+ struct bt_bap_stream *stream = NULL;
struct bt_bap_endpoint *ep;
struct match_pac match;

@@ -5227,7 +5231,8 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
}
}

- stream = ep->stream;
+ if (lpac->type != BT_BAP_BCAST_SOURCE)
+ stream = ep->stream;
if (!stream)
stream = bap_stream_new(bap, ep, lpac, rpac, data, true);

--
2.39.2


Subject: [PATCH BlueZ v3 7/7] bap: Set generated BASE on all setups from the same BIG

Set the BASE generated in BlueZ on all setups from the same BIG,
and use defer to inform the kernel when to create the BIG.

---
profiles/audio/bap.c | 160 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 144 insertions(+), 16 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index b4acdd9ef..def5e1432 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -943,8 +943,12 @@ 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 IOs if connecting since QoS is going to be reconfigured */
- ep_close(ep);
+ /* Broadcast source supports multiple setups, each setup will be BIS
+ * and will be configured with the set_configuration command
+ * TO DO reconfiguration of a BIS.
+ */
+ if (bt_bap_pac_get_type(ep->lpac) != BT_BAP_BCAST_SOURCE)
+ ep_close(ep);

setup = setup_new(ep);

@@ -980,7 +984,6 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SINK)
setup->msg = dbus_message_ref(msg);
else {
- setup->base = bt_bap_stream_get_base(setup->stream);
setup->id = 0;
}

@@ -1846,7 +1849,7 @@ static void setup_connect_io(struct bap_data *data, struct bap_setup *setup,
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 bt_iso_qos *qos, int defer)
{
struct btd_adapter *adapter = data->user_data;
GIOChannel *io = NULL;
@@ -1883,7 +1886,7 @@ static void setup_connect_io_broadcast(struct bap_data *data,
BT_IO_OPT_MODE, BT_IO_MODE_ISO,
BT_IO_OPT_QOS, qos,
BT_IO_OPT_BASE, &base,
- BT_IO_OPT_DEFER_TIMEOUT, false,
+ BT_IO_OPT_DEFER_TIMEOUT, defer,
BT_IO_OPT_INVALID);

if (!io) {
@@ -2012,9 +2015,6 @@ static void setup_create_bcast_io(struct bap_data *data,

memset(&iso_qos, 0, sizeof(iso_qos));

- if (!defer)
- goto done;
-
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;
@@ -2031,9 +2031,10 @@ static void setup_create_bcast_io(struct bap_data *data,
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(setup->ep->lpac) == BT_BAP_BCAST_SOURCE)
- setup_connect_io_broadcast(data, setup, stream, &iso_qos);
+ setup_connect_io_broadcast(data, setup, stream, &iso_qos,
+ defer);
else
setup_listen_io_broadcast(data, setup, stream, &iso_qos);
}
@@ -2121,11 +2122,77 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
}
}

+/* This function will call setup_create_io on all BISes from a BIG.
+ * The defer parameter will be set on true on all but the last one.
+ */
+static bool create_io_bises(struct bap_setup *setup,
+ uint8_t nb_bises, struct bap_data *data)
+{
+ const struct queue_entry *entry;
+ struct bap_setup *ent_setup;
+ bool defer = true;
+
+ for (entry = queue_get_entries(setup->ep->setups);
+ entry; entry = entry->next) {
+ ent_setup = entry->data;
+
+ if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.big !=
+ bt_bap_stream_get_qos(setup->stream)->bcast.big)
+ continue;
+
+ if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.bis ==
+ nb_bises)
+ defer = false;
+
+ setup_create_io(data, ent_setup, ent_setup->stream, defer);
+ if (!ent_setup->io) {
+ error("Unable to create io");
+ goto fail;
+ }
+ }
+
+ return true;
+
+fail:
+ /* Clear the io of the created sockets if one
+ * socket creation fails.
+ */
+ for (entry = queue_get_entries(setup->ep->setups);
+ entry; entry = entry->next) {
+ ent_setup = entry->data;
+
+ if (bt_bap_stream_get_qos(ent_setup->stream)->bcast.big !=
+ bt_bap_stream_get_qos(setup->stream)->bcast.big)
+ continue;
+
+ if (setup->io)
+ g_io_channel_unref(setup->io);
+ }
+ return false;
+}
+
+static void iterate_setup_update_base(void *data, void *user_data)
+{
+ struct bap_setup *setup = data;
+ struct bap_setup *data_setup = user_data;
+
+ if ((setup->stream != data_setup->stream) &&
+ (setup->qos.bcast.big == data_setup->qos.bcast.big)) {
+
+ if (setup->base)
+ util_iov_free(setup->base, 1);
+
+ setup->base = util_iov_dup(data_setup->base, 1);
+ }
+}
+
static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
uint8_t new_state, void *user_data)
{
struct bap_data *data = user_data;
struct bap_setup *setup;
+ bool defer = false;
+ uint8_t nb_bises = 0;

DBG("stream %p: %s(%u) -> %s(%u)", stream,
bt_bap_stream_statestr(old_state), old_state,
@@ -2146,14 +2213,75 @@ static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
queue_remove(data->streams, stream);
break;
case BT_BAP_STREAM_STATE_CONFIG:
- if (setup && !setup->id) {
- setup_create_io(data, setup, stream, true);
+ if (!setup || setup->id)
+ break;
+ /* If the stream is attached to a
+ * broadcast sink endpoint.
+ */
+ if (bt_bap_stream_io_dir(stream) ==
+ BT_BAP_BCAST_SOURCE) {
+ setup_create_io(data, setup, stream, defer);
if (!setup->io) {
error("Unable to create io");
- if (old_state != BT_BAP_STREAM_STATE_RELEASING)
- bt_bap_stream_release(stream, NULL,
- NULL);
- return;
+ if (old_state !=
+ BT_BAP_STREAM_STATE_RELEASING)
+ bt_bap_stream_release(stream,
+ NULL, NULL);
+ }
+ } else {
+ /* If the stream attached to a broadcast
+ * source endpoint generate the base.
+ */
+ if (setup->base == NULL) {
+ setup->base = bt_bap_stream_get_base(
+ setup->stream);
+ /* Set the generated BASE on all setups
+ * from the same BIG.
+ */
+ queue_foreach(setup->ep->setups,
+ iterate_setup_update_base, setup);
+ }
+ /* If there is only one BIS create the io
+ * with defer false
+ */
+ if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET) {
+ setup_create_io(data, setup,
+ stream, defer);
+ if (!setup->io) {
+ error("Unable to create io");
+ if (old_state !=
+ BT_BAP_STREAM_STATE_RELEASING)
+ bt_bap_stream_release(stream,
+ NULL, NULL);
+ }
+ } else {
+ /* The kernel has 2 requirements when handling
+ * multiple BIS connections for the same BIG:
+ * 1 - setup_create_io for all but the last BIS
+ * must be with defer true so we can inform the
+ * kernel when to start the BIG.
+ * 2 - The order in which the setup_create_io
+ * are called must be in the order of BIS
+ * indexes in BASE from first to last.
+ * To address this requirement we will call
+ * setup_create_io on all BISes only when all
+ * transport acquire have been received and will
+ * send it in the order of the BIS index
+ * from BASE.
+ */
+ nb_bises = bt_bap_get_streams_by_state(
+ setup->stream,
+ BT_BAP_STREAM_STATE_CONFIG);
+
+ if (!nb_bises)
+ break;
+
+ if (!create_io_bises(setup, nb_bises, data)) {
+ if (old_state !=
+ BT_BAP_STREAM_STATE_RELEASING)
+ bt_bap_stream_release(stream,
+ NULL, NULL);
+ }
}
}
break;
--
2.39.2


Subject: [PATCH BlueZ v3 1/7] bap: Remove set lpac user data at bcast ep register

Remove set lpac user data at bcast ep register

---
profiles/audio/bap.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 88c93127b..38ee42894 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -1207,8 +1207,6 @@ static struct bap_ep *ep_register_bcast(struct bap_data *data,
*/
if (rpac)
bt_bap_pac_set_user_data(rpac, ep->path);
- else
- bt_bap_pac_set_user_data(lpac, ep->path);

DBG("ep %p lpac %p rpac %p path %s", ep, ep->lpac, ep->rpac, ep->path);

--
2.39.2


Subject: [PATCH BlueZ v3 3/7] shared/bap: Generate one BIS BASE for

Generate single BIS BASE for a config with BIG ID 0xFF

---
src/shared/bap.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index e26dbf944..a39b95407 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -6094,11 +6094,16 @@ struct iovec *bt_bap_stream_get_base(struct bt_bap_stream *stream)
base.next_bis_index = 1;
base.big_id = stream->qos.bcast.big;

- /*
- * Create subgroups with each different Metadata and Codec
- * Specific Configuration from all streams having the same BIG ID.
+ /* If the BIG ID was explicitly set, create a BASE with information
+ * from all streams belonging to this BIG. Otherwise, create a BASE
+ * with only this BIS.
*/
- queue_foreach(stream->bap->streams, set_base_subgroup, &base);
+ if (stream->qos.bcast.big != 0xFF)
+ queue_foreach(stream->bap->streams, set_base_subgroup, &base);
+ else {
+ base.pres_delay = stream->qos.bcast.delay;
+ set_base_subgroup(stream, &base);
+ }

base_iov = generate_base(&base);

--
2.39.2


2024-02-15 23:51:43

by bluez.test.bot

[permalink] [raw]
Subject: RE: Add support for multiple BISes on the bcast source

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

---Test result---

Test Summary:
CheckPatch PASS 3.09 seconds
GitLint PASS 2.02 seconds
BuildEll PASS 25.09 seconds
BluezMake PASS 769.14 seconds
MakeCheck PASS 12.12 seconds
MakeDistcheck PASS 172.80 seconds
CheckValgrind PASS 241.48 seconds
CheckSmatch PASS 347.73 seconds
bluezmakeextell PASS 112.50 seconds
IncrementalBuild PASS 5188.44 seconds
ScanBuild WARNING 1011.39 seconds

Details
##############################
Test: ScanBuild - WARNING
Desc: Run Scan Build
Output:
src/shared/bap.c:1134:2: warning: Use of memory after it is freed
DBG(bap, "stream %p", stream);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:40:2: note: expanded from macro 'DBG'
bap_debug(_bap, "%s:%s() " fmt, __FILE__, __func__, ## arg)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:1147:2: warning: Use of memory after it is freed
DBG(stream->bap, "stream %p", stream);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:40:2: note: expanded from macro 'DBG'
bap_debug(_bap, "%s:%s() " fmt, __FILE__, __func__, ## arg)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:1242:33: warning: Use of memory after it is freed
for (entry = queue_get_entries(bap->state_cbs); entry;
^~~~~~~~~~~~~~
src/shared/bap.c:1281:8: warning: Use of memory after it is freed
bap = bt_bap_ref_safe(bap);
^~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:1699:3: warning: Use of memory after it is freed
stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 warnings generated.



---
Regards,
Linux Bluetooth

2024-02-20 19:13:59

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 4/7] shared/bap: Add state in stream struct for bcast source

Hi Silviu,

On Thu, Feb 15, 2024 at 4:24 PM Silviu Florian Barbulescu
<[email protected]> wrote:
>
> Add state support in the stream struct for broadcast source.
> ---
> src/shared/bap.c | 32 ++++++++++++++++++--------------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/src/shared/bap.c b/src/shared/bap.c
> index a39b95407..524bfa058 100644
> --- a/src/shared/bap.c
> +++ b/src/shared/bap.c
> @@ -251,6 +251,8 @@ struct bt_bap_stream {
> struct bt_bap_stream *link;
> struct bt_bap_stream_io *io;
> const struct bt_bap_stream_ops *ops;
> + uint8_t bcast_old_state;
> + uint8_t bcast_state;

Lets have it as generic one, old_state and state.

> bool client;
> void *user_data;
> };
> @@ -1271,7 +1273,6 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
>
> static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
> {
> - struct bt_bap_endpoint *ep = stream->ep;
> struct bt_bap *bap = stream->bap;
>
> /* Check if ref_count is already 0 which means detaching is in
> @@ -1283,14 +1284,6 @@ static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
> return;
> }
>
> - ep->old_state = ep->state;
> - ep->state = state;
> -
> - DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
> - bt_bap_stream_get_dir(stream),
> - bt_bap_stream_statestr(stream->ep->old_state),
> - bt_bap_stream_statestr(stream->ep->state));
> -
> if (stream->ops && stream->ops->set_state)
> stream->ops->set_state(stream, state);
>
> @@ -1527,6 +1520,14 @@ static void bap_ucast_set_state(struct bt_bap_stream *stream, uint8_t state)
> {
> struct bt_bap_endpoint *ep = stream->ep;
>
> + ep->old_state = ep->state;
> + ep->state = state;
> +
> + DBG(stream->bap, "stream %p dir 0x%02x: %s -> %s", stream,
> + bt_bap_stream_get_dir(stream),
> + bt_bap_stream_statestr(stream->ep->old_state),
> + bt_bap_stream_statestr(stream->ep->state));
> +
> if (stream->lpac->type == BT_BAP_BCAST_SINK || stream->client)
> goto done;
>
> @@ -1942,22 +1943,25 @@ static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
> struct bt_bap *bap = stream->bap;
> const struct queue_entry *entry;
>
> + stream->bcast_old_state = stream->bcast_state;
> + stream->bcast_state = state;
> +
> DBG(bap, "stream %p dir 0x%02x: %s -> %s", stream,
> bt_bap_stream_get_dir(stream),
> - bt_bap_stream_statestr(stream->ep->old_state),
> - bt_bap_stream_statestr(stream->ep->state));
> + bt_bap_stream_statestr(stream->bcast_old_state),
> + bt_bap_stream_statestr(stream->bcast_state));
>
> for (entry = queue_get_entries(bap->state_cbs); entry;
> entry = entry->next) {
> struct bt_bap_state *state = entry->data;
>
> if (state->func)
> - state->func(stream, stream->ep->old_state,
> - stream->ep->state, state->data);
> + state->func(stream, stream->bcast_old_state,
> + stream->bcast_state, state->data);
> }
>
> /* Post notification updates */
> - switch (stream->ep->state) {
> + switch (stream->bcast_state) {
> case BT_ASCS_ASE_STATE_IDLE:
> bap_stream_detach(stream);
> break;
> --
> 2.39.2
>


--
Luiz Augusto von Dentz

2024-02-21 19:50:23

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 0/7] Add support for multiple BISes on the bcast source

Hello:

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

On Thu, 15 Feb 2024 23:23:49 +0200 you wrote:
> This patch adds support for multiple BISes in broadcast sources.
>
> Example commands:
> Create a local endpoint and an endpoint for BIS1:
> endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06
> [/local/endpoint/ep0] Auto Accept (yes/no): y
> [/local/endpoint/ep0] Max Transports (auto/value): a
> [/local/endpoint/ep0] Locations: 0x03
> [/local/endpoint/ep0] Supported Context (value): 0
>
> [...]

Here is the summary with links:
- [BlueZ,v3,1/7] bap: Remove set lpac user data at bcast ep register
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=c5f1c5ba0e8d
- [BlueZ,v3,2/7] bap: Split bap_state and bap_connecting in two functions
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=5629f4784a4d
- [BlueZ,v3,3/7] shared/bap: Generate one BIS BASE for
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=a16c2ccf9c25
- [BlueZ,v3,4/7] shared/bap: Add state in stream struct for bcast source
(no matching commit)
- [BlueZ,v3,5/7] shared/bap: Check state of all streams with same BIG ID
(no matching commit)
- [BlueZ,v3,6/7] shared/bap: Add support to create stream for bcast source
(no matching commit)
- [BlueZ,v3,7/7] bap: Set generated BASE on all setups from the same BIG
(no matching commit)

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