@@ -330,12 +330,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)
@@ -581,12 +578,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,
@@ -1129,14 +1123,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);
@@ -1572,15 +1566,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;
}
@@ -1757,15 +1751,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,
@@ -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;
}
@@ -1872,6 +1897,13 @@ static unsigned int bap_ucast_start(struct bt_bap_stream *stream,
return req->id;
}
+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,
@@ -1895,7 +1927,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;
}
@@ -2327,18 +2359,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);
@@ -5846,8 +5890,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;
}
@@ -5902,7 +5945,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 ||
@@ -5911,8 +5955,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)
@@ -5925,12 +5975,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)
@@ -5973,11 +6023,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;
@@ -5988,6 +6038,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;
@@ -6007,8 +6065,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;
}
@@ -6043,7 +6100,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;
}
@@ -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);