@@ -214,6 +214,7 @@ struct discovery_filter {
GSList *uuids;
bool duplicate;
bool discoverable;
+ bool auto_connect;
};
struct discovery_client {
@@ -2697,6 +2698,21 @@ static bool parse_pattern(DBusMessageIter *value,
return true;
}
+static bool parse_auto_connect(DBusMessageIter *value,
+ struct discovery_filter *filter)
+{
+ dbus_bool_t connect;
+
+ if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN)
+ return false;
+
+ dbus_message_iter_get_basic(value, &connect);
+
+ filter->auto_connect = connect;
+
+ return true;
+}
+
struct filter_parser {
const char *name;
bool (*func)(DBusMessageIter *iter, struct discovery_filter *filter);
@@ -2708,6 +2724,7 @@ struct filter_parser {
{ "DuplicateData", parse_duplicate_data },
{ "Discoverable", parse_discoverable },
{ "Pattern", parse_pattern },
+ { "AutoConnect", parse_auto_connect },
{ }
};
@@ -2748,6 +2765,7 @@ static bool parse_discovery_filter_dict(struct btd_adapter *adapter,
(*filter)->type = get_scan_type(adapter);
(*filter)->duplicate = false;
(*filter)->discoverable = false;
+ (*filter)->auto_connect = false;
(*filter)->pattern = NULL;
dbus_message_iter_init(msg, &iter);
@@ -2794,11 +2812,12 @@ static bool parse_discovery_filter_dict(struct btd_adapter *adapter,
goto invalid_args;
DBG("filtered discovery params: transport: %d rssi: %d pathloss: %d "
- " duplicate data: %s discoverable %s pattern %s",
+ " duplicate data: %s discoverable %s pattern %s auto-connect %s",
(*filter)->type, (*filter)->rssi, (*filter)->pathloss,
(*filter)->duplicate ? "true" : "false",
(*filter)->discoverable ? "true" : "false",
- (*filter)->pattern);
+ (*filter)->pattern,
+ (*filter)->auto_connect ? "true" : "false");
return true;
@@ -7212,7 +7231,7 @@ static void filter_duplicate_data(void *data, void *user_data)
static bool device_is_discoverable(struct btd_adapter *adapter,
struct eir_data *eir, const char *addr,
- uint8_t bdaddr_type)
+ uint8_t bdaddr_type, bool *auto_connect)
{
GSList *l;
bool discoverable;
@@ -7242,15 +7261,21 @@ static bool device_is_discoverable(struct btd_adapter *adapter,
discoverable = false;
pattern_len = strlen(filter->pattern);
- if (!pattern_len)
+ if (!pattern_len) {
+ *auto_connect = filter->auto_connect;
return true;
+ }
- if (!strncmp(filter->pattern, addr, pattern_len))
+ if (!strncmp(filter->pattern, addr, pattern_len)) {
+ *auto_connect = filter->auto_connect;
return true;
+ }
if (eir->name && !strncmp(filter->pattern, eir->name,
- pattern_len))
+ pattern_len)) {
+ *auto_connect = filter->auto_connect;
return true;
+ }
}
return discoverable;
@@ -7274,6 +7299,7 @@ void btd_adapter_device_found(struct btd_adapter *adapter,
bool name_resolve_failed;
bool scan_rsp;
bool duplicate = false;
+ bool auto_connect = false;
struct queue *matched_monitors = NULL;
confirm = (flags & MGMT_DEV_FOUND_CONFIRM_NAME);
@@ -7310,7 +7336,7 @@ void btd_adapter_device_found(struct btd_adapter *adapter,
ba2str(bdaddr, addr);
discoverable = device_is_discoverable(adapter, &eir_data, addr,
- bdaddr_type);
+ bdaddr_type, &auto_connect);
dev = btd_adapter_find_device(adapter, bdaddr, bdaddr_type);
if (!dev) {
@@ -7330,7 +7356,14 @@ void btd_adapter_device_found(struct btd_adapter *adapter,
MGMT_SETTING_ISO_SYNC_RECEIVER))
monitoring = true;
- if (!discoverable && !monitoring && not_connectable) {
+ /* Monitor Devices advertising RSI since those can be
+ * coordinated sets not marked as visible but their object are
+ * needed.
+ */
+ if (eir_data.rsi)
+ monitoring = true;
+
+ if (!discoverable && !monitoring) {
eir_data_free(&eir_data);
return;
}
@@ -7468,6 +7501,12 @@ void btd_adapter_device_found(struct btd_adapter *adapter,
adapter->discovery_found = g_slist_prepend(adapter->discovery_found,
dev);
+ /* If device has a pattern match and it also set auto-connect then
+ * attempt to connect.
+ */
+ if (!btd_device_is_connected(dev) && auto_connect)
+ btd_device_connect_services(dev, NULL);
+
return;
connect_le:
@@ -2569,9 +2569,61 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
return dev->pending;
}
+#define NVAL_TIME ((time_t) -1)
+#define SEEN_TRESHHOLD 300
+
+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);
+
+ /* 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->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 */
+ if (dev->bdaddr_type == BDADDR_LE_RANDOM)
+ return dev->bdaddr_type;
+
+ if (dev->bredr_state.connectable && dev->bredr_state.last_seen) {
+ bredr_last = current - dev->bredr_state.last_seen;
+ if (bredr_last > SEEN_TRESHHOLD)
+ bredr_last = NVAL_TIME;
+ }
+
+ if (dev->le_state.connectable && dev->le_state.last_seen) {
+ le_last = current - dev->le_state.last_seen;
+ if (le_last > SEEN_TRESHHOLD)
+ le_last = NVAL_TIME;
+ }
+
+ if (le_last == NVAL_TIME && bredr_last == NVAL_TIME)
+ return dev->bdaddr_type;
+
+ if (dev->bredr && (!dev->le || le_last == NVAL_TIME))
+ return BDADDR_BREDR;
+
+ if (dev->le && (!dev->bredr || bredr_last == NVAL_TIME))
+ return dev->bdaddr_type;
+
+ /*
+ * Prefer BR/EDR if time is the same since it might be from an
+ * advertisement with BR/EDR flag set.
+ */
+ if (bredr_last <= le_last && btd_adapter_get_bredr(dev->adapter))
+ return BDADDR_BREDR;
+
+ return dev->bdaddr_type;
+}
+
int btd_device_connect_services(struct btd_device *dev, GSList *services)
{
GSList *l;
+ uint8_t bdaddr_type;
if (dev->pending || dev->connect || dev->browse)
return -EBUSY;
@@ -2579,6 +2631,14 @@ int btd_device_connect_services(struct btd_device *dev, GSList *services)
if (!btd_adapter_get_powered(dev->adapter))
return -ENETDOWN;
+ bdaddr_type = select_conn_bearer(dev);
+ if (bdaddr_type != BDADDR_BREDR) {
+ if (dev->le_state.connected)
+ return -EALREADY;
+
+ return device_connect_le(dev);
+ }
+
if (!dev->bredr_state.svc_resolved)
return -ENOENT;
@@ -2661,57 +2721,6 @@ resolve_services:
return NULL;
}
-#define NVAL_TIME ((time_t) -1)
-#define SEEN_TRESHHOLD 300
-
-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);
-
- /* 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->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 */
- if (dev->bdaddr_type == BDADDR_LE_RANDOM)
- return dev->bdaddr_type;
-
- if (dev->bredr_state.connectable && dev->bredr_state.last_seen) {
- bredr_last = current - dev->bredr_state.last_seen;
- if (bredr_last > SEEN_TRESHHOLD)
- bredr_last = NVAL_TIME;
- }
-
- if (dev->le_state.connectable && dev->le_state.last_seen) {
- le_last = current - dev->le_state.last_seen;
- if (le_last > SEEN_TRESHHOLD)
- le_last = NVAL_TIME;
- }
-
- if (le_last == NVAL_TIME && bredr_last == NVAL_TIME)
- return dev->bdaddr_type;
-
- if (dev->bredr && (!dev->le || le_last == NVAL_TIME))
- return BDADDR_BREDR;
-
- if (dev->le && (!dev->bredr || bredr_last == NVAL_TIME))
- return dev->bdaddr_type;
-
- /*
- * Prefer BR/EDR if time is the same since it might be from an
- * advertisement with BR/EDR flag set.
- */
- if (bredr_last <= le_last && btd_adapter_get_bredr(dev->adapter))
- return BDADDR_BREDR;
-
- return dev->bdaddr_type;
-}
-
static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This implements AutoConnect filter option in SetFilterPolicy method according to its documentation. --- src/adapter.c | 55 +++++++++++++++++++++---- src/device.c | 111 +++++++++++++++++++++++++++----------------------- 2 files changed, 107 insertions(+), 59 deletions(-)