Implement cancel primary discovery session

Extend bt_cancel_discovery function to cancel an ongoing Discover
All Primary Services procedure.
diff --git a/src/device.c b/src/device.c
index cec2153..d20a6d4 100644
--- a/src/device.c
+++ b/src/device.c
@@ -186,8 +186,7 @@
 
 	adapter_get_address(adapter, &src);
 
-	if (device->type != DEVICE_TYPE_LE)
-		bt_cancel_discovery(&src, &device->bdaddr);
+	bt_cancel_discovery(&src, &device->bdaddr);
 
 	device->browse = NULL;
 	browse_request_free(req);
@@ -1530,11 +1529,11 @@
 		goto done;
 	}
 
-	services_changed(req->device);
-	device_set_temporary(req->device, FALSE);
-	device_probe_drivers(req->device, services);
+	services_changed(device);
+	device_set_temporary(device, FALSE);
+	device_probe_drivers(device, services);
 
-	create_device_reply(req->device, req);
+	create_device_reply(device, req);
 
 done:
 	device->browse = NULL;
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 8181f4d..6505249 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -51,12 +51,15 @@
 	bdaddr_t src;
 	bdaddr_t dst;
 	GAttrib *attrib;
+	GIOChannel *io;
 	bt_primary_t cb;
 	bt_destroy_t destroy;
 	gpointer user_data;
 	GSList *uuids;
 };
 
+static GSList *gattrib_list = NULL;
+
 struct cached_sdp_session {
 	bdaddr_t src;
 	bdaddr_t dst;
@@ -68,12 +71,18 @@
 
 static void gattrib_context_free(struct gattrib_context *ctxt)
 {
+	gattrib_list = g_slist_remove(gattrib_list, ctxt);
 	if (ctxt->destroy)
 		ctxt->destroy(ctxt->user_data);
 
 	g_slist_foreach(ctxt->uuids, (GFunc) g_free, NULL);
 	g_slist_free(ctxt->uuids);
 	g_attrib_unref(ctxt->attrib);
+	if (ctxt->io) {
+		g_io_channel_unref(ctxt->io);
+		g_io_channel_shutdown(ctxt->io, FALSE, NULL);
+	}
+
 	g_free(ctxt);
 }
 
@@ -138,7 +147,6 @@
 	bdaddr_t		dst;
 	sdp_session_t		*session;
 	bt_callback_t		cb;
-	bt_primary_t		prim_cb;
 	bt_destroy_t		destroy;
 	gpointer		user_data;
 	uuid_t			uuid;
@@ -373,21 +381,16 @@
 					bacmp(&ctxt->src, &search->src));
 }
 
-int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
+static gint gattrib_find_by_bdaddr(gconstpointer data, gconstpointer user_data)
 {
-	struct search_context search, *ctxt;
-	GSList *match;
+	const struct gattrib_context *ctxt = data, *search = user_data;
 
-	memset(&search, 0, sizeof(search));
-	bacpy(&search.src, src);
-	bacpy(&search.dst, dst);
+	return (bacmp(&ctxt->dst, &search->dst) &&
+					bacmp(&ctxt->src, &search->src));
+}
 
-	/* Ongoing SDP Discovery */
-	match = g_slist_find_custom(context_list, &search, find_by_bdaddr);
-	if (!match)
-		return -ENODATA;
-
-	ctxt = match->data;
+static int cancel_sdp(struct search_context *ctxt)
+{
 	if (!ctxt->session)
 		return -ENOTCONN;
 
@@ -398,9 +401,48 @@
 		sdp_close(ctxt->session);
 
 	search_context_cleanup(ctxt);
+
 	return 0;
 }
 
+static int cancel_gattrib(struct gattrib_context *ctxt)
+{
+	if (ctxt->attrib)
+		g_attrib_cancel_all(ctxt->attrib);
+
+	gattrib_context_free(ctxt);
+
+	return 0;
+}
+
+int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
+{
+	struct search_context sdp_ctxt;
+	struct gattrib_context gatt_ctxt;
+	GSList *match;
+
+	memset(&sdp_ctxt, 0, sizeof(sdp_ctxt));
+	bacpy(&sdp_ctxt.src, src);
+	bacpy(&sdp_ctxt.dst, dst);
+
+	/* Ongoing SDP Discovery */
+	match = g_slist_find_custom(context_list, &sdp_ctxt, find_by_bdaddr);
+	if (match)
+		return cancel_sdp(match->data);
+
+	memset(&gatt_ctxt, 0, sizeof(gatt_ctxt));
+	bacpy(&gatt_ctxt.src, src);
+	bacpy(&gatt_ctxt.dst, dst);
+
+	/* Ongoing Discover All Primary Services */
+	match = g_slist_find_custom(gattrib_list, &gatt_ctxt,
+						gattrib_find_by_bdaddr);
+	if (match == NULL)
+		return -ENOTCONN;
+
+	return cancel_gattrib(match->data);
+}
+
 static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
@@ -471,6 +513,7 @@
 		return;
 	}
 
+	ctxt->attrib = g_attrib_new(io);
 	gatt_discover_primary(ctxt->attrib, 0x0001, 0xffff, NULL, primary_cb,
 									ctxt);
 }
@@ -513,9 +556,9 @@
 		return -EIO;
 	}
 
-	ctxt->attrib = g_attrib_new(io);
+	ctxt->io = io;
 
-	g_io_channel_unref(io);
+	gattrib_list = g_slist_append(gattrib_list, ctxt);
 
 	return 0;
 }