shared/bap: Allow multiple links per stream
authorIulia Tanasescu <iulia.tanasescu@nxp.com>
Fri, 25 Oct 2024 12:21:33 +0000 (15:21 +0300)
committerWootak Jung <wootak.jung@samsung.com>
Thu, 20 Feb 2025 07:43:24 +0000 (16:43 +0900)
This commit adds support to link multiple streams together, creating
the foundation for implementing broadcast links: for Broadcast Sinks,
the user could select multiple streams to receive audio from. All
selected streams need to be linked together and considered when
creating BIG sync.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
profiles/audio/transport.c
src/shared/bap.c
src/shared/bap.h

index 88383dabe39ab7a6b82f47d95b2dcf6a3b622cf0..8baf146da6cd9cded84f956ba42fa8b26ad7031f 100644 (file)
@@ -335,12 +335,9 @@ static void transport_bap_remove_owner(struct media_transport *transport,
 {
        struct bap_transport *bap = transport->data;
 
-       if (bap && bap->linked) {
-               struct bt_bap_stream *link;
-
-               link = bt_bap_stream_io_get_link(bap->stream);
-               linked_transport_remove_owner(link, owner);
-       }
+       if (bap && bap->linked)
+               queue_foreach(bt_bap_stream_io_get_links(bap->stream),
+                               linked_transport_remove_owner, owner);
 }
 
 static void media_transport_remove_owner(struct media_transport *transport)
@@ -586,12 +583,9 @@ static void transport_bap_set_owner(struct media_transport *transport,
 {
        struct bap_transport *bap = transport->data;
 
-       if (bap && bap->linked) {
-               struct bt_bap_stream *link;
-
-               link = bt_bap_stream_io_get_link(bap->stream);
-               linked_transport_set_owner(link, owner);
-       }
+       if (bap && bap->linked)
+               queue_foreach(bt_bap_stream_io_get_links(bap->stream),
+                               linked_transport_set_owner, owner);
 }
 
 static void media_transport_set_owner(struct media_transport *transport,
@@ -1182,14 +1176,14 @@ static gboolean get_links(const GDBusPropertyTable *property,
 {
        struct media_transport *transport = data;
        struct bap_transport *bap = transport->data;
-       struct bt_bap_stream *link = bt_bap_stream_io_get_link(bap->stream);
+       struct queue *links = bt_bap_stream_io_get_links(bap->stream);
        DBusMessageIter array;
 
        dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
                                        DBUS_TYPE_OBJECT_PATH_AS_STRING,
                                        &array);
 
-       append_link(link, &array);
+       queue_foreach(links, append_link, &array);
 
        dbus_message_iter_close_container(iter, &array);
 
@@ -1671,15 +1665,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 bt_bap_stream *link = bt_bap_stream_io_get_link(bap->stream);
+       struct queue *links = bt_bap_stream_io_get_links(bap->stream);
 
-       if (bap->linked == (!!link))
+       if (bap->linked == !queue_isempty(links))
                return;
 
-       bap->linked = link ? true : false;
+       bap->linked = !queue_isempty(links);
 
        /* Check if the links transport has been create yet */
-       if (bap->linked && !match_link_transport(link, NULL)) {
+       if (bap->linked && !queue_find(links, match_link_transport, NULL)) {
                bap->linked = false;
                return;
        }
@@ -1856,15 +1850,13 @@ static void transport_bap_set_state(struct media_transport *transport,
                                        transport_state_t state)
 {
        struct bap_transport *bap = transport->data;
-       struct bt_bap_stream *link;
 
        if (!bap->linked)
                return;
 
-       link = bt_bap_stream_io_get_link(bap->stream);
-
-       /* Update link */
-       link_set_state(link, UINT_TO_PTR(state));
+       /* Update links */
+       queue_foreach(bt_bap_stream_io_get_links(bap->stream), link_set_state,
+                                                       UINT_TO_PTR(state));
 }
 
 static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
index 8d04290f88ae2e88a804205fde79c86d1b6d4784..0b234275c083abe955e272c2a5e4fb16580019f6 100644 (file)
@@ -262,7 +262,7 @@ struct bt_bap_stream {
        struct iovec *cc;
        struct iovec *meta;
        struct bt_bap_qos qos;
-       struct bt_bap_stream *link;
+       struct queue *links;
        struct bt_bap_stream_io *io;
        const struct bt_bap_stream_ops *ops;
        uint8_t old_state;
@@ -1101,6 +1101,14 @@ 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 *stream = data;
+       struct bt_bap_stream *link = user_data;
+
+       queue_remove(stream->links, link);
+}
+
 static void bap_stream_free(void *data)
 {
        struct bt_bap_stream *stream = data;
@@ -1110,8 +1118,8 @@ static void bap_stream_free(void *data)
        if (stream->ep)
                stream->ep->stream = NULL;
 
-       if (stream->link)
-               stream->link->link = NULL;
+       queue_foreach(stream->links, bap_stream_unlink, stream);
+       queue_destroy(stream->links, NULL);
 
        stream_io_unref(stream->io);
        util_iov_free(stream->cc, 1);
@@ -1246,6 +1254,17 @@ static void bap_stream_update_io_links(struct bt_bap_stream *stream)
        queue_find(bap->streams, bap_stream_io_link, stream);
 }
 
+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;
@@ -1259,7 +1278,7 @@ static bool bap_stream_io_detach(struct bt_bap_stream *stream)
        io = stream->io;
        stream->io = NULL;
 
-       link = stream->link;
+       link = queue_find(stream->links, match_stream_io, io);
        if (link) {
                /* Detach link if in QoS state */
                if (link->ep->state == BT_ASCS_ASE_STATE_QOS)
@@ -1803,6 +1822,14 @@ static unsigned int bap_bcast_config(struct bt_bap_stream *stream,
        return 1;
 }
 
+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);
+}
+
 static unsigned int bap_ucast_enable(struct bt_bap_stream *stream,
                                        bool enable_links, struct iovec *data,
                                        bt_bap_stream_func_t func,
@@ -1821,9 +1848,7 @@ static unsigned int bap_ucast_enable(struct bt_bap_stream *stream,
        if (!ret || !enable_links)
                return ret;
 
-       if (stream->link)
-               bap_stream_metadata(stream->link, BT_ASCS_ENABLE, data,
-                                       NULL, NULL);
+       queue_foreach(stream->links, bap_stream_enable_link, data);
 
        return ret;
 }
@@ -1893,6 +1918,13 @@ static uint8_t stream_disable(struct bt_bap_stream *stream, struct iovec *rsp)
        return 0;
 }
 
+static void bap_stream_disable_link(void *data, void *user_data)
+{
+       struct bt_bap_stream *stream = data;
+
+       bt_bap_stream_disable(stream, false, NULL, NULL);
+}
+
 static unsigned int bap_ucast_disable(struct bt_bap_stream *stream,
                                        bool disable_links,
                                        bt_bap_stream_func_t func,
@@ -1919,7 +1951,7 @@ static unsigned int bap_ucast_disable(struct bt_bap_stream *stream,
        }
 
        if (disable_links)
-               bt_bap_stream_disable(stream->link, false, NULL, NULL);
+               queue_foreach(stream->links, bap_stream_disable_link, NULL);
 
        return req->id;
 }
@@ -2351,18 +2383,30 @@ 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 = NULL;
+
        if (!stream)
                return NULL;
 
        if (stream->io)
                return stream->io;
 
-       if (stream->link)
-               return stream->link->io;
+       queue_foreach(stream->links, stream_find_io, &io);
 
-       return NULL;
+       return io;
 }
 
 static bool stream_io_disconnected(struct io *io, void *user_data);
@@ -5849,8 +5893,7 @@ bool bt_bap_stream_set_io(struct bt_bap_stream *stream, int fd)
 
        bap_stream_set_io(stream, INT_TO_PTR(fd));
 
-       if (stream->link)
-               bap_stream_set_io(stream->link, INT_TO_PTR(fd));
+       queue_foreach(stream->links, bap_stream_set_io, INT_TO_PTR(fd));
 
        return true;
 }
@@ -5905,7 +5948,8 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
 
        bap = stream->bap;
 
-       if (stream->link || link->link)
+       if (queue_find(stream->links, NULL, link) ||
+               queue_find(link->links, NULL, stream))
                return -EALREADY;
 
        if (stream->client != link->client ||
@@ -5914,8 +5958,14 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
                        stream->ep->dir == link->ep->dir)
                return -EINVAL;
 
-       stream->link = link;
-       link->link = stream;
+       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);
 
        /* Link IOs if already set on stream/link */
        if (stream->io && !link->io)
@@ -5928,12 +5978,12 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
        return 0;
 }
 
