Diff between b1f1b58eecdbdafc73728b1d5aca799997669ba0 and 826023de56896e83f35ae69a73d6a120a2f5b11e

Changed Files

File Additions Deletions Status
src/adapter.c +52 -368 modified
src/adapter.h +0 -18 modified
src/device.c +120 -45 modified
src/device.h +1 -0 modified
src/event.c +0 -8 modified

Full Patch

diff --git a/src/adapter.c b/src/adapter.c
index 9773993..f1e6e1f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -172,17 +172,6 @@ struct btd_adapter {
 
 static gboolean process_auth_queue(gpointer user_data);
 
-static void dev_info_free(void *data)
-{
-	struct remote_dev_info *dev = data;
-
-	g_free(dev->name);
-	g_free(dev->alias);
-	g_slist_free_full(dev->services, g_free);
-	g_strfreev(dev->uuids);
-	g_free(dev);
-}
-
 int btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
 							uint8_t minor)
 {
@@ -511,30 +500,9 @@ static uint8_t get_needed_mode(struct btd_adapter *adapter, uint8_t mode)
 	return mode;
 }
 
-static GSList *remove_bredr(GSList *all)
-{
-	GSList *l, *le;
-
-	for (l = all, le = NULL; l; l = l->next) {
-		struct remote_dev_info *dev = l->data;
-		if (dev->bdaddr_type == BDADDR_BREDR) {
-			dev_info_free(dev);
-			continue;
-		}
-
-		le = g_slist_append(le, dev);
-	}
-
-	g_slist_free(all);
-
-	return le;
-}
-
 /* Called when a session gets removed or the adapter is stopped */
 static void stop_discovery(struct btd_adapter *adapter)
 {
-	adapter->found_devices = remove_bredr(adapter->found_devices);
-
 	if (adapter->oor_devices) {
 		g_slist_free(adapter->oor_devices);
 		adapter->oor_devices = NULL;
@@ -974,6 +942,9 @@ void adapter_remove_device(struct btd_adapter *adapter,
 	GList *l;
 
 	adapter->devices = g_slist_remove(adapter->devices, device);
+	adapter->found_devices = g_slist_remove(adapter->found_devices,
+								device);
+
 	adapter->connections = g_slist_remove(adapter->connections, device);
 
 	l = adapter->auths->head;
@@ -1060,7 +1031,7 @@ static DBusMessage *adapter_start_discovery(DBusConnection *conn,
 	if (adapter->disc_sessions)
 		goto done;
 
-	g_slist_free_full(adapter->found_devices, dev_info_free);
+	g_slist_free(adapter->found_devices);
 	adapter->found_devices = NULL;
 
 	g_slist_free(adapter->oor_devices);
@@ -1498,11 +1469,6 @@ static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg,
 
 	device = l->data;
 
-	if (device_is_temporary(device) || device_is_busy(device))
-		return g_dbus_create_error(msg,
-				ERROR_INTERFACE ".DoesNotExist",
-				"Device creation in progress");
-
 	device_set_temporary(device, TRUE);
 
 	if (!device_is_connected(device)) {
@@ -2158,19 +2124,20 @@ static void call_adapter_powered_callbacks(struct btd_adapter *adapter,
 
 static void emit_device_disappeared(gpointer data, gpointer user_data)
 {
-	struct remote_dev_info *dev = data;
+	struct btd_device *dev = data;
 	struct btd_adapter *adapter = user_data;
 	char address[18];
 	const char *paddr = address;
 
-	ba2str(&dev->bdaddr, address);
+	ba2str(device_get_address(dev), address);
 
 	g_dbus_emit_signal(btd_get_dbus_connection(), adapter->path,
-			ADAPTER_INTERFACE, "DeviceDisappeared",
-			DBUS_TYPE_STRING, &paddr,
-			DBUS_TYPE_INVALID);
+					ADAPTER_INTERFACE, "DeviceDisappeared",
+					DBUS_TYPE_STRING, &paddr,
+					DBUS_TYPE_INVALID);
 
-	adapter->found_devices = g_slist_remove(adapter->found_devices, dev);
+	if (device_is_temporary(dev))
+		adapter_remove_device(adapter, dev, TRUE);
 }
 
 void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode,
@@ -2496,7 +2463,7 @@ static void adapter_free(gpointer user_data)
 
 	sdp_list_free(adapter->services, NULL);
 
-	g_slist_free_full(adapter->found_devices, dev_info_free);
+	g_slist_free(adapter->found_devices);
 
 	g_slist_free(adapter->oor_devices);
 
@@ -2652,6 +2619,7 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 						gboolean discovering)
 {
 	guint connect_list_len;
+	GSList *l;
 
 	adapter->discovering = discovering;
 
@@ -2662,8 +2630,15 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 		return;
 
 	g_slist_foreach(adapter->oor_devices, emit_device_disappeared, adapter);
-	g_slist_free_full(adapter->oor_devices, dev_info_free);
-	adapter->oor_devices = g_slist_copy(adapter->found_devices);
+	g_slist_free(adapter->oor_devices);
+
+	for (l = adapter->found_devices; l != NULL; l = g_slist_next(l)) {
+		struct btd_device *dev = l->data;
+		device_set_rssi(dev, 0);
+	}
+
+	adapter->oor_devices = adapter->found_devices;
+	adapter->found_devices = NULL;
 
 	if (adapter->discov_suspended)
 		return;
@@ -2706,266 +2681,6 @@ static void suspend_discovery(struct btd_adapter *adapter)
 		mgmt_stop_discovery(adapter->dev_id);
 }
 
-static int found_device_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct remote_dev_info *d = a;
-	const bdaddr_t *bdaddr = b;
-
-	if (bacmp(bdaddr, BDADDR_ANY) == 0)
-		return 0;
-
-	return bacmp(&d->bdaddr, bdaddr);
-}
-
-struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter,
-							const bdaddr_t *bdaddr)
-{
-	GSList *l;
-
-	l = g_slist_find_custom(adapter->found_devices, bdaddr,
-							found_device_cmp);
-	if (l)
-		return l->data;
-
-	return NULL;
-}
-
-static int dev_rssi_cmp(struct remote_dev_info *d1, struct remote_dev_info *d2)
-{
-	int rssi1, rssi2;
-
-	rssi1 = d1->rssi < 0 ? -d1->rssi : d1->rssi;
-	rssi2 = d2->rssi < 0 ? -d2->rssi : d2->rssi;
-
-	return rssi1 - rssi2;
-}
-
-static void append_dict_valist(DBusMessageIter *iter,
-					const char *first_key,
-					va_list var_args)
-{
-	DBusMessageIter dict;
-	const char *key;
-	int type;
-	int n_elements;
-	void *val;
-
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	key = first_key;
-	while (key) {
-		type = va_arg(var_args, int);
-		val = va_arg(var_args, void *);
-		if (type == DBUS_TYPE_ARRAY) {
-			n_elements = va_arg(var_args, int);
-			if (n_elements > 0)
-				dict_append_array(&dict, key, DBUS_TYPE_STRING,
-						val, n_elements);
-		} else
-			dict_append_entry(&dict, key, type, val);
-		key = va_arg(var_args, char *);
-	}
-
-	dbus_message_iter_close_container(iter, &dict);
-}
-
-static void emit_device_found(const char *path, const char *address,
-				const char *first_key, ...)
-{
-	DBusMessage *signal;
-	DBusMessageIter iter;
-	va_list var_args;
-
-	signal = dbus_message_new_signal(path, ADAPTER_INTERFACE,
-					"DeviceFound");
-	if (!signal) {
-		error("Unable to allocate new %s.DeviceFound signal",
-				ADAPTER_INTERFACE);
-		return;
-	}
-	dbus_message_iter_init_append(signal, &iter);
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &address);
-
-	va_start(var_args, first_key);
-	append_dict_valist(&iter, first_key, var_args);
-	va_end(var_args);
-
-	g_dbus_send_message(btd_get_dbus_connection(), signal);
-}
-
-static char **strlist2array(GSList *list)
-{
-	unsigned int i, n;
-	char **array;
-
-	if (list == NULL)
-		return NULL;
-
-	n = g_slist_length(list);
-	array = g_new0(char *, n + 1);
-
-	for (i = 0; list; list = list->next, i++)
-		array[i] = g_strdup((const gchar *) list->data);
-
-	return array;
-}
-
-void adapter_emit_device_found(struct btd_adapter *adapter,
-						struct remote_dev_info *dev)
-{
-	struct btd_device *device;
-	char peer_addr[18];
-	const char *icon, *paddr = peer_addr;
-	dbus_bool_t paired = FALSE, trusted = FALSE;
-	dbus_int16_t rssi = dev->rssi;
-	dbus_bool_t legacy = dev->legacy;
-	char *alias;
-	size_t uuid_count;
-
-	ba2str(&dev->bdaddr, peer_addr);
-
-	device = adapter_find_device(adapter, paddr);
-	if (device) {
-		paired = device_is_paired(device);
-		trusted = device_is_trusted(device);
-	}
-
-	/* The uuids string array is updated only if necessary */
-	uuid_count = g_slist_length(dev->services);
-	if (dev->services && dev->uuid_count != uuid_count) {
-		g_strfreev(dev->uuids);
-		dev->uuids = strlist2array(dev->services);
-		dev->uuid_count = uuid_count;
-	}
-
-	if (!dev->alias) {
-		if (!dev->name) {
-			alias = g_strdup(peer_addr);
-			g_strdelimit(alias, ":", '-');
-		} else
-			alias = g_strdup(dev->name);
-	} else
-		alias = g_strdup(dev->alias);
-
-	if (dev->bdaddr_type != BDADDR_BREDR) {
-		uint16_t app;
-
-		/* Avoid emitting DeviceFound() signal if device is not
-		 * discoverable */
-		if (!(dev->flags & (EIR_LIM_DISC | EIR_GEN_DISC))) {
-			g_free(alias);
-			return;
-		}
-
-		if (read_remote_appearance(&adapter->bdaddr, &dev->bdaddr,
-						dev->bdaddr_type, &app) == 0)
-			icon = gap_appearance_to_icon(app);
-		else {
-			app = 0;
-			icon = NULL;
-		}
-
-		emit_device_found(adapter->path, paddr,
-				"Address", DBUS_TYPE_STRING, &paddr,
-				"Appearance", DBUS_TYPE_UINT16, &app,
-				"Icon", DBUS_TYPE_STRING, &icon,
-				"RSSI", DBUS_TYPE_INT16, &rssi,
-				"Name", DBUS_TYPE_STRING, &dev->name,
-				"Alias", DBUS_TYPE_STRING, &alias,
-				"LegacyPairing", DBUS_TYPE_BOOLEAN, &legacy,
-				"Paired", DBUS_TYPE_BOOLEAN, &paired,
-				"UUIDs", DBUS_TYPE_ARRAY, &dev->uuids, uuid_count,
-				NULL);
-	} else {
-		icon = class_to_icon(dev->class);
-
-		emit_device_found(adapter->path, paddr,
-				"Address", DBUS_TYPE_STRING, &paddr,
-				"Class", DBUS_TYPE_UINT32, &dev->class,
-				"Icon", DBUS_TYPE_STRING, &icon,
-				"RSSI", DBUS_TYPE_INT16, &rssi,
-				"Name", DBUS_TYPE_STRING, &dev->name,
-				"Alias", DBUS_TYPE_STRING, &alias,
-				"LegacyPairing", DBUS_TYPE_BOOLEAN, &legacy,
-				"Paired", DBUS_TYPE_BOOLEAN, &paired,
-				"Trusted", DBUS_TYPE_BOOLEAN, &trusted,
-				"UUIDs", DBUS_TYPE_ARRAY, &dev->uuids, uuid_count,
-				NULL);
-	}
-
-	g_free(alias);
-}
-
-static struct remote_dev_info *found_device_new(const bdaddr_t *bdaddr,
-					uint8_t bdaddr_type, const char *name,
-					const char *alias, uint32_t class,
-					bool legacy, int flags)
-{
-	struct remote_dev_info *dev;
-
-	dev = g_new0(struct remote_dev_info, 1);
-	bacpy(&dev->bdaddr, bdaddr);
-	dev->bdaddr_type = bdaddr_type;
-	dev->name = g_strdup(name);
-	dev->alias = g_strdup(alias);
-	dev->class = class;
-	dev->legacy = legacy;
-	if (flags >= 0)
-		dev->flags = flags;
-
-	return dev;
-}
-
-static void remove_same_uuid(gpointer data, gpointer user_data)
-{
-	struct remote_dev_info *dev = user_data;
-	GSList *l;
-
-	for (l = dev->services; l; l = l->next) {
-		char *current_uuid = l->data;
-		char *new_uuid = data;
-
-		if (strcmp(current_uuid, new_uuid) == 0) {
-			g_free(current_uuid);
-			dev->services = g_slist_delete_link(dev->services, l);
-			break;
-		}
-	}
-}
-
-static void dev_prepend_uuid(gpointer data, gpointer user_data)
-{
-	struct remote_dev_info *dev = user_data;
-	char *new_uuid = data;
-
-	dev->services = g_slist_prepend(dev->services, g_strdup(new_uuid));
-}
-
-static char *read_stored_data(const bdaddr_t *local, const bdaddr_t *peer,
-			      uint8_t peer_type, const char *file)
-{
-	char local_addr[18], key[20], filename[PATH_MAX + 1], *str;
-
-	ba2str(local, local_addr);
-
-	create_name(filename, PATH_MAX, STORAGEDIR, local_addr, file);
-
-	ba2str(peer, key);
-	sprintf(&key[17], "#%hhu", peer_type);
-
-	str = textfile_get(filename, key);
-	if (str != NULL)
-		return str;
-
-	/* Try old format (address only) */
-	key[17] = '\0';
-
-	return textfile_get(filename, key);
-}
-
 static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -3018,10 +2733,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 					bool confirm_name, bool legacy,
 					uint8_t *data, uint8_t data_len)
 {
-	struct remote_dev_info *dev;
+	struct btd_device *dev;
 	struct eir_data eir_data;
-	char *alias, *name;
-	gboolean name_known;
+	char addr[18];
 	int err;
 	GSList *l;
 
@@ -3043,81 +2757,51 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 		write_device_name(&adapter->bdaddr, bdaddr, bdaddr_type,
 								eir_data.name);
 
-	dev = adapter_search_found_devices(adapter, bdaddr);
-	if (dev && dev->bdaddr_type == BDADDR_BREDR) {
-		adapter->oor_devices = g_slist_remove(adapter->oor_devices,
-							dev);
-
-		/* If an existing device had no name but the newly received EIR
-		 * data has (complete or not), we want to present it to the
-		 * user. */
-		if (dev->name == NULL && eir_data.name != NULL) {
-			dev->name = g_strdup(eir_data.name);
-			goto done;
-		}
-
-		if (dev->rssi != rssi || dev->legacy != legacy)
-			goto done;
-
+	/* Avoid creating LE device if it's not discoverable */
+	if (bdaddr_type != BDADDR_BREDR &&
+			!(eir_data.flags & (EIR_LIM_DISC | EIR_GEN_DISC))) {
 		eir_data_free(&eir_data);
-
 		return;
 	}
 
-	/* New device in the discovery session */
-
-	name = read_stored_data(&adapter->bdaddr, bdaddr, bdaddr_type, "names");
+	ba2str(bdaddr, addr);
 
-	if (bdaddr_type == BDADDR_BREDR && !name && main_opts.name_resolv &&
-			adapter_has_discov_sessions(adapter))
-		name_known = FALSE;
+	l = g_slist_find_custom(adapter->devices, bdaddr,
+					(GCompareFunc) device_bdaddr_cmp);
+	if (l)
+		dev = l->data;
 	else
-		name_known = TRUE;
+		dev = adapter_create_device(adapter, addr, bdaddr_type);
 
-	if (confirm_name)
-		mgmt_confirm_name(adapter->dev_id, bdaddr, bdaddr_type,
-								name_known);
+	device_set_legacy(dev, legacy);
+	device_set_rssi(dev, rssi);
 
-	alias = read_stored_data(&adapter->bdaddr, bdaddr, bdaddr_type,
-								"aliases");
+	if (eir_data.name)
+		device_set_name(dev, eir_data.name);
 
-	dev = found_device_new(bdaddr, bdaddr_type, name, alias,
-				eir_data.class, legacy, eir_data.flags);
-	free(name);
-	free(alias);
+	device_add_eir_uuids(dev, eir_data.services);
 
-	adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);
+	eir_data_free(&eir_data);
 
-	if (bdaddr_type == BDADDR_LE_PUBLIC ||
-					bdaddr_type == BDADDR_LE_RANDOM) {
-		struct btd_device *device;
+	if (device_is_bredr(dev))
+		adapter->oor_devices = g_slist_remove(adapter->oor_devices,
+									dev);
 
-		l = g_slist_find_custom(adapter->connect_list, bdaddr,
-					(GCompareFunc) device_bdaddr_cmp);
-		if (!l)
-			goto done;
+	if (g_slist_find(adapter->found_devices, dev))
+		return;
 
-		device = l->data;
-		adapter_connect_list_remove(adapter, device);
+	if (confirm_name)
+		mgmt_confirm_name(adapter->dev_id, bdaddr, bdaddr_type,
+						device_name_known(dev));
 
-		g_idle_add(connect_pending_cb, btd_device_ref(device));
+	adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);
+
+	if (device_is_le(dev) && g_slist_find(adapter->connect_list, dev)) {
+		adapter_connect_list_remove(adapter, dev);
+		g_idle_add(connect_pending_cb, btd_device_ref(dev));
 		stop_discovery(adapter);
 		adapter->waiting_to_connect++;
 	}
-
-done:
-	dev->rssi = rssi;
-	dev->legacy = legacy;
-
-	adapter->found_devices = g_slist_sort(adapter->found_devices,
-						(GCompareFunc) dev_rssi_cmp);
-
-	g_slist_foreach(eir_data.services, remove_same_uuid, dev);
-	g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);
-
-	adapter_emit_device_found(adapter, dev);
-
-	eir_data_free(&eir_data);
 }
 
 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode)
diff --git a/src/adapter.h b/src/adapter.h
index d36c717..d53c658 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -76,20 +76,6 @@ struct smp_ltk_info {
 	uint8_t val[16];
 };
 
-struct remote_dev_info {
-	bdaddr_t bdaddr;
-	uint8_t bdaddr_type;
-	int8_t rssi;
-	uint32_t class;
-	char *name;
-	char *alias;
-	bool legacy;
-	char **uuids;
-	size_t uuid_count;
-	GSList *services;
-	uint8_t flags;
-};
-
 void btd_adapter_start(struct btd_adapter *adapter);
 
 int btd_adapter_stop(struct btd_adapter *adapter);
@@ -124,15 +110,11 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 uint16_t adapter_get_dev_id(struct btd_adapter *adapter);
 const gchar *adapter_get_path(struct btd_adapter *adapter);
 const bdaddr_t *adapter_get_address(struct btd_adapter *adapter);
-struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter,
-							const bdaddr_t *bdaddr);
 void adapter_update_found_devices(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
 					bool confirm_name, bool legacy,
 					uint8_t *data, uint8_t data_len);
-void adapter_emit_device_found(struct btd_adapter *adapter,
-						struct remote_dev_info *dev);
 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
 int adapter_set_name(struct btd_adapter *adapter, const char *name);
 void adapter_name_changed(struct btd_adapter *adapter, const char *name);
