aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2017-01-30 04:48:06 -0500
committerJiri Kosina <jkosina@suse.cz>2017-02-03 08:45:57 -0500
commitf3287a995ac3520b1afcf03932b9c405f502657c (patch)
treeb54c9641b4d2a6be1d7b8ad6bec8c9db2a245855
parent8e9faa15469ed7c7467423db4c62aeed3ff4cae3 (diff)
HID: multitouch: fix LG Melfas touchscreen
The LG Melfas touchscreen has a bad firmware where it declares the Contact ID field as constant while it shouldn't. This messes up the autodetection and the reporting of the events by hid-multitouch given that hid-input ignores constant fields. The autodetection is simply worked around by manually adding the device to hid_have_special_driver[]. The processing of the events requires either a report fixup, or some specific case handling. Given that the report fixup would require to basically rewrite all the report descriptor, I went for the programatic way of fixing that after the report descriptors are loaded. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1416181 Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-multitouch.c44
3 files changed, 46 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index ea36b557d5ee..1f6d0c000381 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1933,6 +1933,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1933 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 1933 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
1934 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, 1934 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
1935#endif 1935#endif
1936 { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
1936 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, 1937 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
1937 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, 1938 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
1938 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, 1939 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 350accfee8e8..8943a58c626d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -633,6 +633,7 @@
633 633
634#define USB_VENDOR_ID_LG 0x1fd2 634#define USB_VENDOR_ID_LG 0x1fd2
635#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 635#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
636#define USB_DEVICE_ID_LG_MELFAS_MT 0x6007
636 637
637#define USB_VENDOR_ID_LOGITECH 0x046d 638#define USB_VENDOR_ID_LOGITECH 0x046d
638#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e 639#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 6dca66806844..692647485a53 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -68,6 +68,7 @@ MODULE_LICENSE("GPL");
68#define MT_QUIRK_HOVERING (1 << 11) 68#define MT_QUIRK_HOVERING (1 << 11)
69#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) 69#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
70#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13) 70#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13)
71#define MT_QUIRK_FIX_CONST_CONTACT_ID (1 << 14)
71 72
72#define MT_INPUTMODE_TOUCHSCREEN 0x02 73#define MT_INPUTMODE_TOUCHSCREEN 0x02
73#define MT_INPUTMODE_TOUCHPAD 0x03 74#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -157,6 +158,7 @@ static void mt_post_parse(struct mt_device *td);
157#define MT_CLS_FLATFROG 0x0107 158#define MT_CLS_FLATFROG 0x0107
158#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108 159#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
159#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109 160#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
161#define MT_CLS_LG 0x010a
160#define MT_CLS_VTL 0x0110 162#define MT_CLS_VTL 0x0110
161 163
162#define MT_DEFAULT_MAXCONTACT 10 164#define MT_DEFAULT_MAXCONTACT 10
@@ -263,6 +265,12 @@ static struct mt_class mt_classes[] = {
263 .sn_move = 2048, 265 .sn_move = 2048,
264 .maxcontacts = 40, 266 .maxcontacts = 40,
265 }, 267 },
268 { .name = MT_CLS_LG,
269 .quirks = MT_QUIRK_ALWAYS_VALID |
270 MT_QUIRK_FIX_CONST_CONTACT_ID |
271 MT_QUIRK_IGNORE_DUPLICATES |
272 MT_QUIRK_HOVERING |
273 MT_QUIRK_CONTACT_CNT_ACCURATE },
266 { .name = MT_CLS_VTL, 274 { .name = MT_CLS_VTL,
267 .quirks = MT_QUIRK_ALWAYS_VALID | 275 .quirks = MT_QUIRK_ALWAYS_VALID |
268 MT_QUIRK_CONTACT_CNT_ACCURATE | 276 MT_QUIRK_CONTACT_CNT_ACCURATE |
@@ -1078,6 +1086,34 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
1078 return 0; 1086 return 0;
1079} 1087}
1080 1088
1089static void mt_fix_const_field(struct hid_field *field, unsigned int usage)
1090{
1091 if (field->usage[0].hid != usage ||
1092 !(field->flags & HID_MAIN_ITEM_CONSTANT))
1093 return;
1094
1095 field->flags &= ~HID_MAIN_ITEM_CONSTANT;
1096 field->flags |= HID_MAIN_ITEM_VARIABLE;
1097}
1098
1099static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
1100{
1101 struct hid_report *report;
1102 int i;
1103
1104 list_for_each_entry(report,
1105 &hdev->report_enum[HID_INPUT_REPORT].report_list,
1106 list) {
1107
1108 if (!report->maxfield)
1109 continue;
1110
1111 for (i = 0; i < report->maxfield; i++)
1112 if (report->field[i]->maxusage >= 1)
1113 mt_fix_const_field(report->field[i], usage);
1114 }
1115}
1116
1081static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 1117static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
1082{ 1118{
1083 int ret, i; 1119 int ret, i;
@@ -1151,6 +1187,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
1151 if (ret != 0) 1187 if (ret != 0)
1152 return ret; 1188 return ret;
1153 1189
1190 if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
1191 mt_fix_const_fields(hdev, HID_DG_CONTACTID);
1192
1154 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 1193 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1155 if (ret) 1194 if (ret)
1156 return ret; 1195 return ret;
@@ -1398,6 +1437,11 @@ static const struct hid_device_id mt_devices[] = {
1398 MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, 1437 MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
1399 USB_DEVICE_ID_ILITEK_MULTITOUCH) }, 1438 USB_DEVICE_ID_ILITEK_MULTITOUCH) },
1400 1439
1440 /* LG Melfas panel */
1441 { .driver_data = MT_CLS_LG,
1442 HID_USB_DEVICE(USB_VENDOR_ID_LG,
1443 USB_DEVICE_ID_LG_MELFAS_MT) },
1444
1401 /* MosArt panels */ 1445 /* MosArt panels */
1402 { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, 1446 { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
1403 MT_USB_DEVICE(USB_VENDOR_ID_ASUS, 1447 MT_USB_DEVICE(USB_VENDOR_ID_ASUS,