-struct bt_bap_stream *bt_bap_stream_io_get_link(struct bt_bap_stream *stream)
+struct queue *bt_bap_stream_io_get_links(struct bt_bap_stream *stream)
 {
        if (!stream)
                return NULL;
 
-       return stream->link;
+       return stream->links;
 }
 
 static void bap_stream_get_in_qos(void *data, void *user_data)
@@ -5976,11 +6026,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);
-               bap_stream_get_out_qos(stream->link, out);
+               queue_foreach(stream->links, bap_stream_get_out_qos, out);
                break;
        case BT_BAP_SINK:
                bap_stream_get_out_qos(stream, out);
-               bap_stream_get_in_qos(stream->link, in);
+               queue_foreach(stream->links, bap_stream_get_in_qos, in);
                break;
        default:
                return false;
@@ -5991,6 +6041,14 @@ 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;
@@ -6010,8 +6068,7 @@ uint8_t bt_bap_stream_io_dir(struct bt_bap_stream *stream)
 
        }
 
-       if (stream->link)
-               dir |= stream->link->ep->dir;
+       queue_foreach(stream->links, bap_stream_get_dir, &dir);
 
        return dir;
 }
@@ -6046,7 +6103,8 @@ int bt_bap_stream_io_connecting(struct bt_bap_stream *stream, int fd)
                return -EINVAL;
 
        bap_stream_io_connecting(stream, INT_TO_PTR(fd));
-       bap_stream_io_connecting(stream->link, INT_TO_PTR(fd));
+
+       queue_foreach(stream->links, bap_stream_io_connecting, INT_TO_PTR(fd));
 
        return 0;
 }
index bf928bc2d577ff839e8e1410f379c7f19cfbf791..cd5ea2eba37463f948b74c855587b44c36bcc485 100644 (file)
@@ -231,7 +231,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 bt_bap_stream *bt_bap_stream_io_get_link(struct bt_bap_stream *stream);
+struct queue *bt_bap_stream_io_get_links(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);