diff mbox series

[BlueZ,v3,4/4] storage: Add support for storing PreferredBearer

Message ID 20250226181129.2958079-4-luiz.dentz@gmail.com
State New
Headers show
Series None | expand

Commit Message

Luiz Augusto von Dentz Feb. 26, 2025, 6:11 p.m. UTC
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 mbox series

Patch

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