[PATCH BlueZ v2 1/2] Allow Adapter1 ConnectDevice method to connect a limited set of service UUIDs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 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




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux