108 lines
4.3 KiB
Diff
108 lines
4.3 KiB
Diff
From 8c6b638bb620eef53cb83ffe88d7b528f666af10 Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Wed, 22 Nov 2017 12:57:08 +0100
|
|
Subject: [PATCH] HID: multitouch: Properly deal with Win8 PTP reports with 0
|
|
touches
|
|
|
|
The Windows Precision Touchpad spec "Figure 4 Button Only Down and Up"
|
|
and "Table 9 Report Sequence for Button Only Down and Up" indicate
|
|
that the first packet of a (possibly hybrid mode multi-packet) frame
|
|
may contain a contact-count of 0 if only a button is pressed and no
|
|
fingers are detected.
|
|
|
|
This means that a value of 0 for contact-count is a valid value and
|
|
should be used as expected contact count when it is the first packet
|
|
(num_received == 0), as extra check to make sure that this is the first
|
|
packet of a buttons only frame, we also check that the timestamp is
|
|
different.
|
|
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
|
---
|
|
drivers/hid/hid-multitouch.c | 32 ++++++++++++++++++++++++++++++--
|
|
1 file changed, 30 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
|
index 397592959238..0a42e19d914a 100644
|
|
--- a/drivers/hid/hid-multitouch.c
|
|
+++ b/drivers/hid/hid-multitouch.c
|
|
@@ -119,6 +119,9 @@ struct mt_device {
|
|
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
|
int cc_index; /* contact count field index in the report */
|
|
int cc_value_index; /* contact count value index in the field */
|
|
+ int scantime_index; /* scantime field index in the report */
|
|
+ int scantime_val_index; /* scantime value index in the field */
|
|
+ int prev_scantime; /* scantime reported in the previous packet */
|
|
unsigned last_slot_field; /* the last field of a slot */
|
|
unsigned mt_report_id; /* the report ID of the multitouch device */
|
|
unsigned long initial_quirks; /* initial quirks state */
|
|
@@ -599,6 +602,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|
EV_MSC, MSC_TIMESTAMP);
|
|
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
|
|
mt_store_field(usage, td, hi);
|
|
+ /* Ignore if indexes are out of bounds. */
|
|
+ if (field->index >= field->report->maxfield ||
|
|
+ usage->usage_index >= field->report_count)
|
|
+ return 1;
|
|
+ td->scantime_index = field->index;
|
|
+ td->scantime_val_index = usage->usage_index;
|
|
return 1;
|
|
case HID_DG_CONTACTCOUNT:
|
|
/* Ignore if indexes are out of bounds. */
|
|
@@ -866,10 +875,11 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
|
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
|
{
|
|
struct mt_device *td = hid_get_drvdata(hid);
|
|
+ __s32 cls = td->mtclass.name;
|
|
struct hid_field *field;
|
|
bool first_packet;
|
|
unsigned count;
|
|
- int r, n;
|
|
+ int r, n, scantime = 0;
|
|
|
|
/* sticky fingers release in progress, abort */
|
|
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
|
@@ -879,12 +889,29 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
|
* Includes multi-packet support where subsequent
|
|
* packets are sent with zero contactcount.
|
|
*/
|
|
+ if (td->scantime_index >= 0) {
|
|
+ field = report->field[td->scantime_index];
|
|
+ scantime = field->value[td->scantime_val_index];
|
|
+ }
|
|
if (td->cc_index >= 0) {
|
|
struct hid_field *field = report->field[td->cc_index];
|
|
int value = field->value[td->cc_value_index];
|
|
- if (value)
|
|
+
|
|
+ /*
|
|
+ * For Win8 PTPs the first packet (td->num_received == 0) may
|
|
+ * have a contactcount of 0 if there only is a button event.
|
|
+ * We double check that this is not a continuation packet
|
|
+ * of a possible multi-packet frame be checking that the
|
|
+ * timestamp has changed.
|
|
+ */
|
|
+ if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
|
+ td->num_received == 0 && td->prev_scantime != scantime)
|
|
+ td->num_expected = value;
|
|
+ /* A non 0 contact count always indicates a first packet */
|
|
+ else if (value)
|
|
td->num_expected = value;
|
|
}
|
|
+ td->prev_scantime = scantime;
|
|
|
|
first_packet = td->num_received == 0;
|
|
for (r = 0; r < report->maxfield; r++) {
|
|
@@ -1342,6 +1369,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|
td->maxcontact_report_id = -1;
|
|
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
|
td->cc_index = -1;
|
|
+ td->scantime_index = -1;
|
|
td->mt_report_id = -1;
|
|
hid_set_drvdata(hdev, td);
|
|
|
|
--
|
|
2.14.3
|
|
|