[PATCH BlueZ 2/2] android/hog: Fix report lookup

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

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This fixes not utilizing the report id to match the characteristic that
map it.
---
 android/hog.c | 87 ++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 34 deletions(-)

diff --git a/android/hog.c b/android/hog.c
index 09a16d5..51c7c64 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -382,12 +382,47 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
 					external_service_char_cb, hog);
 }
 
-static int report_type_cmp(gconstpointer a, gconstpointer b)
+
+static int report_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct report *ra = a, *rb = b;
+
+	/* sort by type first.. */
+	if (ra->type != rb->type)
+		return ra->type - rb->type;
+
+	/* skip id check in case of report id 0 */
+	if (!rb->id)
+		return 0;
+
+	/* ..then by id */
+	return ra->id - rb->id;
+}
+
+static struct report *find_report(struct bt_hog *hog, uint8_t type, uint8_t id)
 {
-	const struct report *report = a;
-	uint8_t type = GPOINTER_TO_UINT(b);
+	struct report cmp;
+	GSList *l;
+
+	switch (type) {
+	case UHID_FEATURE_REPORT:
+		cmp.type = HOG_REPORT_TYPE_FEATURE;
+		break;
+	case UHID_OUTPUT_REPORT:
+		cmp.type = HOG_REPORT_TYPE_OUTPUT;
+		break;
+	case UHID_INPUT_REPORT:
+		cmp.type = HOG_REPORT_TYPE_INPUT;
+		break;
+	default:
+		return NULL;
+	}
+
+	cmp.id = hog->has_report_id ? id : 0;
 
-	return report->type - type;
+	l = g_slist_find_custom(hog->reports, &cmp, report_cmp);
+
+	return l ? l->data : NULL;
 }
 
 static void output_written_cb(guint8 status, const guint8 *pdu,
@@ -403,30 +438,22 @@ static void forward_report(struct uhid_event *ev, void *user_data)
 {
 	struct bt_hog *hog = user_data;
 	struct report *report;
-	GSList *l;
 	void *data;
 	int size;
-	guint type;
-
-	if (hog->has_report_id) {
-		data = ev->u.output.data + 1;
-		size = ev->u.output.size - 1;
-	} else {
-		data = ev->u.output.data;
-		size = ev->u.output.size;
-	}
 
-	type = HOG_REPORT_TYPE_OUTPUT;
-
-	l = g_slist_find_custom(hog->reports, GUINT_TO_POINTER(type),
-							report_type_cmp);
-	if (!l)
+	report = find_report(hog, ev->u.output.rtype, ev->u.output.data[0]);
+	if (!report)
 		return;
 
-	report = l->data;
+	data = ev->u.output.data;
+	size = ev->u.output.size;
+	if (hog->has_report_id && size > 0) {
+		data++;
+		--size;
+	}
 
-	DBG("Sending report type %d to handle 0x%X", type,
-						report->decl->value_handle);
+	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
+				report->id, report->decl->value_handle);
 
 	if (hog->attrib == NULL)
 		return;
@@ -443,7 +470,6 @@ static void get_report(struct uhid_event *ev, void *user_data)
 {
 	struct bt_hog *hog = user_data;
 	struct report *report;
-	GSList *l;
 	struct uhid_event rsp;
 	int err;
 
@@ -451,16 +477,12 @@ static void get_report(struct uhid_event *ev, void *user_data)
 	rsp.type = UHID_FEATURE_ANSWER;
 	rsp.u.feature_answer.id = ev->u.feature.id;
 
-	l = g_slist_find_custom(hog->reports,
-				GUINT_TO_POINTER(ev->u.feature.rtype),
-				report_type_cmp);
-	if (!l) {
+	report = find_report(hog, ev->u.feature.rtype, ev->u.feature.rnum);
+	if (!report) {
 		rsp.u.feature_answer.err = ENOTSUP;
 		goto done;
 	}
 
-	report = l->data;
-
 	if (!report->value) {
 		rsp.u.feature_answer.err = EIO;
 		goto done;
@@ -1090,13 +1112,10 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
 	if (!hog->attrib)
 		return -ENOTCONN;
 
-	l = g_slist_find_custom(hog->reports, GUINT_TO_POINTER(type),
-							report_type_cmp);
-	if (!l)
+	report = find_report(hog, type, 0);
+	if (!report)
 		return -ENOTSUP;
 
-	report = l->data;
-
 	DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
 
 	if (report->decl->properties & GATT_CHR_PROP_WRITE)
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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