Diff between caa49d9670ace03a054967ca9e72b082580a771f and 8bea94707a6441e4f09ba27d9acb23dd047754cb

Changed Files

File Additions Deletions Status
src/device.c +56 -8 modified

Full Patch

diff --git a/src/device.c b/src/device.c
index 57e7897..8626ad6 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1532,6 +1532,46 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
 	}
 }
 
+static gint primary_cmp(gconstpointer a, gconstpointer b)
+{
+	return memcmp(a, b, sizeof(struct gatt_primary));
+}
+
+static void update_gatt_services(struct browse_req *req, GSList *current,
+								GSList *found)
+{
+	GSList *l, *lmatch, *left = g_slist_copy(current);
+
+	/* Added Profiles */
+	for (l = found; l; l = g_slist_next(l)) {
+		struct gatt_primary *prim = l->data;
+
+		/* Entry found ? */
+		lmatch = g_slist_find_custom(current, prim, primary_cmp);
+		if (lmatch) {
+			left = g_slist_remove(left, lmatch->data);
+			continue;
+		}
+
+		/* New entry */
+		req->profiles_added = g_slist_append(req->profiles_added,
+							g_strdup(prim->uuid));
+
+		DBG("UUID Added: %s", prim->uuid);
+	}
+
+	/* Removed Profiles */
+	for (l = left; l; l = g_slist_next(l)) {
+		struct gatt_primary *prim = l->data;
+		req->profiles_removed = g_slist_append(req->profiles_removed,
+							g_strdup(prim->uuid));
+
+		DBG("UUID Removed: %s", prim->uuid);
+	}
+
+	g_slist_free(left);
+}
+
 static void store_profiles(struct btd_device *device)
 {
 	struct btd_adapter *adapter = device->adapter;
@@ -1830,11 +1870,17 @@ done:
 	return FALSE;
 }
 
+static void device_unregister_services(struct btd_device *device)
+{
+	attrib_client_unregister(device->services);
+	g_slist_free_full(device->services, g_free);
+	device->services = NULL;
+}
+
 static void primary_cb(GSList *services, guint8 status, gpointer user_data)
 {
 	struct browse_req *req = user_data;
 	struct btd_device *device = req->device;
-	GSList *l, *uuids = NULL;
 
 	if (status) {
 		if (req->msg) {
@@ -1848,20 +1894,22 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
 
 	device_set_temporary(device, FALSE);
 
-	for (l = services; l; l = l->next) {
-		struct gatt_primary *prim = l->data;
+	if (device->services)
+		device_unregister_services(device);
 
-		uuids = g_slist_append(uuids, prim->uuid);
-	}
+	update_gatt_services(req, device->primaries, services);
+	g_slist_free_full(device->primaries, g_free);
+	device->primaries = NULL;
 
 	device_register_services(req->conn, device, g_slist_copy(services), -1);
-	device_probe_drivers(device, uuids);
+	if (req->profiles_removed)
+		device_remove_drivers(device, req->profiles_removed);
+
+	device_probe_drivers(device, req->profiles_added);
 
 	if (device->attios == NULL && device->attios_offline == NULL)
 		attio_cleanup(device);
 
-	g_slist_free(uuids);
-
 	services_changed(device);
 	if (req->msg)
 		create_device_reply(device, req);