[PATCH 4.18 003/158] HID: multitouch: fix Elan panels with 2 input modes declaration

From: Greg Kroah-Hartman
Date: Mon Sep 17 2018 - 19:08:14 EST


4.18-stable review patch. If anyone has any objections, please let me know.

------------------

From: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx>

commit ec6adef5fbc3f140c70e7499fdad818acb3a46c6 upstream.

When implementing commit 7f81c8db5489 ("HID: multitouch: simplify
the settings of the various features"), I wrongly removed a test
that made sure we never try to set the second InputMode feature
to something else than 0.

This broke badly some recent Elan panels that now forget to send the
click button in some area of the touchpad.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=200899
Fixes: 7f81c8db5489 ("HID: multitouch: simplify the settings of the various features")
Cc: stable@xxxxxxxxxxxxxxx # v4.18+
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx>
Signed-off-by: Jiri Kosina <jkosina@xxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/hid/hid-multitouch.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1167,7 +1167,8 @@ static bool mt_need_to_apply_feature(str
struct hid_usage *usage,
enum latency_mode latency,
bool surface_switch,
- bool button_switch)
+ bool button_switch,
+ bool *inputmode_found)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
@@ -1179,6 +1180,14 @@ static bool mt_need_to_apply_feature(str

switch (usage->hid) {
case HID_DG_INPUTMODE:
+ /*
+ * Some elan panels wrongly declare 2 input mode features,
+ * and silently ignore when we set the value in the second
+ * field. Skip the second feature and hope for the best.
+ */
+ if (*inputmode_found)
+ return false;
+
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
report_len = hid_report_len(report);
buf = hid_alloc_report_buf(report, GFP_KERNEL);
@@ -1194,6 +1203,7 @@ static bool mt_need_to_apply_feature(str
}

field->value[index] = td->inputmode_value;
+ *inputmode_found = true;
return true;

case HID_DG_CONTACTMAX:
@@ -1231,6 +1241,7 @@ static void mt_set_modes(struct hid_devi
struct hid_usage *usage;
int i, j;
bool update_report;
+ bool inputmode_found = false;

rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
list_for_each_entry(rep, &rep_enum->report_list, list) {
@@ -1249,7 +1260,8 @@ static void mt_set_modes(struct hid_devi
usage,
latency,
surface_switch,
- button_switch))
+ button_switch,
+ &inputmode_found))
update_report = true;
}
}