Fix left-button not working with some hid-multitouch touchpads
This commit is contained in:
parent
5d8f3c9211
commit
f10b01dcd4
106
0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch
Normal file
106
0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
From f5c1da991de077420fda17a236342de5a0068f5d 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 v2 1/3] 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 9ef24b518f12..d8b1cad74faf 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. */
|
||||||
|
@@ -855,9 +864,10 @@ 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;
|
||||||
|
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))
|
||||||
|
@@ -867,12 +877,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;
|
||||||
|
|
||||||
|
for (r = 0; r < report->maxfield; r++) {
|
||||||
|
field = report->field[r];
|
||||||
|
@@ -1329,6 +1356,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
|
||||||
|
|
@ -0,0 +1,84 @@
|
|||||||
|
From c25d877f4ee97deb92170129eee4777a5d5997d9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Wed, 22 Nov 2017 12:57:09 +0100
|
||||||
|
Subject: [PATCH v2 2/3] HID: multitouch: Only look at non touch fields in
|
||||||
|
first packet of a frame
|
||||||
|
|
||||||
|
Devices in "single finger hybrid mode" will send one report per finger,
|
||||||
|
on some devices only the first report of such a multi-packet frame will
|
||||||
|
contain a value for BTN_LEFT, in subsequent reports (if multiple fingers
|
||||||
|
are down) the value is always 0, causing hid-mt to report BTN_LEFT going
|
||||||
|
1 - 0 - 1 - 0 when pressing a clickpad and putting down a second finger.
|
||||||
|
This happens for example on USB 0603:0002 mt touchpads.
|
||||||
|
|
||||||
|
This commit fixes this by only reporting non touch fields for the first
|
||||||
|
packet of a (possibly) multi-packet frame.
|
||||||
|
|
||||||
|
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 | 17 +++++++++++++++--
|
||||||
|
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index d8b1cad74faf..760c4a042e6a 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -787,9 +787,11 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
|
- struct hid_usage *usage, __s32 value)
|
||||||
|
+ struct hid_usage *usage, __s32 value,
|
||||||
|
+ bool first_packet)
|
||||||
|
{
|
||||||
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
|
+ __s32 cls = td->mtclass.name;
|
||||||
|
__s32 quirks = td->mtclass.quirks;
|
||||||
|
struct input_dev *input = field->hidinput->input;
|
||||||
|
|
||||||
|
@@ -846,6 +848,15 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
+ /*
|
||||||
|
+ * For Win8 PTP touchpads we should only look at
|
||||||
|
+ * non finger/touch events in the first_packet of
|
||||||
|
+ * a (possible) multi-packet frame.
|
||||||
|
+ */
|
||||||
|
+ if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||||
|
+ !first_packet)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
if (usage->type)
|
||||||
|
input_event(input, usage->type, usage->code,
|
||||||
|
value);
|
||||||
|
@@ -866,6 +877,7 @@ 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, scantime = 0;
|
||||||
|
|
||||||
|
@@ -901,6 +913,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
|
}
|
||||||
|
td->prev_scantime = scantime;
|
||||||
|
|
||||||
|
+ first_packet = td->num_received == 0;
|
||||||
|
for (r = 0; r < report->maxfield; r++) {
|
||||||
|
field = report->field[r];
|
||||||
|
count = field->report_count;
|
||||||
|
@@ -910,7 +923,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
|
|
||||||
|
for (n = 0; n < count; n++)
|
||||||
|
mt_process_mt_event(hid, field, &field->usage[n],
|
||||||
|
- field->value[n]);
|
||||||
|
+ field->value[n], first_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (td->num_received >= td->num_expected)
|
||||||
|
--
|
||||||
|
2.14.3
|
||||||
|
|
@ -0,0 +1,78 @@
|
|||||||
|
From 1719566899e5a69b4ba767beb07dab7ceb9ae5a8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Wed, 22 Nov 2017 12:57:10 +0100
|
||||||
|
Subject: [PATCH v2 3/3] HID: multitouch: Combine all left-button events in a
|
||||||
|
frame
|
||||||
|
|
||||||
|
According to the Win8 Precision Touchpad spec, inside the HID_UP_BUTTON
|
||||||
|
usage-page usage 1 is for a clickpad getting clicked, 2 for an external
|
||||||
|
left button and 3 for an external right button. Since Linux uses
|
||||||
|
BTN_LEFT for a clickpad being clicked we end up mapping both usage 1
|
||||||
|
and 2 to BTN_LEFT and if a single report contains both then we ended
|
||||||
|
up always reporting the value of both in a single SYN, e.g. :
|
||||||
|
BTN_LEFT 1, BTN_LEFT 0, SYN. This happens for example with Hantick
|
||||||
|
HTT5288 i2c mt touchpads.
|
||||||
|
|
||||||
|
This commit fixes this by not immediately reporting left button when we
|
||||||
|
parse the report, but instead storing or-ing together the values and
|
||||||
|
reporting the result from mt_sync_frame() when we've a complete frame.
|
||||||
|
|
||||||
|
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 | 20 ++++++++++++++++++++
|
||||||
|
1 file changed, 20 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index 760c4a042e6a..76088f2cf598 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -122,6 +122,7 @@ struct mt_device {
|
||||||
|
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 */
|
||||||
|
+ int left_button_state; /* left button state */
|
||||||
|
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 */
|
||||||
|
@@ -743,10 +744,16 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
||||||
|
*/
|
||||||
|
static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
|
||||||
|
{
|
||||||
|
+ __s32 cls = td->mtclass.name;
|
||||||
|
+
|
||||||
|
+ if (cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL)
|
||||||
|
+ input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
|
||||||
|
+
|
||||||
|
input_mt_sync_frame(input);
|
||||||
|
input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
|
||||||
|
input_sync(input);
|
||||||
|
td->num_received = 0;
|
||||||
|
+ td->left_button_state = 0;
|
||||||
|
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
|
||||||
|
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
||||||
|
else
|
||||||
|
@@ -857,6 +864,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
|
!first_packet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * For Win8 PTP touchpads we map both the clickpad click
|
||||||
|
+ * and any "external" left buttons to BTN_LEFT if a
|
||||||
|
+ * device claims to have both we need to report 1 for
|
||||||
|
+ * BTN_LEFT if either is pressed, so we or all values
|
||||||
|
+ * together and report the result in mt_sync_frame().
|
||||||
|
+ */
|
||||||
|
+ if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||||
|
+ usage->type == EV_KEY && usage->code == BTN_LEFT) {
|
||||||
|
+ td->left_button_state |= value;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (usage->type)
|
||||||
|
input_event(input, usage->type, usage->code,
|
||||||
|
value);
|
||||||
|
--
|
||||||
|
2.14.3
|
||||||
|
|
10
kernel.spec
10
kernel.spec
@ -641,6 +641,13 @@ Patch628: 0001-Bluetooth-btusb-Add-a-Kconfig-option-to-enable-USB-a.patch
|
|||||||
# rhbz 1516584
|
# rhbz 1516584
|
||||||
Patch629: drm-ttm-don-t-attempt-to-use-hugepages-if-dma32-requested.mbox
|
Patch629: drm-ttm-don-t-attempt-to-use-hugepages-if-dma32-requested.mbox
|
||||||
|
|
||||||
|
# Fix left-button not working with some hid-multitouch touchpads
|
||||||
|
# Adding these suggested by Benjamin Tissoires
|
||||||
|
# Queued in hid.git/for-4.16/hid-quirks-cleanup/multitouch for merging into 4.16
|
||||||
|
Patch630: 0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch
|
||||||
|
Patch631: 0002-HID-multitouch-Only-look-at-non-touch-fields-in-firs.patch
|
||||||
|
Patch632: 0003-HID-multitouch-Combine-all-left-button-events-in-a-f.patch
|
||||||
|
|
||||||
# END OF PATCH DEFINITIONS
|
# END OF PATCH DEFINITIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -2190,6 +2197,9 @@ fi
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Nov 26 2017 Hans de Goede <jwrdegoede@fedoraproject.org>
|
||||||
|
- Fix left-button not working with some hid-multitouch touchpads
|
||||||
|
|
||||||
* Thu Nov 23 2017 Laura Abbott <labbott@redhat.com> - 4.15.0-0.rc0.git7.2
|
* Thu Nov 23 2017 Laura Abbott <labbott@redhat.com> - 4.15.0-0.rc0.git7.2
|
||||||
- Fix for TTM regression (rhbz 1516584)
|
- Fix for TTM regression (rhbz 1516584)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user