瀏覽代碼

HID: 3m: Adjust to sequential MT HID protocol

The multitouch extensions to the HID protocol allows for contact
data to be sent over several reports, which is also the case for
the 3M M2256PW touchscreen. This patch modifies the logic to only
synchronize the input layer when all contacts have been received.
Consequentially, the full 60-finger capacity of the device is enabled.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Acked-by: Stephane Chatty <chatty@enac.fr>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Henrik Rydberg 14 年之前
父節點
當前提交
41035901df
共有 1 個文件被更改,包括 18 次插入4 次删除
  1. 18 4
      drivers/hid/hid-3m-pct.c

+ 18 - 4
drivers/hid/hid-3m-pct.c

@@ -24,6 +24,9 @@ MODULE_LICENSE("GPL");
 
 
 #include "hid-ids.h"
 #include "hid-ids.h"
 
 
+#define MAX_SLOTS		60
+#define MAX_TRKID		59
+
 struct mmm_finger {
 struct mmm_finger {
 	__s32 x, y, w, h;
 	__s32 x, y, w, h;
 	__u8 rank;
 	__u8 rank;
@@ -31,8 +34,9 @@ struct mmm_finger {
 };
 };
 
 
 struct mmm_data {
 struct mmm_data {
-	struct mmm_finger f[10];
+	struct mmm_finger f[MAX_SLOTS];
 	__u8 curid, num;
 	__u8 curid, num;
+	__u8 nexp, nreal;
 	bool touch, valid;
 	bool touch, valid;
 };
 };
 
 
@@ -93,7 +97,7 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					1, 1, 0, 0);
 					1, 1, 0, 0);
 			return 1;
 			return 1;
 		case HID_DG_CONTACTID:
 		case HID_DG_CONTACTID:
-			field->logical_maximum = 59;
+			field->logical_maximum = MAX_TRKID;
 			hid_map_usage(hi, usage, bit, max,
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TRACKING_ID);
 					EV_ABS, ABS_MT_TRACKING_ID);
 			return 1;
 			return 1;
@@ -133,7 +137,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
 	 * we need to iterate on all fingers to decide if we have a press
 	 * we need to iterate on all fingers to decide if we have a press
 	 * or a release event in our touchscreen emulation.
 	 * or a release event in our touchscreen emulation.
 	 */
 	 */
-	for (i = 0; i < 10; ++i) {
+	for (i = 0; i < MAX_SLOTS; ++i) {
 		struct mmm_finger *f = &md->f[i];
 		struct mmm_finger *f = &md->f[i];
 		if (!f->valid) {
 		if (!f->valid) {
 			/* this finger is just placeholder data, ignore */
 			/* this finger is just placeholder data, ignore */
@@ -190,6 +194,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
 	} else if (released) {
 	} else if (released) {
 		input_event(input, EV_KEY, BTN_TOUCH, 0);
 		input_event(input, EV_KEY, BTN_TOUCH, 0);
 	}
 	}
+	input_sync(input);
 }
 }
 
 
 /*
 /*
@@ -223,10 +228,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field,
 				md->f[md->curid].h = value;
 				md->f[md->curid].h = value;
 			break;
 			break;
 		case HID_DG_CONTACTID:
 		case HID_DG_CONTACTID:
+			value = clamp_val(value, 0, MAX_SLOTS - 1);
 			if (md->valid) {
 			if (md->valid) {
 				md->curid = value;
 				md->curid = value;
 				md->f[value].touch = md->touch;
 				md->f[value].touch = md->touch;
 				md->f[value].valid = 1;
 				md->f[value].valid = 1;
+				md->nreal++;
 			}
 			}
 			break;
 			break;
 		case HID_GD_X:
 		case HID_GD_X:
@@ -238,7 +245,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field,
 				md->f[md->curid].y = value;
 				md->f[md->curid].y = value;
 			break;
 			break;
 		case HID_DG_CONTACTCOUNT:
 		case HID_DG_CONTACTCOUNT:
-			mmm_filter_event(md, input);
+			if (value)
+				md->nexp = value;
+			if (md->nreal >= md->nexp) {
+				mmm_filter_event(md, input);
+				md->nreal = 0;
+			}
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -255,6 +267,8 @@ static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	int ret;
 	int ret;
 	struct mmm_data *md;
 	struct mmm_data *md;
 
 
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
 	md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
 	md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
 	if (!md) {
 	if (!md) {
 		dev_err(&hdev->dev, "cannot allocate 3M data\n");
 		dev_err(&hdev->dev, "cannot allocate 3M data\n");