--- src/adapter.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 7 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index c24432125..33c25a49b 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -2298,7 +2298,7 @@ done: return btd_error_failed(msg, strerror(-err)); } -static bool parse_uuids(DBusMessageIter *value, struct discovery_filter *filter) +static bool get_uuids_from_iter(DBusMessageIter *value, GSList **uuids) { DBusMessageIter arriter; @@ -2323,7 +2323,7 @@ static bool parse_uuids(DBusMessageIter *value, struct discovery_filter *filter) bt_uuid_to_uuid128(&uuid, &u128); bt_uuid_to_string(&u128, uuidstr, sizeof(uuidstr)); - filter->uuids = g_slist_prepend(filter->uuids, strdup(uuidstr)); + *uuids = g_slist_prepend(*uuids, strdup(uuidstr)); dbus_message_iter_next(&arriter); } @@ -2331,6 +2331,11 @@ static bool parse_uuids(DBusMessageIter *value, struct discovery_filter *filter) return true; } +static bool parse_uuids(DBusMessageIter *value, struct discovery_filter *filter) +{ + return get_uuids_from_iter(value, &filter->uuids); +} + static bool parse_rssi(DBusMessageIter *value, struct discovery_filter *filter) { if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_INT16) @@ -3206,15 +3211,77 @@ struct device_connect_data { struct btd_adapter *adapter; bdaddr_t dst; uint8_t dst_type; + GSList *uuids; DBusMessage *msg; }; +static GSList *find_matching_strings(GSList *list1, GSList *list2) +{ + GSList *l, *matches = NULL; + + if (!list1 || !list2) + return NULL; + + for (l = list1; l; l = g_slist_next(l)) { + char *item = l->data; + + if (g_slist_find_custom(list2, item, g_strcmp)) + matches = g_slist_append(matches, item); + } + return matches; +} + +static GSList *device_get_services(struct btd_device *dev, GSList *uuids) +{ + GSList *l, *services = NULL; + + if (uuids == NULL) + return NULL; + + for (l = uuids; l; l = g_slist_next(l)) { + char *uuid = l->data; + struct btd_service *service = btd_device_get_service(dev, + uuid); + services = g_slist_append(services, service); + } + + return services; +} + +static GSList *device_get_matching_services(struct btd_device *dev, + GSList *uuids) +{ + GSList *matching_uuids = NULL, *services = NULL; + GSList *device_uuids = btd_device_get_uuids(dev); + + matching_uuids = find_matching_strings(uuids, + device_uuids); + services = device_get_services(dev, matching_uuids); + g_slist_free(matching_uuids); + + return services; +} + static void device_browse_cb(struct btd_device *dev, int err, void *user_data) { DBG("err %d (%s)", err, strerror(-err)); - if (!err) - btd_device_connect_services(dev, NULL); + if (!err) { + GSList *services; + + if (!user_data) { + btd_device_connect_services(dev, NULL); + return; + } + + services = device_get_matching_services(dev, user_data); + if (services) { + btd_device_connect_services(dev, services); + g_slist_free(services); + } else + DBG("no matching services"); + g_slist_free(user_data); + } } static void device_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) @@ -3249,7 +3316,7 @@ static void device_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) } device_discover_services(device); - device_wait_for_svc_complete(device, device_browse_cb, NULL); + device_wait_for_svc_complete(device, device_browse_cb, data->uuids); g_io_channel_unref(io); dbus_message_unref(data->msg); @@ -3264,7 +3331,7 @@ failed: } static void device_connect(struct btd_adapter *adapter, const bdaddr_t *dst, - uint8_t dst_type, DBusMessage *msg) + uint8_t dst_type, GSList *uuids, DBusMessage *msg) { struct device_connect_data *data; GIOChannel *io; @@ -3273,6 +3340,7 @@ static void device_connect(struct btd_adapter *adapter, const bdaddr_t *dst, data->adapter = adapter; bacpy(&data->dst, dst); data->dst_type = dst_type; + data->uuids = uuids; data->msg = dbus_message_ref(msg); if (dst_type == BDADDR_BREDR) @@ -3309,6 +3377,7 @@ static DBusMessage *connect_device(DBusConnection *conn, DBusMessageIter iter, subiter, dictiter, value; uint8_t addr_type = BDADDR_BREDR; bdaddr_t addr = *BDADDR_ANY; + GSList *uuids = NULL; DBG("sender %s", dbus_message_get_sender(msg)); @@ -3364,6 +3433,14 @@ static DBusMessage *connect_device(DBusConnection *conn, addr_type = BDADDR_LE_RANDOM; else return btd_error_invalid_args(msg); + } else if (!strcmp(key, "UUIDs")) { + if ((dbus_message_iter_get_arg_type(&value) != + DBUS_TYPE_ARRAY) || + (dbus_message_iter_get_element_type(&value) != + DBUS_TYPE_STRING)) + return btd_error_invalid_args(msg); + if (!get_uuids_from_iter(&value, &uuids)) + return btd_error_invalid_args(msg); } else { return btd_error_invalid_args(msg); } @@ -3377,7 +3454,7 @@ static DBusMessage *connect_device(DBusConnection *conn, if (btd_adapter_find_device(adapter, &addr, addr_type)) return btd_error_already_exists(msg); - device_connect(adapter, &addr, addr_type, msg); + device_connect(adapter, &addr, addr_type, uuids, msg); return NULL; } -- 2.17.1