From f28433d448fa9ae33305d87f112a1b8abb7c6b17 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 30 Nov 2022 14:20:14 -0800 Subject: 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. --- profiles/audio/bap.c | 58 +++++++++++++++++++++++++++++++++++++------------- profiles/audio/media.c | 27 ++++++++++------------- 2 files changed, 54 insertions(+), 31 deletions(-) (limited to 'profiles') 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, -- cgit v1.2.1