@@ -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 },
{ }
};
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(-)