diff mbox series

[BlueZ,1/1] client/player: Rework transport.select

Message ID 20250123132331.27435-2-iulia.tanasescu@nxp.com
State New
Headers show
Series client/player: Rework transport.select | expand

Commit Message

Iulia Tanasescu Jan. 23, 2025, 1:23 p.m. UTC
Since the transport.select command should also work for transports
created by audio servers, the transport should not be required to
be associated with a local bluetoothctl endpoint, to avoid errors
like below:

[bluetoothctl]> scan on
[bluetoothctl]> [NEW] Device 1C:F1:FA:E7:B0:3F 1C-F1-FA-E7-B0-3F
[1C-F1-FA-E7-B0-3F]> [NEW] Transport
                     /org/bluez/hci0/dev_1C_F1_FA_E7_B0_3F/bis1/fd0
[1C-F1-FA-E7-B0-3F]> [NEW] Transport
                     /org/bluez/hci0/dev_1C_F1_FA_E7_B0_3F/bis2/fd1
[1C-F1-FA-E7-B0-3F]> transport.select
                     /org/bluez/hci0/dev_1C_F1_FA_E7_B0_3F/bis1/fd0
                     /org/bluez/hci0/dev_1C_F1_FA_E7_B0_3F/bis2/fd
Local endpoint not found

This reworks transport.select to use a dedicated structure to hold
information about the transport and its links, instead of using the
local endpoint.
---
 client/player.c | 160 +++++++++++++++++++++++-------------------------
 1 file changed, 77 insertions(+), 83 deletions(-)
diff mbox series

Patch

diff --git a/client/player.c b/client/player.c
index 464a9cc14..e58b42bec 100644
--- a/client/player.c
+++ b/client/player.c
@@ -4,7 +4,7 @@ 
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2020  Intel Corporation. All rights reserved.
- *  Copyright 2023-2024 NXP
+ *  Copyright 2023-2025 NXP
  *
  *
  */
