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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Iulia,

On Thu, Jan 23, 2025 at 8:23 AM Iulia Tanasescu <iulia.tanasescu@xxxxxxx> wrote:
>
> 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:

We may want to expand the documentation though to state the above in
the Select documentation:

https://github.com/bluez/bluez/blob/master/doc/org.bluez.MediaTransport.rst

> [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 --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);
> +       }

Seems like you could in fact remove the queue_isempty and only leave
queue_pop_head since if that is empty it would result in NULL link
anyway.

>  }
>
>  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);
>  }
>
> --
> 2.43.0
>


-- 
Luiz Augusto von Dentz





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux