diff mbox series

[BlueZ,v2,3/3] client: Add support get/set PreferredBearer

Message ID 20250225220059.2821394-3-luiz.dentz@gmail.com
State New
Headers show
Series [BlueZ,v2,1/3] org.bluez.Device: Introduced PreferredBearer | expand

Commit Message

Luiz Augusto von Dentz Feb. 25, 2025, 10 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds support for PreferredBearer which is printed with the likes of
info command:

bluetoothctl> info <addr>
...
	PreferredBearer: last-seen

It also introduces a new command to get/set the PreferredBearer:

[bluetoothctl]> bearer --help
Get/Set preferred bearer
Usage:
	 bearer <dev> [last-seen/bredr/le]

[bluetoothctl]> bearer <addr>
	PreferredBearer: last-seen
[bluetoothctl]> bearer <addr> le
bluetoothd: @ MGMT Command: Add Device (0x0033) plen 8
        LE Address: <addr>
        Action: Auto-connect remote device (0x02)
[CHG] Device <addr> PreferredBearer: le
Changing le succeeded
[bluetoothctl]> bearer <addr>
	PreferredBearer: le
[bluetoothctl]> bearer <addr> bredr
bluetoothd: @ MGMT Command: Remove Device (0x0034) plen 7
        LE Address: <addr>
[CHG] Device <addr> PreferredBearer: bredr
Changing bredr succeeded
---
 client/main.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

Comments

Luiz Augusto von Dentz Feb. 25, 2025, 10:10 p.m. UTC | #1
Hi Pauli, Bastien,

On Tue, Feb 25, 2025 at 5:01 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds support for PreferredBearer which is printed with the likes of
> info command:
>
> bluetoothctl> info <addr>
> ...
>         PreferredBearer: last-seen
>
> It also introduces a new command to get/set the PreferredBearer:
>
> [bluetoothctl]> bearer --help
> Get/Set preferred bearer
> Usage:
>          bearer <dev> [last-seen/bredr/le]
>
> [bluetoothctl]> bearer <addr>
>         PreferredBearer: last-seen
> [bluetoothctl]> bearer <addr> le
> bluetoothd: @ MGMT Command: Add Device (0x0033) plen 8
>         LE Address: <addr>
>         Action: Auto-connect remote device (0x02)
> [CHG] Device <addr> PreferredBearer: le
> Changing le succeeded
> [bluetoothctl]> bearer <addr>
>         PreferredBearer: le
> [bluetoothctl]> bearer <addr> bredr
> bluetoothd: @ MGMT Command: Remove Device (0x0034) plen 7
>         LE Address: <addr>
> [CHG] Device <addr> PreferredBearer: bredr
> Changing bredr succeeded
> ---
>  client/main.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>
> diff --git a/client/main.c b/client/main.c
> index feb21a1163d2..76c9bc329c96 100644
> --- a/client/main.c
> +++ b/client/main.c
> @@ -1714,6 +1714,7 @@ static void cmd_info(int argc, char *argv[])
>         print_property(proxy, "AdvertisingFlags");
>         print_property(proxy, "AdvertisingData");
>         print_property(proxy, "Sets");
> +       print_property(proxy, "PreferredBearer");
>
>         battery_proxy = find_proxies_by_path(battery_proxies,
>                                         g_dbus_proxy_get_path(proxy));
> @@ -2086,6 +2087,30 @@ static void cmd_wake(int argc, char *argv[])
>         return bt_shell_noninteractive_quit(EXIT_FAILURE);
>  }
>
> +static void cmd_bearer(int argc, char *argv[])
> +{
> +       GDBusProxy *proxy;
> +       char *str;
> +
> +       proxy = find_device(argc, argv);
> +       if (!proxy)
> +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +
> +       if (argc <= 2) {
> +               print_property(proxy, "PreferredBearer");
> +               return;
> +       }
> +
> +       str = strdup(argv[2]);
> +
> +       if (g_dbus_proxy_set_property_basic(proxy, "PreferredBearer",
> +                                       DBUS_TYPE_STRING, &str,
> +                                       generic_callback, str, free))
> +               return;
> +
> +       return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +}
> +
>  static void cmd_list_attributes(int argc, char *argv[])
>  {
>         GDBusProxy *proxy;
> @@ -3247,6 +3272,8 @@ static const struct bt_shell_menu main_menu = {
>                                                         dev_generator },
>         { "wake",         "[dev] [on/off]",    cmd_wake, "Get/Set wake support",
>                                                         dev_generator },
> +       { "bearer",       "<dev> [last-seen/bredr/le]", cmd_bearer,
> +                               "Get/Set preferred bearer", dev_generator },
>         { } },
>  };
>
> --
> 2.48.1

So I went ahead and implemented the idea of having PreferredBearer,
this works great when setting bredr it really stops from connecting to
LE, the said the other way around when setting to le seems to confuse
some headsets like EarFun and it ends up connecting both bearers:

[EarFun Air Pro 3]> transport.show
Transport /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0/fd1
    UUID: Sink PAC                  (00002bc9-0000-1000-8000-00805f9b34fb)
    Codec: 0x06 (6)
    Configuration.#0: len 0x02 type 0x01
    Configuration.Sampling Frequency: 16 Khz (0x03)
    Configuration.#1: len 0x02 type 0x02
    Configuration.Frame Duration: 7.5 ms (0x00)
    Configuration.#2: len 0x05 type 0x03
    Configuration.Location: 0x00000001
    Configuration.Location: Front Left (0x00000001)
    Configuration.#3: len 0x03 type 0x04
    Configuration.Frame Length: 30 (0x001e)
    Configuration.#4: len 0x02 type 0x05
    Configuration.Frame Blocks per SDU: 1 (0x01)
    Device: /org/bluez/hci0/dev_70_5A_6F_63_B6_41
    State: idle
    Volume: 0x00c8 (200)
    Endpoint: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0
    QoS.CIG: 0x00 (0)
    QoS.CIS: 0x00 (0)
    QoS.Framing: 0x00 (0)
    QoS.PresentationDelay: 0x00009c40 (40000)
    QoS.Interval: 0x00001d4c (7500)
    QoS.Latency: 0x0008 (8)
    QoS.SDU: 0x001e (30)
    QoS.PHY: 0x02 (2)
    QoS.Retransmissions: 0x02 (2)
    Location: 0x00000003 (3)
    Links: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0/fd3
Transport /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0/fd2
    UUID: Sink PAC                  (00002bc9-0000-1000-8000-00805f9b34fb)
    Codec: 0x06 (6)
    Configuration.#0: len 0x02 type 0x01
    Configuration.Sampling Frequency: 16 Khz (0x03)
    Configuration.#1: len 0x02 type 0x02
    Configuration.Frame Duration: 7.5 ms (0x00)
    Configuration.#2: len 0x05 type 0x03
    Configuration.Location: 0x00000002
    Configuration.Location: Front Right (0x00000002)
    Configuration.#3: len 0x03 type 0x04
    Configuration.Frame Length: 30 (0x001e)
    Configuration.#4: len 0x02 type 0x05
    Configuration.Frame Blocks per SDU: 1 (0x01)
    Device: /org/bluez/hci0/dev_70_5A_6F_63_B6_41
    State: idle
    Volume: 0x00c8 (200)
    Endpoint: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0
    QoS.CIG: 0x00 (0)
    QoS.CIS: 0x01 (1)
    QoS.Framing: 0x00 (0)
    QoS.PresentationDelay: 0x00009c40 (40000)
    QoS.Interval: 0x00001d4c (7500)
    QoS.Latency: 0x0008 (8)
    QoS.SDU: 0x001e (30)
    QoS.PHY: 0x02 (2)
    QoS.Retransmissions: 0x02 (2)
    Location: 0x00000003 (3)
    Links: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0/fd4
Transport /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0/fd3
    UUID: Source PAC                (00002bcb-0000-1000-8000-00805f9b34fb)
    Codec: 0x06 (6)
    Configuration.#0: len 0x02 type 0x01
    Configuration.Sampling Frequency: 48 Khz (0x08)
    Configuration.#1: len 0x02 type 0x02
    Configuration.Frame Duration: 7.5 ms (0x00)
    Configuration.#2: len 0x05 type 0x03
    Configuration.Location: 0x00000001
    Configuration.Location: Front Left (0x00000001)
    Configuration.#3: len 0x03 type 0x04
    Configuration.Frame Length: 90 (0x005a)
    Configuration.#4: len 0x02 type 0x05
    Configuration.Frame Blocks per SDU: 1 (0x01)
    Device: /org/bluez/hci0/dev_70_5A_6F_63_B6_41
    State: idle
    Volume: 0x00c8 (200)
    Endpoint: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0
    QoS.CIG: 0x00 (0)
    QoS.CIS: 0x00 (0)
    QoS.Framing: 0x00 (0)
    QoS.PresentationDelay: 0x00009c40 (40000)
    QoS.Interval: 0x00001d4c (7500)
    QoS.Latency: 0x000f (15)
    QoS.SDU: 0x005a (90)
    QoS.PHY: 0x02 (2)
    QoS.Retransmissions: 0x05 (5)
    Location: 0x00000003 (3)
    Links: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0/fd1