@@ -115,8 +115,6 @@  struct endpoint {
 	uint8_t iso_group;
 	uint8_t iso_stream;
 	struct queue *acquiring;
-	struct queue *links;
-	struct queue *selecting;
 	struct queue *transports;
 	DBusMessage *msg;
 	struct preset *preset;
@@ -150,8 +148,14 @@  struct transport {
 	int num;
 };
 
-static void transport_set_links(struct endpoint *ep, GDBusProxy *proxy);
-static void transport_select(GDBusProxy *proxy);
+struct transport_select_args {
+	GDBusProxy *proxy;
+	struct queue *links;
+	struct queue *selecting;
+};
+
+static void transport_set_links(struct transport_select_args *args);
+static void transport_select(struct transport_select_args *args);
 
 static void endpoint_unregister(void *data)
 {
@@ -2923,8 +2927,6 @@  static void endpoint_free(void *data)
 		free(ep->preset);
 
 	queue_destroy(ep->acquiring, NULL);
-	queue_destroy(ep->links, NULL);
-	queue_destroy(ep->selecting, NULL);
 	queue_destroy(ep->transports, free);
 
 	g_free(ep->path);
@@ -4891,28 +4893,45 @@  static void acquire_reply(DBusMessage *message, void *user_data)
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
+static void free_transport_select_args(struct transport_select_args *args)
+{
+	queue_destroy(args->links, NULL);
+	queue_destroy(args->selecting, NULL);
+	g_free(args);
+}
+
 static void select_reply(DBusMessage *message, void *user_data)
 {
 	DBusError error;
-	struct endpoint *ep = user_data;
+	struct transport_select_args *args = user_data;
+	GDBusProxy *link;
 
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
 		bt_shell_printf("Failed to select: %s\n", error.name);
 		dbus_error_free(&error);
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	bt_shell_printf("Select successful\n");
 
-	if (queue_isempty(ep->selecting)) {
+	if (queue_isempty(args->selecting)) {
 		/* All links have been selected */
-		queue_destroy(ep->selecting, NULL);
-		ep->selecting = NULL;
-
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 	}
+
+	/* Select next link */
+	link = queue_pop_head(args->selecting);
+	if (link) {
+		args->proxy = link;
+		transport_select(args);
+	} else {
+		free_transport_select_args(args);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 }
 
 static void unselect_reply(DBusMessage *message, void *user_data)
@@ -5174,22 +5193,23 @@  static void cmd_acquire_transport(int argc, char *argv[])
 
 static void set_bcode_cb(const DBusError *error, void *user_data)
 {
-	GDBusProxy *proxy = user_data;
+	struct transport_select_args *args = user_data;
 
 	if (dbus_error_is_set(error)) {
 		bt_shell_printf("Failed to set broadcast code: %s\n",
 								error->name);
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	bt_shell_printf("Setting broadcast code succeeded\n");
 
-	transport_select(proxy);
+	transport_select(args);
 }
 
 static void set_bcode(const char *input, void *user_data)
 {
-	GDBusProxy *proxy = user_data;
+	struct transport_select_args *args = user_data;
 	char *bcode;
 
 	if (!strcasecmp(input, "n") || !strcasecmp(input, "no"))
@@ -5197,47 +5217,39 @@  static void set_bcode(const char *input, void *user_data)
 	else
 		bcode = g_strdup(input);
 
-	if (g_dbus_proxy_set_property_dict(proxy, "QoS",
+	if (g_dbus_proxy_set_property_dict(args->proxy, "QoS",
 				set_bcode_cb, user_data,
 				NULL, "BCode", DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
 				strlen(bcode), bcode, NULL) == FALSE) {
 		bt_shell_printf("Setting broadcast code failed\n");
 		g_free(bcode);
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	g_free(bcode);
 }
 
-static void transport_select(GDBusProxy *proxy)
+static void transport_select(struct transport_select_args *args)
 {
-	struct endpoint *ep;
-	GDBusProxy *link;
-
-	ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
-	if (!ep)
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-
-	if (!g_dbus_proxy_method_call(proxy, "Select", NULL,
-					select_reply, ep, NULL)) {
+	if (!g_dbus_proxy_method_call(args->proxy, "Select", NULL,
+					select_reply, args, NULL)) {
 		bt_shell_printf("Failed select transport\n");
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
-
-	/* Select next link */
-	link = queue_pop_head(ep->selecting);
-	if (link)
-		transport_select(link);
 }
 
-static void transport_set_bcode(GDBusProxy *proxy)
+static void transport_set_bcode(struct transport_select_args *args)
 {
 	DBusMessageIter iter, array, entry, value;
 	unsigned char encryption;
 	const char *key;
 
-	if (g_dbus_proxy_get_property(proxy, "QoS", &iter) == FALSE)
+	if (g_dbus_proxy_get_property(args->proxy, "QoS", &iter) == FALSE) {
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
 
 	dbus_message_iter_recurse(&iter, &array);
 
@@ -5253,7 +5265,7 @@  static void transport_set_bcode(GDBusProxy *proxy)
 			if (encryption == 1) {
 				bt_shell_prompt_input("",
 					"Enter brocast code[value/no]:",
-					set_bcode, proxy);
+					set_bcode, args);
 				return;
 			}
 			break;
@@ -5264,7 +5276,7 @@  static void transport_set_bcode(GDBusProxy *proxy)
 	/* Go straight to selecting transport, if Broadcast Code
 	 * is not required.
 	 */
-	transport_select(proxy);
+	transport_select(args);
 }
 
 static void transport_unselect(GDBusProxy *proxy, bool prompt)
@@ -5278,58 +5290,52 @@  static void transport_unselect(GDBusProxy *proxy, bool prompt)
 
 static void set_links_cb(const DBusError *error, void *user_data)
 {
-	GDBusProxy *proxy = user_data;
-	const char *path = g_dbus_proxy_get_path(proxy);
-	struct endpoint *ep;
+	struct transport_select_args *args = user_data;
 	GDBusProxy *link;
 
-	ep = find_ep_by_transport(path);
-	if (!ep) {
-		bt_shell_printf("Local endpoint not found\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	link = queue_pop_head(ep->links);
+	link = queue_pop_head(args->links);
 
-	if (queue_isempty(ep->links)) {
-		queue_destroy(ep->links, NULL);
-		ep->links = NULL;
+	if (queue_isempty(args->links)) {
+		queue_destroy(args->links, NULL);
+		args->links = NULL;
 	}
 
 	if (dbus_error_is_set(error)) {
 		bt_shell_printf("Failed to set link %s: %s\n",
 						g_dbus_proxy_get_path(link),
 						error->name);
+		free_transport_select_args(args);
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	bt_shell_printf("Successfully linked transport %s\n",
 						g_dbus_proxy_get_path(link));
 
-	if (!ep->selecting)
-		ep->selecting = queue_new();
+	if (!args->selecting)
+		args->selecting = queue_new();
 
 	/* Enqueue link to mark that it is ready to be selected */
-	queue_push_tail(ep->selecting, link);
+	queue_push_tail(args->selecting, link);
 
 	/* Continue setting the remanining links */
-	transport_set_links(ep, proxy);
+	transport_set_links(args);
 }
 
-static void transport_set_links(struct endpoint *ep, GDBusProxy *proxy)
+static void transport_set_links(struct transport_select_args *args)
 {
 	GDBusProxy *link;
 	const char *path;
 
-	link = queue_peek_head(ep->links);
+	link = queue_peek_head(args->links);
 	if (link) {
 		path = g_dbus_proxy_get_path(link);
 
-		if (g_dbus_proxy_set_property_array(proxy, "Links",
+		if (g_dbus_proxy_set_property_array(args->proxy, "Links",
 					DBUS_TYPE_OBJECT_PATH,
 					&path, 1, set_links_cb,
-					proxy, NULL) == FALSE) {
+					args, NULL) == FALSE) {
 			bt_shell_printf("Linking transport %s failed\n", path);
+			free_transport_select_args(args);
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
@@ -5339,28 +5345,17 @@  static void transport_set_links(struct endpoint *ep, GDBusProxy *proxy)
 	/* If all links have been set, check is transport requires the
 	 * user to provide a Broadcast Code.
 	 */
-	transport_set_bcode(proxy);
-}
-
-static void endpoint_set_links(struct endpoint *ep)
-{
-	GDBusProxy *proxy = queue_pop_head(ep->links);
-
-	if (!proxy) {
-		bt_shell_printf("No transport to set links for\n");
-		return bt_shell_noninteractive_quit(EXIT_FAILURE);
-	}
-
-	transport_set_links(ep, proxy);
+	transport_set_bcode(args);
 }
 
 static void cmd_select_transport(int argc, char *argv[])
 {
 	GDBusProxy *link = NULL;
-	struct queue *links = queue_new();
-	struct endpoint *ep;
+	struct transport_select_args *args;
 	int i;
 
+	args = g_new0(struct transport_select_args, 1);
+
 	for (i = 1; i < argc; i++) {
 		link = g_dbus_proxy_lookup(transports, NULL, argv[i],
 					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
@@ -5375,26 +5370,25 @@  static void cmd_select_transport(int argc, char *argv[])
 			goto fail;
 		}
 
-		/* Enqueue all links */
-		queue_push_tail(links, link);
-	}
+		if (!args->proxy) {
+			args->proxy = link;
+			continue;
+		}
 
-	/* Get reference to local endpoint */
-	ep = find_ep_by_transport(g_dbus_proxy_get_path(link));
-	if (!ep) {
-		bt_shell_printf("Local endpoint not found\n");
-		goto fail;
-	}
+		if (!args->links)
+			args->links = queue_new();
 
-	ep->links = links;
+		/* Enqueue all links */
+		queue_push_tail(args->links, link);
+	}
 
 	/* Link streams before selecting one by one */
-	endpoint_set_links(ep);
+	transport_set_links(args);
 
 	return;
 
 fail:
-	queue_destroy(links, NULL);
+	free_transport_select_args(args);
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }