diff mbox series

[RFC,BlueZ,4/9] bap: use futures for select operation

Message ID 53008159e52e92871039f94677f3b469eea83cfe.1740844616.git.pav@iki.fi (mailing list archive)
State New
Headers show
Series BAP stream reconfiguration | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success

Commit Message

Pauli Virtanen March 1, 2025, 3:57 p.m. UTC
Change select operation to use futures.

Remove spurious bap_config for bcast streams, it does not even run if
there are only bcast PACs, and bcast streams are created differently.
---
 profiles/audio/bap.c | 74 ++++++++++++++++++++++++++++++++------------
 1 file changed, 55 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 8b9b89c70..39484c74a 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -93,6 +93,8 @@  struct bap_ep {
 	uint16_t supported_context;
 	uint16_t context;
 	struct queue *setups;
+	struct future *select_done;
+	int selecting;
 };
 
 struct bap_data {
@@ -110,7 +112,6 @@  struct bap_data {
 	struct queue *streams;
 	GIOChannel *listen_io;
 	unsigned int io_id;
-	int selecting;
 	void *user_data;
 };
 
@@ -166,6 +167,8 @@  struct bt_iso_qos bap_sink_pa_qos = {
 	}
 };
 
+static void pac_select_all(struct bap_data *data);
+
 static void future_clear(struct future **p, int err, const char *err_msg)
 {
 	struct future *h = *p;
@@ -239,7 +242,6 @@  static void future_init_dbus_reply(struct future **p, const char *name,
 	future_init(p, name, future_dbus_callback_func, dbus_message_ref(msg));
 }
 
-__attribute__((unused))
 static void future_init_chain(struct future **p, struct future *h)
 {
 	future_clear(p, ECANCELED, NULL);
@@ -1595,7 +1597,6 @@  static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
 
 	if (err) {
 		error("err %d", err);
-		ep->data->selecting--;
 		goto done;
 	}
 
@@ -1604,16 +1605,12 @@  static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps,
 	setup->metadata = util_iov_dup(metadata, 1);
 	setup->qos = *qos;
 
-	DBG("selecting %d", ep->data->selecting);
-	ep->data->selecting--;
-
 done:
-	if (ep->data->selecting)
-		return;
+	DBG("ep %p selecting %d", ep, ep->selecting);
 
-	queue_foreach(ep->data->srcs, bap_config, NULL);
-	queue_foreach(ep->data->snks, bap_config, NULL);
-	queue_foreach(ep->data->bcast, bap_config, NULL);
+	ep->selecting--;
+	if (!ep->selecting)
+		future_clear(&ep->select_done, 0, NULL);
 }
 
 static bool pac_register(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
@@ -1631,11 +1628,17 @@  static bool pac_register(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	return true;
 }
 
+struct pac_select_data {
+	struct bap_data *data;
+	struct future *select_done;
+};
+
 static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 							void *user_data)
 {
-	struct btd_service *service = user_data;
-	struct bap_data *data = btd_service_get_user_data(service);
+	struct pac_select_data *select_data = user_data;
+	struct bap_data *data = select_data->data;
+	struct btd_service *service = data->service;
 	struct match_ep match = { lpac, rpac };
 	struct queue *queue;
 	struct bap_ep *ep;
@@ -1658,8 +1661,12 @@  static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	}
 
 	/* TODO: Cache LRU? */
-	if (btd_service_is_initiator(service))
-		bt_bap_select(lpac, rpac, &ep->data->selecting, select_cb, ep);
+	if (btd_service_is_initiator(service)) {
+		bt_bap_select(lpac, rpac, &ep->selecting, select_cb, ep);
+		if (ep->selecting)
+			future_init_chain(&ep->select_done,
+						select_data->select_done);
+	}
 
 	return true;
 }
@@ -1678,8 +1685,12 @@  static void ep_cancel_select(struct bap_ep *ep)
 {
 	struct bt_bap *bap = ep->data->bap;
 
+	future_clear(&ep->select_done, ECANCELED, NULL);
+
 	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_cancel_select, ep);
 	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_cancel_select, ep);
+
+	ep->selecting = 0;
 }
 
 static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
@@ -1703,9 +1714,36 @@  static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 	return true;
 }
 
+static void select_complete_cb(int err, const char *err_msg, void *user_data)
+{
+	struct bap_data *data = user_data;
+
+	if (err == ECANCELED)
+		return;
+
+	queue_foreach(data->srcs, bap_config, NULL);
+	queue_foreach(data->snks, bap_config, NULL);
+}
+
+static void pac_select_all(struct bap_data *data)
+{
+	struct pac_select_data select_data = {
+		.data = data,
+	};
+
+	future_init(&select_data.select_done, "pac_select_all",
+						select_complete_cb, data);
+
+	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_select, &select_data);
+	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_select, &select_data);
+
+	future_clear(&select_data.select_done, 0, NULL);
+}
+
 static void bap_ready(struct bt_bap *bap, void *user_data)
 {
 	struct btd_service *service = user_data;
+	struct bap_data *data = btd_service_get_user_data(service);
 
 	DBG("bap %p", bap);
 
@@ -1715,8 +1753,7 @@  static void bap_ready(struct bt_bap *bap, void *user_data)
 	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_register, service);
 	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_register, service);
 
-	bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_select, service);
-	bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_select, service);
+	pac_select_all(data);
 }
 
 static bool match_setup_stream(const void *data, const void *user_data)
@@ -2684,8 +2721,7 @@  static void pac_added(struct bt_bap_pac *pac, void *user_data)
 	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_register, service);
 	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_register, service);
 
-	bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_select, service);
-	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_select, service);
+	pac_select_all(data);
 }
 
 static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data)