[PATCH] hog: fix output-report to attr mapping

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

 



Instead of mapping all UHID_OUTPUT events blindly to the first hid output
report found, we now map it to the correct attribute. We use the rtype and
report-id information in each UHID_OUTPUT message and map it according to
the mapping-characteristics provided by the device.
---
 profiles/input/hog.c | 55 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index df2b30b..30f9ed1 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -306,12 +306,16 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
 					external_service_char_cb, hogdev);
 }
 
-static int report_type_cmp(gconstpointer a, gconstpointer b)
+static int report_cmp(gconstpointer a, gconstpointer b)
 {
-	const struct report *report = a;
-	uint8_t type = GPOINTER_TO_UINT(b);
+	const struct report *ra = a, *rb = b;
 
-	return report->type - type;
+	/* sort by type first.. */
+	if (ra->type != rb->type)
+		return ra->type - rb->type;
+
+	/* ..then by id */
+	return ra->id - rb->id;
 }
 
 static void output_written_cb(guint8 status, const guint8 *pdu,
@@ -326,31 +330,44 @@ static void output_written_cb(guint8 status, const guint8 *pdu,
 static void forward_report(struct uhid_event *ev, void *user_data)
 {
 	struct hog_device *hogdev = user_data;
-	struct report *report;
+	struct report *report, cmp;
 	GSList *l;
-	void *data;
-	int size;
-	guint type;
+	uint8_t *data;
+	int size, type, id;
+
+	switch (ev->u.output.rtype) {
+	case UHID_FEATURE_REPORT:
+		type = HOG_REPORT_TYPE_FEATURE;
+		break;
+	case UHID_OUTPUT_REPORT:
+		type = HOG_REPORT_TYPE_OUTPUT;
+		break;
+	case UHID_INPUT_REPORT:
+		type = HOG_REPORT_TYPE_INPUT;
+		break;
+	default:
+		return;
+	}
 
-	if (hogdev->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;
+	id = 0;
+	data = ev->u.output.data;
+	size = ev->u.output.size;
+	if (hogdev->has_report_id && size > 0) {
+		id = *data++;
+		--size;
 	}
 
-	type = HOG_REPORT_TYPE_OUTPUT;
+	cmp.type = type;
+	cmp.id = id;
 
-	l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(type),
-							report_type_cmp);
+	l = g_slist_find_custom(hogdev->reports, &cmp, report_cmp);
 	if (!l)
 		return;
 
 	report = l->data;
 
-	DBG("Sending report type %d to device 0x%04X handle 0x%X", type,
-				hogdev->id, report->decl->value_handle);
+	DBG("Sending report type %d ID %d to device 0x%04X handle 0x%X",
+			type, id, hogdev->id, report->decl->value_handle);
 
 	if (hogdev->attrib == NULL)
 		return;
-- 
2.0.4

--
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