summaryrefslogtreecommitdiff
path: root/profiles
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-11-30 14:20:14 -0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-12-02 11:20:17 -0800
commitf28433d448fa9ae33305d87f112a1b8abb7c6b17 (patch)
tree0f80eb9b0ca7c8cbfa9b1131c3b9133d22d1dfd2 /profiles
parentb907befc2d801f1a7607cd651369a67cceef8d33 (diff)
downloadbluez-f28433d448fa9ae33305d87f112a1b8abb7c6b17.tar.gz
bap: Fix not waiting Endpoint.SelectProperties
If there are multiple Endpoint.SelectProperties wait them to complete before attempting to proceed to configure a stream otherwise streams may not be linked properly and may end up creating multiple CIS instead.
Diffstat (limited to 'profiles')
-rw-r--r--profiles/audio/bap.c58
-rw-r--r--profiles/audio/media.c27
2 files changed, 54 insertions, 31 deletions
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 9cee9fd03..f28843ae6 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -83,6 +83,7 @@ struct bap_data {
struct queue *snks;
struct queue *streams;
GIOChannel *listen_io;
+ int selecting;
};
static struct queue *sessions;
@@ -503,7 +504,8 @@ static void ep_free(void *data)
bap_io_close(ep);
- free(ep->caps);
+ util_iov_free(ep->caps, 1);
+ util_iov_free(ep->metadata, 1);
free(ep->path);
free(ep);
}
@@ -566,20 +568,14 @@ static struct bap_ep *ep_register(struct btd_service *service,
return ep;
}
-static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
- struct iovec *metadata, struct bt_bap_qos *qos,
- void *user_data)
+static void bap_config(void *data, void *user_data)
{
- struct bap_ep *ep = user_data;
+ struct bap_ep *ep = data;
- if (err) {
- error("err %d", err);
- return;
- }
+ DBG("ep %p caps %p metadata %p", ep, ep->caps, ep->metadata);
- ep->caps = caps;
- ep->metadata = metadata;
- ep->qos = *qos;
+ if (!ep->caps)
+ return;
/* TODO: Check if stream capabilities match add support for Latency
* and PHY.
@@ -594,13 +590,43 @@ static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
if (!ep->stream) {
DBG("Unable to config stream");
- free(ep->caps);
+ util_iov_free(ep->caps, 1);
ep->caps = NULL;
+ util_iov_free(ep->metadata, 1);
+ ep->metadata = NULL;
}
bt_bap_stream_set_user_data(ep->stream, ep->path);
}
+static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
+ struct iovec *metadata, struct bt_bap_qos *qos,
+ void *user_data)
+{
+ struct bap_ep *ep = user_data;
+
+ if (err) {
+ error("err %d", err);
+ return;
+ }
+
+ ep->caps = util_iov_dup(caps, 1);
+
+ if (metadata && metadata->iov_base && metadata->iov_len)
+ ep->metadata = util_iov_dup(metadata, 1);
+
+ ep->qos = *qos;
+
+ DBG("selecting %d", ep->data->selecting);
+ ep->data->selecting--;
+
+ if (ep->data->selecting)
+ return;
+
+ queue_foreach(ep->data->srcs, bap_config, NULL);
+ queue_foreach(ep->data->snks, bap_config, NULL);
+}
+
static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
void *user_data)
{
@@ -616,8 +642,10 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
}
/* TODO: Cache LRU? */
- if (btd_service_is_initiator(service))
- bt_bap_select(lpac, rpac, select_cb, ep);
+ if (btd_service_is_initiator(service)) {
+ if (!bt_bap_select(lpac, rpac, select_cb, ep))
+ ep->data->selecting++;
+ }
return true;
}
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 6947cf963..fbb350889 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -725,24 +725,21 @@ struct pac_select_data {
void *user_data;
};
-static int parse_array(DBusMessageIter *iter, struct iovec **iov)
+static int parse_array(DBusMessageIter *iter, struct iovec *iov)
{
DBusMessageIter array;
if (!iov)
return 0;
- if (!(*iov))
- *iov = new0(struct iovec, 1);
-
dbus_message_iter_recurse(iter, &array);
- dbus_message_iter_get_fixed_array(&array, &(*iov)->iov_base,
- (int *)&(*iov)->iov_len);
+ dbus_message_iter_get_fixed_array(&array, &iov->iov_base,
+ (int *)&iov->iov_len);
return 0;
}
-static int parse_select_properties(DBusMessageIter *props, struct iovec **caps,
- struct iovec **metadata,
+static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
+ struct iovec *metadata,
struct bt_bap_qos *qos)
{
const char *key;
@@ -845,11 +842,6 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec **caps,
fail:
DBG("Failed parsing %s", key);
- if (*caps) {
- free(*caps);
- *caps = NULL;
- }
-
return -EINVAL;
}
@@ -859,7 +851,7 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
struct pac_select_data *data = user_data;
DBusMessageIter *iter = ret;
int err;
- struct iovec *caps = NULL, *metadata = NULL;
+ struct iovec caps, meta;
struct bt_bap_qos qos;
if (!ret) {
@@ -881,12 +873,15 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
qos.cig_id = BT_ISO_QOS_CIG_UNSET;
qos.cis_id = BT_ISO_QOS_CIS_UNSET;
- err = parse_select_properties(iter, &caps, &metadata, &qos);
+ memset(&caps, 0, sizeof(caps));
+ memset(&meta, 0, sizeof(meta));
+
+ err = parse_select_properties(iter, &caps, &meta, &qos);
if (err < 0)
DBG("Unable to parse properties");
done:
- data->cb(data->pac, err, caps, metadata, &qos, data->user_data);
+ data->cb(data->pac, err, &caps, &meta, &qos, data->user_data);
}
static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,