Re: [PATCH BlueZ] client: Support single profile connection/disconnection

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

 



Hi Arkadiusz,

On Sun, Mar 2, 2025 at 11:47 AM Arkadiusz Bokowy
<arkadiusz.bokowy@xxxxxxxxx> wrote:
>
> ---
>  client/main.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 80 insertions(+), 13 deletions(-)
>
> diff --git a/client/main.c b/client/main.c
> index feb21a116..e4ed692ec 100644
> --- a/client/main.c
> +++ b/client/main.c
> @@ -1969,13 +1969,44 @@ static void cmd_remove(int argc, char *argv[])
>         remove_device(proxy);
>  }
>
> +struct connection_data {
> +       GDBusProxy *proxy;
> +       char *uuid;
> +};
> +
> +static void connection_setup(DBusMessageIter *iter, void *user_data)
> +{
> +       struct connection_data *data = user_data;
> +
> +       if (!data->uuid)
> +               return;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->uuid);
> +}
> +
> +static void format_connection_profile(char *output, size_t size,
> +                                                       const char *uuid)
> +{
> +       const char *text;
> +
> +       text = bt_uuidstr_to_str(uuid);
> +       if (!text)
> +               text = uuid;
> +
> +       snprintf(output, size, " profile \"%s\"", text);
> +}
> +
>  static void connect_reply(DBusMessage *message, void *user_data)
>  {
> -       GDBusProxy *proxy = user_data;
> +       struct connection_data *data = user_data;
> +       GDBusProxy *proxy = data->proxy;
>         DBusError error;
>
>         dbus_error_init(&error);
>
> +       g_free(data->uuid);
> +       g_free(data);
> +
>         if (dbus_set_error_from_message(&error, message) == TRUE) {
>                 bt_shell_printf("Failed to connect: %s %s\n", error.name,
>                                 error.message);
> @@ -1991,6 +2022,9 @@ static void connect_reply(DBusMessage *message, void *user_data)
>
>  static void cmd_connect(int argc, char *argv[])
>  {
> +       struct connection_data *data;
> +       const char *method = "Connect";
> +       char profile[128] = "";
>         GDBusProxy *proxy;
>
>         if (check_default_ctrl() == FALSE)
> @@ -2002,31 +2036,49 @@ static void cmd_connect(int argc, char *argv[])
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>         }
>
> -       if (g_dbus_proxy_method_call(proxy, "Connect", NULL, connect_reply,
> -                                                       proxy, NULL) == FALSE) {
> +       data = new0(struct connection_data, 1);
> +       data->proxy = proxy;
> +
> +       if (argc == 3) {
> +               method = "ConnectProfile";
> +               data->uuid = g_strdup(argv[2]);
> +               format_connection_profile(profile, sizeof(profile), argv[2]);
> +       }
> +
> +       if (g_dbus_proxy_method_call(proxy, method, connection_setup,
> +                                       connect_reply, data, NULL) == FALSE) {
>                 bt_shell_printf("Failed to connect\n");
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>         }
>
> -       bt_shell_printf("Attempting to connect to %s\n", argv[1]);
> +       bt_shell_printf("Attempting to connect%s to %s\n", profile, argv[1]);
>  }
>
>  static void disconn_reply(DBusMessage *message, void *user_data)
>  {
> -       GDBusProxy *proxy = user_data;
> +       struct connection_data *data = user_data;
> +       const bool profile_disconnected = data->uuid != NULL;
> +       GDBusProxy *proxy = data->proxy;
>         DBusError error;
>
>         dbus_error_init(&error);
>
> +       g_free(data->uuid);
> +       g_free(data);
> +
>         if (dbus_set_error_from_message(&error, message) == TRUE) {
>                 bt_shell_printf("Failed to disconnect: %s\n", error.name);
>                 dbus_error_free(&error);
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>         }
>
> -       bt_shell_printf("Successful disconnected\n");
> +       bt_shell_printf("Disconnection successful\n");
>
> -       if (proxy == default_dev)
> +       /* If only a single profile was disconnected, the device itself might
> +        * still be connected. In that case, let the property change handler
> +        * take care of setting the default device to NULL.
> +        */
> +       if (proxy == default_dev && !profile_disconnected)
>                 set_default_device(NULL, NULL);
>
>         return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> @@ -2034,19 +2086,31 @@ static void disconn_reply(DBusMessage *message, void *user_data)
>
>  static void cmd_disconn(int argc, char *argv[])
>  {
> +       struct connection_data *data;
> +       const char *method = "Disconnect";
> +       char profile[128] = "";
>         GDBusProxy *proxy;
>
>         proxy = find_device(argc, argv);
>         if (!proxy)
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>
> -       if (g_dbus_proxy_method_call(proxy, "Disconnect", NULL, disconn_reply,
> -                                                       proxy, NULL) == FALSE) {
> +       data = new0(struct connection_data, 1);
> +       data->proxy = proxy;
> +
> +       if (argc == 3) {
> +               method = "DisconnectProfile";
> +               data->uuid = g_strdup(argv[2]);
> +               format_connection_profile(profile, sizeof(profile), argv[2]);
> +       }
> +
> +       if (g_dbus_proxy_method_call(proxy, method, connection_setup,
> +                                       disconn_reply, data, NULL) == FALSE) {
>                 bt_shell_printf("Failed to disconnect\n");
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>         }
>
> -       bt_shell_printf("Attempting to disconnect from %s\n",
> +       bt_shell_printf("Attempting to disconnect%s from %s\n", profile,
>                                                 proxy_address(proxy));
>  }
>
> @@ -3241,10 +3305,13 @@ static const struct bt_shell_menu main_menu = {
>                                                                 dev_generator },
>         { "remove",       "<dev>",    cmd_remove, "Remove device",
>                                                         dev_generator },
> -       { "connect",      "<dev>",    cmd_connect, "Connect device",
> -                                                       dev_generator },
> -       { "disconnect",   "[dev]",    cmd_disconn, "Disconnect device",
> +       { "connect",      "<dev> [uuid]", cmd_connect,
> +                               "Connect a device and all its profiles or "
> +                               "optionally connect a single profile only",
>                                                         dev_generator },
> +       { "disconnect",   "[dev] [uuid]", cmd_disconn,
> +                               "Disconnect a device or optionally disconnect "
> +                               "a single profile only", dev_generator },

Great idea, but let's update the documentation as well so it reflects
this change (client/bluetoothctl.rst), also it is probably worth
adding a few examples like connect/disconnect all/hfp/a2dp, etc.

>         { "wake",         "[dev] [on/off]",    cmd_wake, "Get/Set wake support",
>                                                         dev_generator },
>         { } },
> --
> 2.39.5
>
>


-- 
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