diff --git a/src/adapter.c b/src/adapter.c
index a107214..2417e3c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
GSList *uuids;
bool duplicate;
bool discoverable;
+ bool auto_connect;
};
struct discovery_client {
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);
{ "DuplicateData", parse_duplicate_data },
{ "Discoverable", parse_discoverable },
{ "Pattern", parse_pattern },
+ { "AutoConnect", parse_auto_connect },
{ }
};
(*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);
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;
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;
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;
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);
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) {
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;
}
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:
diff --git a/src/device.c b/src/device.c
index 2ecf145..902c4aa 100644
--- a/src/device.c
+++ b/src/device.c
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;
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;
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)
{