Diff between 2fa0703398125bc6a2aa25be05324f656ddc494f and c730f68303d73f987dda829c17360a11308a046c

Changed Files

File Additions Deletions Status
src/device.c +8 -18 modified
src/sdp-client.c +56 -5 modified
src/sdp-client.h +3 -0 modified

Full Patch

diff --git a/src/device.c b/src/device.c
index a8f4c22..c351a15 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4584,27 +4584,18 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
 
 	for (seq = recs; seq; seq = seq->next) {
 		sdp_record_t *rec = (sdp_record_t *) seq->data;
-		sdp_list_t *svcclass = NULL;
 		char *profile_uuid;
 
 		if (!rec)
 			break;
 
-		if (sdp_get_service_classes(rec, &svcclass) < 0)
-			continue;
-
-		/* Check for empty service classes list */
-		if (svcclass == NULL) {
-			DBG("Skipping record with no service classes");
-			continue;
-		}
+		/* If service class attribute is missing, svclass will be all
+		 * zero and the resulting uuid string will be NULL.
+		 */
+		profile_uuid = bt_uuid2string(&rec->svclass);
 
-		/* Extract the first element and skip the remainning */
-		profile_uuid = bt_uuid2string(svcclass->data);
-		if (!profile_uuid) {
-			sdp_list_free(svcclass, free);
+		if (!profile_uuid)
 			continue;
-		}
 
 		if (bt_uuid_strcmp(profile_uuid, PNP_UUID) == 0) {
 			uint16_t source, vendor, product, version;
@@ -4638,7 +4629,6 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
 
 next:
 		free(profile_uuid);
-		sdp_list_free(svcclass, free);
 	}
 
 	if (sdp_key_file) {
@@ -5352,9 +5342,9 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg)
 
 	req->sdp_flags = get_sdp_flags(device);
 
-	err = bt_search_service(btd_adapter_get_address(adapter),
-				&device->bdaddr, &uuid, browse_cb, req, NULL,
-				req->sdp_flags);
+	err = bt_search(btd_adapter_get_address(adapter),
+			&device->bdaddr, &uuid, browse_cb, req, NULL,
+			req->sdp_flags);
 	if (err < 0) {
 		browse_request_free(req);
 		return err;
diff --git a/src/sdp-client.c b/src/sdp-client.c
index 413cf30..b92a083 100644
--- a/src/sdp-client.c
+++ b/src/sdp-client.c
@@ -143,6 +143,7 @@ struct search_context {
 	gpointer		user_data;
 	uuid_t			uuid;
 	guint			io_id;
+	gboolean		filter_svc_class;
 };
 
 static GSList *context_list = NULL;
@@ -195,6 +196,16 @@ static void search_completed_cb(uint8_t type, uint16_t status,
 		rsp += recsize;
 		bytesleft -= recsize;
 
+		/* Check whether service class ID matches some specified uuid.
+		 * If the record is missing service class ID, svclass will be
+		 * all zero, and thus will be unequal to the requested uuid.
+		 */
+		if (ctxt->filter_svc_class &&
+				sdp_uuid_cmp(&ctxt->uuid, &rec->svclass) != 0) {
+			sdp_record_free(rec);
+			continue;
+		}
+
 		recs = sdp_list_append(recs, rec);
 	} while (scanned < (ssize_t) size && bytesleft > 0);
 
@@ -338,7 +349,28 @@ static int create_search_context(struct search_context **ctxt,
 	return 0;
 }
 
-int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
+static int create_search_context_full(struct search_context **ctxt,
+					const bdaddr_t *src,
+					const bdaddr_t *dst,
+					uuid_t *uuid, uint16_t flags,
+					void *user_data, bt_callback_t cb,
+					bt_destroy_t destroy,
+					gboolean filter_svc_class)
+{
+	int err = create_search_context(ctxt, src, dst, uuid, flags);
+
+	if (err < 0)
+		return err;
+
+	(*ctxt)->cb = cb;
+	(*ctxt)->destroy = destroy;
+	(*ctxt)->user_data = user_data;
+	(*ctxt)->filter_svc_class = filter_svc_class;
+
+	return 0;
+}
+
+int bt_search(const bdaddr_t *src, const bdaddr_t *dst,
 			uuid_t *uuid, bt_callback_t cb, void *user_data,
 			bt_destroy_t destroy, uint16_t flags)
 {
@@ -348,13 +380,32 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
 	if (!cb)
 		return -EINVAL;
 
-	err = create_search_context(&ctxt, src, dst, uuid, flags);
+	/* The resulting service class ID doesn't have to match uuid */
+	err = create_search_context_full(&ctxt, src, dst, uuid, flags,
+					user_data, cb, destroy, FALSE);
 	if (err < 0)
 		return err;
 
-	ctxt->cb	= cb;
-	ctxt->destroy	= destroy;
-	ctxt->user_data	= user_data;
+	context_list = g_slist_append(context_list, ctxt);
+
+	return 0;
+}
+
+int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
+			uuid_t *uuid, bt_callback_t cb, void *user_data,
+			bt_destroy_t destroy, uint16_t flags)
+{
+	struct search_context *ctxt = NULL;
+	int err;
+
+	if (!cb)
+		return -EINVAL;
+
+	/* The resulting service class ID need to match uuid */
+	err = create_search_context_full(&ctxt, src, dst, uuid, flags,
+					user_data, cb, destroy, TRUE);
+	if (err < 0)
+		return err;
 
 	context_list = g_slist_append(context_list, ctxt);
 
diff --git a/src/sdp-client.h b/src/sdp-client.h
index 9aa5a4d..3a7212f 100644
--- a/src/sdp-client.h
+++ b/src/sdp-client.h
@@ -24,6 +24,9 @@
 typedef void (*bt_callback_t) (sdp_list_t *recs, int err, gpointer user_data);
 typedef void (*bt_destroy_t) (gpointer user_data);
 
+int bt_search(const bdaddr_t *src, const bdaddr_t *dst,
+			uuid_t *uuid, bt_callback_t cb, void *user_data,
+			bt_destroy_t destroy, uint16_t flags);
 int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
 			uuid_t *uuid, bt_callback_t cb, void *user_data,
 			bt_destroy_t destroy, uint16_t flags);