All of lore.kernel.org
 help / color / mirror / Atom feed
From: "João Paulo Rechi Vita" <jprvita@openbossa.org>
To: linux-bluetooth@vger.kernel.org
Cc: "João Paulo Rechi Vita" <jprvita@openbossa.org>
Subject: [BlueZ 15/15] HoG: Prepend report id to the HID report
Date: Thu, 26 Apr 2012 16:45:45 -0300	[thread overview]
Message-ID: <1335469545-1007-15-git-send-email-jprvita@openbossa.org> (raw)
In-Reply-To: <1335469545-1007-1-git-send-email-jprvita@openbossa.org>

If the report descriptor has a report id tag it has to be prepended
to the report data to construct the report itself.
---
 input/hog_device.c |   74 ++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/input/hog_device.c b/input/hog_device.c
index 99de25c..081f33c 100644
--- a/input/hog_device.c
+++ b/input/hog_device.c
@@ -59,10 +59,6 @@
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #endif
 
-struct report {
-	struct gatt_char *decl;
-};
-
 struct hog_device {
 	char			*path;
 	struct btd_device	*device;
@@ -72,16 +68,35 @@ struct hog_device {
 	struct gatt_primary	*hog_primary;
 	GSList			*reports;
 	int			uhid_fd;
+	gboolean		prepend_id;
+};
+
+struct report {
+	uint8_t			id;
+	uint8_t			type;
+	struct gatt_char	*decl;
+	struct hog_device	*hogdev;
 };
 
 static GSList *devices = NULL;
 
+static gint report_handle_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct report *report = a;
+	uint16_t handle = GPOINTER_TO_UINT(b);
+
+	return report->decl->value_handle - handle;
+}
+
 static void report_value_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
 	struct uhid_event ev;
 	uint16_t handle;
 	uint16_t report_size = len - 3;
+	GSList *l;
+	struct report *report;
+	uint8_t *buf;
 
 	if (len < 3) { /* 1-byte opcode + 2-byte handle */
 		error("Malformed ATT notification");
@@ -90,10 +105,26 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len, gpointer user_data
 
 	handle = att_get_u16(&pdu[1]);
 
+	l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(handle),
+							report_handle_cmp);
+	if (!l) {
+		error("Invalid report");
+		return;
+	}
+	report = l->data;
+
 	memset(&ev, 0, sizeof(ev));
 	ev.type = UHID_INPUT;
 	ev.u.input.size = MIN(report_size, UHID_DATA_MAX);
-	memcpy(ev.u.input.data, &pdu[3], MIN(report_size, UHID_DATA_MAX));
+
+	buf = ev.u.input.data;
+	if (hogdev->prepend_id) {
+		*buf = report->id;
+		buf++;
+		ev.u.input.size++;
+	}
+
+	memcpy(buf, &pdu[3], MIN(report_size, UHID_DATA_MAX));
 
 	if (write(hogdev->uhid_fd, &ev, sizeof(ev)) < 0)
 		error("UHID write failed: %s", strerror(errno));
@@ -123,6 +154,8 @@ static void write_ccc(uint16_t handle, gpointer user_data)
 static void report_reference_cb(guint8 status, const guint8 *pdu,
 					guint16 plen, gpointer user_data)
 {
+	struct report *report = user_data;
+
 	if (status != 0) {
 		error("Read Report Reference descriptor failed: %s",
 							att_ecode2str(status));
@@ -134,13 +167,16 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
 		return;
 	}
 
+	report->id = pdu[1];
+	report->type = pdu[2];
 	DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);
 }
 
 static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
 					guint16 len, gpointer user_data)
 {
-	struct hog_device *hogdev = user_data;
+	struct report *report = user_data;
+	struct hog_device *hogdev = report->hogdev;
 	struct att_data_list *list;
 	uint8_t format;
 	int i;
@@ -167,10 +203,10 @@ static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
 		uuid16 = att_get_u16(&value[2]);
 
 		if (uuid16 == GATT_CLIENT_CHARAC_CFG_UUID)
-			write_ccc(handle, user_data);
+			write_ccc(handle, hogdev);
 		else if (uuid16 == GATT_REPORT_REFERENCE)
 			gatt_read_char(hogdev->attrib, handle, 0,
-					report_reference_cb, hogdev);
+					report_reference_cb, report);
 	}
 
 done:
@@ -211,11 +247,20 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	}
 
 	DBG("Report MAP:");
-	for (i = 0; i < vlen; i += 2) {
-		if (i + 1 == vlen)
-			DBG("\t %02x", value[i]);
-		else
-			DBG("\t %02x %02x", value[i], value[i + 1]);
+	for (i = 0; i < vlen; i++) {
+		switch (value[i]) {
+			case 0x85:
+			case 0x86:
+			case 0x87:
+				hogdev->prepend_id = TRUE;
+		}
+
+		if (i % 2 == 0) {
+			if (i + 1 == vlen)
+				DBG("\t %02x", value[i]);
+			else
+				DBG("\t %02x %02x", value[i], value[i + 1]);
+		}
 	}
 
 	vendor_src = btd_device_get_vendor_src(hogdev->device);
@@ -271,10 +316,11 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 
 		if (bt_uuid_cmp(&uuid, &report_uuid) == 0) {
 			report = g_new0(struct report, 1);
+			report->hogdev = hogdev;
 			report->decl = g_memdup(chr, sizeof(*chr));
 			hogdev->reports = g_slist_append(hogdev->reports,
 								report);
-			discover_descriptor(hogdev->attrib, chr, next, hogdev);
+			discover_descriptor(hogdev->attrib, chr, next, report);
 		} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0)
 			gatt_read_char(hogdev->attrib, chr->value_handle, 0,
 						report_map_read_cb, hogdev);
-- 
1.7.7.6


      parent reply	other threads:[~2012-04-26 19:45 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-26 19:45 [BlueZ 01/15] HoG: Register HID over GATT device driver João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 02/15] HoG: register ATTIO callbacks João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 03/15] HoG: load primary service handle João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 04/15] HoG: discover all characteristics declaration João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 05/15] HoG: discover descriptors for all characteristics João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 06/15] HoG: discover the "Report Map" characteristic João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 07/15] HoG: enable "Report" characteristic notification João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 08/15] HoG: add report notification handler João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 09/15] HoG: HID I/O driver João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 10/15] HoG: Use real values for vendor and product IDs João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 11/15] GATT: Add Report Reference Descriptor declaration João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 12/15] HoG: Add read Report Reference descriptor João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 13/15] GATT: Rename Characteristic Configuration constants João Paulo Rechi Vita
2012-04-26 19:45 ` [BlueZ 14/15] GATT: Move GATT assigned numbers to GATT header João Paulo Rechi Vita
2012-04-26 19:45 ` João Paulo Rechi Vita [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1335469545-1007-15-git-send-email-jprvita@openbossa.org \
    --to=jprvita@openbossa.org \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.