diff --git a/src/device.c b/src/device.c
index af0c593..349ae20 100644
--- a/src/device.c
+++ b/src/device.c
@@ -145,6 +145,8 @@ struct btd_device {
 	bdaddr_t	bdaddr;
 	uint8_t		bdaddr_type;
 	gchar		*path;
+	bool		svc_resolved;
+	GSList		*eir_uuids;
 	char		name[MAX_NAME_LENGTH + 1];
 	char		*alias;
 	uint16_t	vendor_src;
@@ -351,6 +353,14 @@ static gboolean dev_property_get_name(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean dev_property_exists_name(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct btd_device *dev = data;
+
+	return device_name_known(dev);
+}
+
 static gboolean dev_property_get_alias(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -795,7 +805,12 @@ static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
 				DBUS_TYPE_STRING_AS_STRING, &entry);
 
-	for (l = device->uuids; l != NULL; l = l->next)
+	if (!device->svc_resolved)
+		l = device->eir_uuids;
+	else
+		l = device->uuids;
+
+	for (; l != NULL; l = l->next)
 		dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
 							&l->data);
 
@@ -804,6 +819,17 @@ static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean dev_property_exists_uuids(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct btd_device *dev = data;
+
+	if (dev->svc_resolved)
+		return dev->uuids ? TRUE : FALSE;
+	else
+		return dev->eir_uuids ? TRUE : FALSE;
+}
+
 static gboolean dev_property_get_services(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -823,6 +849,13 @@ static gboolean dev_property_get_services(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean dev_property_exists_services(const GDBusPropertyTable *prop,
+								void *data)
+{
+	struct btd_device *dev = data;
+
+	return dev->services ? TRUE : FALSE;
+}
 
 static gboolean dev_property_get_adapter(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
@@ -1194,6 +1227,36 @@ static void dev_profile_connected(struct btd_profile *profile,
 	dev->connect = NULL;
 }
 
+void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
+{
+	GSList *l;
+	bool added = false;
+
+	if (dev->svc_resolved)
+		return;
+
+	for (l = uuids; l != NULL; l = l->next) {
+		const char *str = l->data;
+		if (g_slist_find_custom(dev->eir_uuids, str, bt_uuid_strcmp))
+			continue;
+		added = true;
+		dev->eir_uuids = g_slist_append(dev->eir_uuids, g_strdup(str));
+	}
+
+	if (added)
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						dev->path, DEVICE_INTERFACE,
+						"UUIDs");
+}
+
+static int device_resolve_svc(struct btd_device *dev, DBusMessage *msg)
+{
+	if (device_is_bredr(dev))
+		return device_browse_sdp(dev, msg, NULL, FALSE);
+	else
+		return device_browse_primary(dev, msg, FALSE);
+}
+
 static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
 							void *user_data)
 {
@@ -1205,9 +1268,16 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
 	if (dev->profiles_connected)
 		return btd_error_already_connected(msg);
 
-	if (dev->pending || dev->connect)
+	if (dev->pending || dev->connect || dev->browse)
 		return btd_error_in_progress(msg);
 
+	if (!dev->svc_resolved) {
+		err = device_resolve_svc(dev, msg);
+		if (err < 0)
+			return btd_error_failed(msg, strerror(-err));
+		return NULL;
+	}
+
 	for (l = dev->profiles; l != NULL; l = g_slist_next(l)) {
 		p = l->data;
 
@@ -1227,6 +1297,44 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+static void device_svc_resolved(struct btd_device *dev, int err)
+{
+	DBusMessage *reply;
+	DBusConnection *conn = btd_get_dbus_connection();
+	struct browse_req *req = dev->browse;
+
+	dev->svc_resolved = true;
+	dev->browse = NULL;
+
+	g_slist_free_full(dev->eir_uuids, g_free);
+	dev->eir_uuids = NULL;
+
+	if (!req || !req->msg)
+		return;
+
+	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
+						"DiscoverServices")) {
+		discover_services_reply(req, err, dev->tmp_records);
+	} else if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
+								"Pair")) {
+		reply = dbus_message_new_method_return(req->msg);
+		g_dbus_send_message(conn, reply);
+	} else if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
+								"Connect")) {
+		if (err) {
+			reply = btd_error_failed(req->msg, strerror(-err));
+			g_dbus_send_message(conn, reply);
+			return;
+		}
+
+		reply = dev_connect(conn, req->msg, dev);
+		if (reply)
+			g_dbus_send_message(conn, reply);
+		else
+			req->msg = NULL;
+	}
+}
+
 static uint8_t parse_io_capability(const char *capability)
 {
 	if (g_str_equal(capability, ""))
@@ -1286,7 +1394,7 @@ static const GDBusSignalTable device_signals[] = {
 
 static const GDBusPropertyTable device_properties[] = {
 	{ "Address", "s", dev_property_get_address },
-	{ "Name", "s", dev_property_get_name },
+	{ "Name", "s", dev_property_get_name, NULL, dev_property_exists_name },
 	{ "Alias", "s", dev_property_get_alias, dev_property_set_alias },
 	{ "Class", "u", dev_property_get_class, NULL,
 					dev_property_exists_class },
@@ -1308,8 +1416,10 @@ static const GDBusPropertyTable device_properties[] = {
 	{ "LegacyPairing", "b", dev_property_get_legacy },
 	{ "RSSI", "n", dev_property_get_rssi, NULL, dev_property_exists_rssi },
 	{ "Connected", "b", dev_property_get_connected },
-	{ "UUIDs", "as", dev_property_get_uuids },
-	{ "Services", "ao", dev_property_get_services },
+	{ "UUIDs", "as", dev_property_get_uuids, NULL,
+						dev_property_exists_uuids },
+	{ "Services", "ao", dev_property_get_services, NULL,
+						dev_property_exists_services },
 	{ "Adapter", "o", dev_property_get_adapter },
 	{ }
 };
@@ -1519,6 +1629,8 @@ void device_set_name(struct btd_device *device, const char *name)
 	if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
 		return;
 
+	DBG("%s %s", device->path, name);
+
 	strncpy(device->name, name, MAX_NAME_LENGTH);
 
 	g_dbus_emit_property_changed(btd_get_dbus_connection(), device->path,
@@ -2015,20 +2127,6 @@ static void store_profiles(struct btd_device *device)
 	g_free(str);
 }
 
-static void create_device_reply(struct btd_device *device, struct browse_req *req)
-{
-	DBusMessage *reply;
-
-	reply = dbus_message_new_method_return(req->msg);
-	if (!reply)
-		return;
-
-	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
-					DBUS_TYPE_INVALID);
-
-	g_dbus_send_message(btd_get_dbus_connection(), reply);
-}
-
 GSList *device_services_from_record(struct btd_device *device, GSList *profiles)
 {
 	GSList *l, *prim_list = NULL;
@@ -2115,33 +2213,11 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
 	uuids_changed(req->device);
 
 send_reply:
-	if (!req->msg)
-		goto cleanup;
-
-	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
-					"DiscoverServices"))
-		discover_services_reply(req, err, device->tmp_records);
-	else if (dbus_message_is_method_call(req->msg, ADAPTER_INTERFACE,
-						"CreatePairedDevice"))
-		create_device_reply(device, req);
-	else if (dbus_message_is_method_call(req->msg, ADAPTER_INTERFACE,
-						"CreateDevice")) {
-		if (err < 0) {
-			DBusMessage *reply;
-			reply = btd_error_failed(req->msg, strerror(-err));
-			g_dbus_send_message(btd_get_dbus_connection(), reply);
-			goto cleanup;
-		}
-
-		create_device_reply(device, req);
-		device_set_temporary(device, FALSE);
-	}
+	device_svc_resolved(device, err);
 
-cleanup:
 	if (!device->temporary)
 		store_profiles(device);
 
-	device->browse = NULL;
 	browse_request_free(req);
 }
 