Transport /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0/fd4
    UUID: Source PAC                (00002bcb-0000-1000-8000-00805f9b34fb)
    Codec: 0x06 (6)
    Configuration.#0: len 0x02 type 0x01
    Configuration.Sampling Frequency: 48 Khz (0x08)
    Configuration.#1: len 0x02 type 0x02
    Configuration.Frame Duration: 7.5 ms (0x00)
    Configuration.#2: len 0x05 type 0x03
    Configuration.Location: 0x00000002
    Configuration.Location: Front Right (0x00000002)
    Configuration.#3: len 0x03 type 0x04
    Configuration.Frame Length: 90 (0x005a)
    Configuration.#4: len 0x02 type 0x05
    Configuration.Frame Blocks per SDU: 1 (0x01)
    Device: /org/bluez/hci0/dev_70_5A_6F_63_B6_41
    State: idle
    Volume: 0x00c8 (200)
    Endpoint: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_sink0
    QoS.CIG: 0x00 (0)
    QoS.CIS: 0x01 (1)
    QoS.Framing: 0x00 (0)
    QoS.PresentationDelay: 0x00009c40 (40000)
    QoS.Interval: 0x00001d4c (7500)
    QoS.Latency: 0x000f (15)
    QoS.SDU: 0x005a (90)
    QoS.PHY: 0x02 (2)
    QoS.Retransmissions: 0x05 (5)
    Location: 0x00000003 (3)
    Links: /org/bluez/hci0/dev_70_5A_6F_63_B6_41/pac_source0/fd2
Transport /org/bluez/hci0/dev_70_5A_6F_63_B6_41/fd5
    UUID: Audio Source              (0000110a-0000-1000-8000-00805f9b34fb)
    Codec: 0x02 (2)
    Media Codec: MPEG24
    Object Types: MPEG-4 AAC LC
    Frequencies: 48kHz
    Channels: 2
    Bitrate: 320000
    VBR: Yes
    Device: /org/bluez/hci0/dev_70_5A_6F_63_B6_41
    State: idle
    Delay: 0x0960 (2400)
    Volume: 0x0064 (100)

We might need to check if other devices have such behavior, perhaps
the headset is saving the last bearer it connected to so it tries to
restore it or something like that, this may messes up with that, in
the other hand the bearer can be selected even before first connecting
so we may decide to default to bredr instead of last seen for this
type of devices (Classic+LE Audio).

Anyway there are some pieces left that I still need to implement like
save the bearer in the storage so when the daemon is reloaded, or in
case of reboot, it restores the last mode properly.
diff mbox series

Patch

diff --git a/client/main.c b/client/main.c
index feb21a1163d2..76c9bc329c96 100644
--- a/client/main.c
+++ b/client/main.c
@@ -1714,6 +1714,7 @@  static void cmd_info(int argc, char *argv[])
 	print_property(proxy, "AdvertisingFlags");
 	print_property(proxy, "AdvertisingData");
 	print_property(proxy, "Sets");
+	print_property(proxy, "PreferredBearer");
 
 	battery_proxy = find_proxies_by_path(battery_proxies,
 					g_dbus_proxy_get_path(proxy));
@@ -2086,6 +2087,30 @@  static void cmd_wake(int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
+static void cmd_bearer(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+	char *str;
+
+	proxy = find_device(argc, argv);
+	if (!proxy)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	if (argc <= 2) {
+		print_property(proxy, "PreferredBearer");
+		return;
+	}
+
+	str = strdup(argv[2]);
+
+	if (g_dbus_proxy_set_property_basic(proxy, "PreferredBearer",
+					DBUS_TYPE_STRING, &str,
+					generic_callback, str, free))
+		return;
+
+	return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
 static void cmd_list_attributes(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
@@ -3247,6 +3272,8 @@  static const struct bt_shell_menu main_menu = {
 							dev_generator },
 	{ "wake",         "[dev] [on/off]",    cmd_wake, "Get/Set wake support",
 							dev_generator },
+	{ "bearer",       "<dev> [last-seen/bredr/le]", cmd_bearer,
+				"Get/Set preferred bearer", dev_generator },
 	{ } },
 };