From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> 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(-) diff --git a/src/adapter.c b/src/adapter.c index fd425e6d2fe4..6f0699302257 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -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: diff --git a/src/device.c b/src/device.c index 56583f71a78b..60fdc2ef2779 100644 --- a/src/device.c +++ b/src/device.c @@ -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) { -- 2.49.0