@@ -2308,12 +2384,11 @@ static void register_all_services(struct browse_req *req, GSList *services)
 		attio_cleanup(device);
 
 	uuids_changed(device);
-	if (req->msg)
-		create_device_reply(device, req);
+
+	device_svc_resolved(device, 0);
 
 	store_services(device);
 
-	device->browse = NULL;
 	browse_request_free(req);
 }
 
diff --git a/src/device.h b/src/device.h
index 0f1f53f..ea646a8 100644
--- a/src/device.h
+++ b/src/device.h
@@ -54,6 +54,7 @@ void device_register_services(struct btd_device *device,
 GSList *device_services_from_record(struct btd_device *device,
 							GSList *profiles);
 void btd_device_add_uuid(struct btd_device *device, const char *uuid);
+void device_add_eir_uuids(struct btd_device *dev, GSList *uuids);
 void device_probe_profile(gpointer a, gpointer b);
 void device_remove_profile(gpointer a, gpointer b);
 struct btd_adapter *device_get_adapter(struct btd_device *device);
diff --git a/src/event.c b/src/event.c
index 5d0fd40..48aeffd 100644
--- a/src/event.c
+++ b/src/event.c
@@ -266,7 +266,6 @@ void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name)
 	struct btd_adapter *adapter;
 	struct btd_device *device;
 	uint8_t peer_type;
-	struct remote_dev_info *dev_info;
 
 	if (!g_utf8_validate(name, -1, NULL)) {
 		int i;
@@ -287,13 +286,6 @@ void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name)
 
 	write_device_name(local, peer, peer_type, name);
 
-	dev_info = adapter_search_found_devices(adapter, peer);
-	if (dev_info) {
-		g_free(dev_info->name);
-		dev_info->name = g_strdup(name);
-		adapter_emit_device_found(adapter, dev_info);
-	}
-
 	if (device)
 		device_set_name(device, name);
 }