* [PATCH BlueZ v3 2/4] device: Add implementation of PreferredBearer
2025-02-26 18:11 [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer Luiz Augusto von Dentz
@ 2025-02-26 18:11 ` Luiz Augusto von Dentz
2025-02-26 18:11 ` [PATCH BlueZ v3 3/4] client: Add support get/set PreferredBearer Luiz Augusto von Dentz
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-02-26 18:11 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds initial implementation of PreferredBearer.
---
src/device.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 96 insertions(+), 3 deletions(-)
diff --git a/src/device.c b/src/device.c
index ec97fc889056..de92e68d2780 100644
--- a/src/device.c
+++ b/src/device.c
@@ -152,6 +152,7 @@ struct svc_callback {
/* Per-bearer (LE or BR/EDR) device state */
struct bearer_state {
+ bool prefer;
bool paired;
bool bonded;
bool connected;
@@ -2543,10 +2544,12 @@ static uint8_t select_conn_bearer(struct btd_device *dev)
time_t bredr_last = NVAL_TIME, le_last = NVAL_TIME;
time_t current = time(NULL);
- /* Prefer bonded bearer in case only one is bonded */
- if (dev->bredr_state.bonded && !dev->le_state.bonded )
+ /* Use preferred bearer or bonded bearer in case only one is bonded */
+ if (dev->bredr_state.prefer ||
+ (dev->bredr_state.bonded && !dev->le_state.bonded))
return BDADDR_BREDR;
- else if (!dev->bredr_state.bonded && dev->le_state.bonded)
+ else if (dev->le_state.prefer ||
+ (!dev->bredr_state.bonded && dev->le_state.bonded))
return dev->bdaddr_type;
/* If the address is random it can only be connected over LE */
@@ -3340,6 +3343,92 @@ static const GDBusMethodTable device_methods[] = {
{ }
};
+static const char *device_prefer_bearer_str(struct btd_device *device)
+{
+ if (device->bredr_state.prefer)
+ return "bredr";
+ else if (device->le_state.prefer)
+ return "le";
+ else
+ return "last-seen";
+}
+
+static gboolean
+dev_property_get_prefer_bearer(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ const char *str = device_prefer_bearer_str(device);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
+
+ return TRUE;
+}
+
+static void
+dev_property_set_prefer_bearer(const GDBusPropertyTable *property,
+ DBusMessageIter *value,
+ GDBusPendingPropertySet id, void *data)
+{
+ struct btd_device *device = data;
+ const char *str;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_STRING) {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ dbus_message_iter_get_basic(value, &str);
+
+ if (!strcasecmp(device_prefer_bearer_str(device), str))
+ goto done;
+
+ if (!strcasecmp(str, "last-seen")) {
+ device->bredr_state.prefer = false;
+ device->le_state.prefer = false;
+ } else if (!strcasecmp(str, "bredr")) {
+ device->bredr_state.prefer = true;
+ device->le_state.prefer = false;
+ /* Remove device from auto-connect list so the kernel does not
+ * attempt to auto-connect to it in case it starts advertising.
+ */
+ device_set_auto_connect(device, FALSE);
+ } else if (!strcasecmp(str, "le")) {
+ device->le_state.prefer = true;
+ device->bredr_state.prefer = false;
+ /* Add device to auto-connect list */
+ device_set_auto_connect(device, TRUE);
+ } else {
+ g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+ return;
+ }
+
+ g_dbus_emit_property_changed(dbus_conn, device->path,
+ DEVICE_INTERFACE, "PreferredBearer");
+
+done:
+ g_dbus_pending_property_success(id);
+}
+
+static gboolean
+dev_property_prefer_bearer_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct btd_device *device = data;
+
+ /* Check if both BR/EDR and LE bearer are connected/bonded */
+ if ((device->bredr_state.connected || device->bredr_state.bonded) &&
+ (device->le_state.connected || device->le_state.bonded))
+ return TRUE;
+
+ /* Check if both BR/EDR and LE are connectable */
+ return device->bredr_state.connectable && device->le_state.connectable;
+}
+
static const GDBusPropertyTable device_properties[] = {
{ "Address", "s", dev_property_get_address },
{ "AddressType", "s", property_get_address_type },
@@ -3378,6 +3467,10 @@ static const GDBusPropertyTable device_properties[] = {
dev_property_wake_allowed_exist },
{ "Sets", "a{oa{sv}}", dev_property_get_set, NULL,
dev_property_set_exists },
+ { "PreferredBearer", "s", dev_property_get_prefer_bearer,
+ dev_property_set_prefer_bearer,
+ dev_property_prefer_bearer_exists,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ }
};
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH BlueZ v3 3/4] client: Add support get/set PreferredBearer
2025-02-26 18:11 [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer Luiz Augusto von Dentz
2025-02-26 18:11 ` [PATCH BlueZ v3 2/4] device: Add implementation of PreferredBearer Luiz Augusto von Dentz
@ 2025-02-26 18:11 ` Luiz Augusto von Dentz
2025-02-26 18:11 ` [PATCH BlueZ v3 4/4] storage: Add support for storing PreferredBearer Luiz Augusto von Dentz
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-02-26 18:11 UTC (permalink / raw)
To: linux-bluetooth
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/bluetoothctl.rst | 17 +++++++++++++++++
client/main.c | 27 +++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/client/bluetoothctl.rst b/client/bluetoothctl.rst
index b6c2efa351d8..106ed971a59f 100644
--- a/client/bluetoothctl.rst
+++ b/client/bluetoothctl.rst
@@ -288,6 +288,23 @@ Device information.
:Usage: **> info <dev>**
+bearer
+------
+
+Get/Set preferred bearer.
+
+:Usage: **> bearer <dev> [last-seen/bredr/le]**
+:Example get preferred bearer:
+ | > bearer <addr>
+ | PreferredBearer: last-seen
+:Example set preferred bearer to LE:
+ | > bearer <addr> le
+ | [CHG] Device <addr> PreferredBearer: le
+ | Changing le succeeded
+:Example set preferred bearer to BREDR:
+ | > bearer <addr> bredr
+ | [CHG] Device <addr> PreferredBearer: bredr
+ | Changing bredr succeeded
Advertise Submenu
=================
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
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH BlueZ v3 4/4] storage: Add support for storing PreferredBearer
2025-02-26 18:11 [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer Luiz Augusto von Dentz
2025-02-26 18:11 ` [PATCH BlueZ v3 2/4] device: Add implementation of PreferredBearer Luiz Augusto von Dentz
2025-02-26 18:11 ` [PATCH BlueZ v3 3/4] client: Add support get/set PreferredBearer Luiz Augusto von Dentz
@ 2025-02-26 18:11 ` Luiz Augusto von Dentz
2025-02-26 19:16 ` [BlueZ,v3,1/4] org.bluez.Device: Introduced PreferredBearer bluez.test.bot
2025-03-06 18:10 ` [PATCH BlueZ v3 1/4] " patchwork-bot+bluetooth
4 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-02-26 18:11 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds support for storing PreferredBearer into device info file.
---
doc/settings-storage.txt | 2 ++
src/device.c | 66 +++++++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 178e7d07bf11..4e9881eedf02 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -293,6 +293,8 @@ Long term key) related to a remote device.
strings remote in 128-bits UUID format,
separated by ";"
+ PreferredBearer String Preferred bearer for remote device
+
[DeviceID] group contains:
diff --git a/src/device.c b/src/device.c
index de92e68d2780..9219eb674f87 100644
--- a/src/device.c
+++ b/src/device.c
@@ -368,10 +368,25 @@ static GSList *find_service_with_uuid(GSList *list, char *uuid)
return NULL;
}
+static const char *device_prefer_bearer_str(struct btd_device *device)
+{
+ /* Check if both BR/EDR and LE bearer are supported */
+ if (!device->bredr || !device->le)
+ return NULL;
+
+ if (device->bredr_state.prefer)
+ return "bredr";
+ else if (device->le_state.prefer)
+ return "le";
+ else
+ return "last-seen";
+}
+
static void update_technologies(GKeyFile *file, struct btd_device *dev)
{
const char *list[2];
size_t len = 0;
+ const char *bearer;
if (dev->bredr)
list[len++] = "BR/EDR";
@@ -391,6 +406,12 @@ static void update_technologies(GKeyFile *file, struct btd_device *dev)
g_key_file_set_string_list(file, "General", "SupportedTechnologies",
list, len);
+
+ /* Store the PreferredBearer in case of dual-mode devices */
+ bearer = device_prefer_bearer_str(dev);
+ if (bearer)
+ g_key_file_set_string(file, "General", "PreferredBearer",
+ bearer);
}
static void store_csrk(struct csrk_info *csrk, GKeyFile *key_file,
@@ -2080,6 +2101,7 @@ bool btd_device_add_set(struct btd_device *device, bool encrypted,
static void device_set_auto_connect(struct btd_device *device, gboolean enable)
{
char addr[18];
+ const char *bearer;
if (!device || !device->le || device_address_is_private(device))
return;
@@ -2100,6 +2122,11 @@ static void device_set_auto_connect(struct btd_device *device, gboolean enable)
return;
}
+ /* Inhibit auto connect if BR/EDR bearer is preferred */
+ bearer = device_prefer_bearer_str(device);
+ if (bearer && !strcasecmp(bearer, "bredr"))
+ return;
+
/* Enabling auto connect */
adapter_auto_connect_add(device->adapter, device);
@@ -3343,16 +3370,6 @@ static const GDBusMethodTable device_methods[] = {
{ }
};
-static const char *device_prefer_bearer_str(struct btd_device *device)
-{
- if (device->bredr_state.prefer)
- return "bredr";
- else if (device->le_state.prefer)
- return "le";
- else
- return "last-seen";
-}
-
static gboolean
dev_property_get_prefer_bearer(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
@@ -3382,6 +3399,7 @@ dev_property_set_prefer_bearer(const GDBusPropertyTable *property,
dbus_message_iter_get_basic(value, &str);
+ /* Check if current preferred bearer is the same */
if (!strcasecmp(device_prefer_bearer_str(device), str))
goto done;
@@ -3407,6 +3425,8 @@ dev_property_set_prefer_bearer(const GDBusPropertyTable *property,
return;
}
+ store_device_info(device);
+
g_dbus_emit_property_changed(dbus_conn, device->path,
DEVICE_INTERFACE, "PreferredBearer");
@@ -3420,13 +3440,7 @@ dev_property_prefer_bearer_exists(const GDBusPropertyTable *property,
{
struct btd_device *device = data;
- /* Check if both BR/EDR and LE bearer are connected/bonded */
- if ((device->bredr_state.connected || device->bredr_state.bonded) &&
- (device->le_state.connected || device->le_state.bonded))
- return TRUE;
-
- /* Check if both BR/EDR and LE are connectable */
- return device->bredr_state.connectable && device->le_state.connectable;
+ return device_prefer_bearer_str(device) != NULL;
}
static const GDBusPropertyTable device_properties[] = {
@@ -3996,6 +4010,24 @@ static void load_info(struct btd_device *device, const char *local,
g_strfreev(techno);
+ /* Load preferred bearer */
+ str = g_key_file_get_string(key_file, "General", "PreferredBearer",
+ NULL);
+ if (str) {
+ if (!strcasecmp(str, "last-seen")) {
+ device->bredr_state.prefer = false;
+ device->le_state.prefer = false;
+ } else if (!strcasecmp(str, "bredr")) {
+ device->bredr_state.prefer = true;
+ device->le_state.prefer = false;
+ } else if (!strcasecmp(str, "le")) {
+ device->le_state.prefer = true;
+ device->bredr_state.prefer = false;
+ }
+
+ g_free(str);
+ }
+
next:
/* Load trust */
device->trusted = g_key_file_get_boolean(key_file, "General",
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* RE: [BlueZ,v3,1/4] org.bluez.Device: Introduced PreferredBearer
2025-02-26 18:11 [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer Luiz Augusto von Dentz
` (2 preceding siblings ...)
2025-02-26 18:11 ` [PATCH BlueZ v3 4/4] storage: Add support for storing PreferredBearer Luiz Augusto von Dentz
@ 2025-02-26 19:16 ` bluez.test.bot
2025-03-06 18:10 ` [PATCH BlueZ v3 1/4] " patchwork-bot+bluetooth
4 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2025-02-26 19:16 UTC (permalink / raw)
To: linux-bluetooth, luiz.dentz
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=938178
---Test result---
Test Summary:
CheckPatch PENDING 0.23 seconds
GitLint PENDING 0.19 seconds
BuildEll PASS 20.53 seconds
BluezMake PASS 1523.85 seconds
MakeCheck PASS 13.59 seconds
MakeDistcheck PASS 159.75 seconds
CheckValgrind PASS 216.30 seconds
CheckSmatch PASS 285.52 seconds
bluezmakeextell PASS 98.01 seconds
IncrementalBuild PENDING 0.30 seconds
ScanBuild PASS 866.45 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer
2025-02-26 18:11 [PATCH BlueZ v3 1/4] org.bluez.Device: Introduced PreferredBearer Luiz Augusto von Dentz
` (3 preceding siblings ...)
2025-02-26 19:16 ` [BlueZ,v3,1/4] org.bluez.Device: Introduced PreferredBearer bluez.test.bot
@ 2025-03-06 18:10 ` patchwork-bot+bluetooth
4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+bluetooth @ 2025-03-06 18:10 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hello:
This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Wed, 26 Feb 2025 13:11:26 -0500 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This introduces PreferredBearer property which can be used to indicate
> what bearer shall be connected first rather than just using last seen
> bearer which may not work always since it seems some devices sometimes
> advertises on LE bearer but expects connections over BR/EDR e.g:
>
> [...]
Here is the summary with links:
- [BlueZ,v3,1/4] org.bluez.Device: Introduced PreferredBearer
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=a22935f9baf5
- [BlueZ,v3,2/4] device: Add implementation of PreferredBearer
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=03240630b39b
- [BlueZ,v3,3/4] client: Add support get/set PreferredBearer
(no matching commit)
- [BlueZ,v3,4/4] storage: Add support for storing PreferredBearer
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=4d3c721ee037
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread