diff mbox

[4/5] hid: ntrig: Support single-touch devices

Message ID 1289549514-5421-5-git-send-email-rydberg@euromail.se
State Accepted
Delegated to: Andy Whitcroft
Headers show

Commit Message

Henrik Rydberg Nov. 12, 2010, 8:11 a.m. UTC
From: Henrik Rydberg <rydberg@bitmath.org>

The current driver was regressed to not work for single-touch devices,
and the driver occasionally crashes in those cases. The HID report
which resets the array index is never received, resulting in out-of-range
memory access. This patch restores functionality by detecting the presence
of the multitouch firmware, and adds a range check to make the driver
resilient to unknown firmware versions.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-ntrig.c |   20 +++++++++++++++++++-
 1 files changed, 19 insertions(+), 1 deletions(-)
diff mbox

Patch

diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 695fa54..05f7e27 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -50,6 +50,8 @@  struct ntrig_data {
 	int nrow, ncol;
 	int index, nindex;
 	int nhold;
+	bool touch;
+	bool hasmt;
 };
 
 
@@ -180,7 +182,14 @@  static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			return 1;
 		}
 		return 0;
+
 	case 0xff000000:
+		switch (usage->hid) {
+		case 0xff000001:
+			/* multi-touch firmware */
+			nd->hasmt = true;
+			break;
+		}
 		/* we do not want to map these: no input-oriented meaning */
 		return -1;
 	}
@@ -334,7 +343,9 @@  static int ntrig_event (struct hid_device *hid, struct hid_field *field,
         if (hid->claimed & HID_CLAIMED_INPUT) {
 		switch (usage->hid) {
 		case HID_DG_TIPSWITCH:
-			nd->index = nd->nindex++;
+			nd->touch = value;
+			if (nd->nindex < MAX_SLOTS)
+				nd->index = nd->nindex++;
 			break;
 		case HID_GD_X:
 			nd->col[nd->index].x = value;
@@ -347,8 +358,15 @@  static int ntrig_event (struct hid_device *hid, struct hid_field *field,
 			break;
 		case HID_DG_HEIGHT:
 			nd->col[nd->index].h = value;
+			if (!nd->hasmt) {
+				nd->nindex = 0;
+				nd->ncol = nd->touch;
+				report_frame(input, nd);
+			}
 			break;
 		case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
+			if (!nd->hasmt)
+				break;
 			nd->nindex = 0;
 			nd->ncol = value;
 			report_frame(input, nd);