diff options
author | Hans de Goede <hdegoede@redhat.com> | 2017-11-22 06:57:08 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-11-22 10:01:06 -0500 |
commit | af8dc4d0949092c4fba17ebb9e54448697c3d4e0 (patch) | |
tree | 84f033d92a75931415db4324418bc7d70dc694be | |
parent | fb55b4026d88a2bdc351f5485461d9314c885b60 (diff) |
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>
-rw-r--r-- | drivers/hid/hid-multitouch.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 9ef24b518f12..d8b1cad74faf 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -119,6 +119,9 @@ struct mt_device { | |||
119 | unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ | 119 | unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ |
120 | int cc_index; /* contact count field index in the report */ | 120 | int cc_index; /* contact count field index in the report */ |
121 | int cc_value_index; /* contact count value index in the field */ | 121 | int cc_value_index; /* contact count value index in the field */ |
122 | int scantime_index; /* scantime field index in the report */ | ||
123 | int scantime_val_index; /* scantime value index in the field */ | ||
124 | int prev_scantime; /* scantime reported in the previous packet */ | ||
122 | unsigned last_slot_field; /* the last field of a slot */ | 125 | unsigned last_slot_field; /* the last field of a slot */ |
123 | unsigned mt_report_id; /* the report ID of the multitouch device */ | 126 | unsigned mt_report_id; /* the report ID of the multitouch device */ |
124 | unsigned long initial_quirks; /* initial quirks state */ | 127 | 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, | |||
599 | EV_MSC, MSC_TIMESTAMP); | 602 | EV_MSC, MSC_TIMESTAMP); |
600 | input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP); | 603 | input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP); |
601 | mt_store_field(usage, td, hi); | 604 | mt_store_field(usage, td, hi); |
605 | /* Ignore if indexes are out of bounds. */ | ||
606 | if (field->index >= field->report->maxfield || | ||
607 | usage->usage_index >= field->report_count) | ||
608 | return 1; | ||
609 | td->scantime_index = field->index; | ||
610 | td->scantime_val_index = usage->usage_index; | ||
602 | return 1; | 611 | return 1; |
603 | case HID_DG_CONTACTCOUNT: | 612 | case HID_DG_CONTACTCOUNT: |
604 | /* Ignore if indexes are out of bounds. */ | 613 | /* Ignore if indexes are out of bounds. */ |
@@ -855,9 +864,10 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | |||
855 | static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | 864 | static void mt_touch_report(struct hid_device *hid, struct hid_report *report) |
856 | { | 865 | { |
857 | struct mt_device *td = hid_get_drvdata(hid); | 866 | struct mt_device *td = hid_get_drvdata(hid); |
867 | __s32 cls = td->mtclass.name; | ||
858 | struct hid_field *field; | 868 | struct hid_field *field; |
859 | unsigned count; | 869 | unsigned count; |
860 | int r, n; | 870 | int r, n, scantime = 0; |
861 | 871 | ||
862 | /* sticky fingers release in progress, abort */ | 872 | /* sticky fingers release in progress, abort */ |
863 | if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) | 873 | if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) |
@@ -867,12 +877,29 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | |||
867 | * Includes multi-packet support where subsequent | 877 | * Includes multi-packet support where subsequent |
868 | * packets are sent with zero contactcount. | 878 | * packets are sent with zero contactcount. |
869 | */ | 879 | */ |
880 | if (td->scantime_index >= 0) { | ||
881 | field = report->field[td->scantime_index]; | ||
882 | scantime = field->value[td->scantime_val_index]; | ||
883 | } | ||
870 | if (td->cc_index >= 0) { | 884 | if (td->cc_index >= 0) { |
871 | struct hid_field *field = report->field[td->cc_index]; | 885 | struct hid_field *field = report->field[td->cc_index]; |
872 | int value = field->value[td->cc_value_index]; | 886 | int value = field->value[td->cc_value_index]; |
873 | if (value) | 887 | |
888 | /* | ||
889 | * For Win8 PTPs the first packet (td->num_received == 0) may | ||
890 | * have a contactcount of 0 if there only is a button event. | ||
891 | * We double check that this is not a continuation packet | ||
892 | * of a possible multi-packet frame be checking that the | ||
893 | * timestamp has changed. | ||
894 | */ | ||
895 | if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) && | ||
896 | td->num_received == 0 && td->prev_scantime != scantime) | ||
897 | td->num_expected = value; | ||
898 | /* A non 0 contact count always indicates a first packet */ | ||
899 | else if (value) | ||
874 | td->num_expected = value; | 900 | td->num_expected = value; |
875 | } | 901 | } |
902 | td->prev_scantime = scantime; | ||
876 | 903 | ||
877 | for (r = 0; r < report->maxfield; r++) { | 904 | for (r = 0; r < report->maxfield; r++) { |
878 | field = report->field[r]; | 905 | field = report->field[r]; |
@@ -1329,6 +1356,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1329 | td->maxcontact_report_id = -1; | 1356 | td->maxcontact_report_id = -1; |
1330 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; | 1357 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; |
1331 | td->cc_index = -1; | 1358 | td->cc_index = -1; |
1359 | td->scantime_index = -1; | ||
1332 | td->mt_report_id = -1; | 1360 | td->mt_report_id = -1; |
1333 | hid_set_drvdata(hdev, td); | 1361 | hid_set_drvdata(hdev, td); |
1334 | 1362 | ||