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>
This commit is contained in:

committed by
Jiri Kosina

parent
8e9faa1546
commit
f3287a995a
@@ -1933,6 +1933,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
|
||||||
#endif
|
#endif
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
|
||||||
|
@@ -633,6 +633,7 @@
|
|||||||
|
|
||||||
#define USB_VENDOR_ID_LG 0x1fd2
|
#define USB_VENDOR_ID_LG 0x1fd2
|
||||||
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
||||||
|
#define USB_DEVICE_ID_LG_MELFAS_MT 0x6007
|
||||||
|
|
||||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||||
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
||||||
|
@@ -68,6 +68,7 @@ MODULE_LICENSE("GPL");
|
|||||||
#define MT_QUIRK_HOVERING (1 << 11)
|
#define MT_QUIRK_HOVERING (1 << 11)
|
||||||
#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
|
#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
|
||||||
#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13)
|
#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13)
|
||||||
|
#define MT_QUIRK_FIX_CONST_CONTACT_ID (1 << 14)
|
||||||
|
|
||||||
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||||
#define MT_INPUTMODE_TOUCHPAD 0x03
|
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||||
@@ -157,6 +158,7 @@ static void mt_post_parse(struct mt_device *td);
|
|||||||
#define MT_CLS_FLATFROG 0x0107
|
#define MT_CLS_FLATFROG 0x0107
|
||||||
#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
|
#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
|
||||||
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
|
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
|
||||||
|
#define MT_CLS_LG 0x010a
|
||||||
#define MT_CLS_VTL 0x0110
|
#define MT_CLS_VTL 0x0110
|
||||||
|
|
||||||
#define MT_DEFAULT_MAXCONTACT 10
|
#define MT_DEFAULT_MAXCONTACT 10
|
||||||
@@ -263,6 +265,12 @@ static struct mt_class mt_classes[] = {
|
|||||||
.sn_move = 2048,
|
.sn_move = 2048,
|
||||||
.maxcontacts = 40,
|
.maxcontacts = 40,
|
||||||
},
|
},
|
||||||
|
{ .name = MT_CLS_LG,
|
||||||
|
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||||
|
MT_QUIRK_FIX_CONST_CONTACT_ID |
|
||||||
|
MT_QUIRK_IGNORE_DUPLICATES |
|
||||||
|
MT_QUIRK_HOVERING |
|
||||||
|
MT_QUIRK_CONTACT_CNT_ACCURATE },
|
||||||
{ .name = MT_CLS_VTL,
|
{ .name = MT_CLS_VTL,
|
||||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||||
@@ -1078,6 +1086,34 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mt_fix_const_field(struct hid_field *field, unsigned int usage)
|
||||||
|
{
|
||||||
|
if (field->usage[0].hid != usage ||
|
||||||
|
!(field->flags & HID_MAIN_ITEM_CONSTANT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
field->flags &= ~HID_MAIN_ITEM_CONSTANT;
|
||||||
|
field->flags |= HID_MAIN_ITEM_VARIABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
|
||||||
|
{
|
||||||
|
struct hid_report *report;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
list_for_each_entry(report,
|
||||||
|
&hdev->report_enum[HID_INPUT_REPORT].report_list,
|
||||||
|
list) {
|
||||||
|
|
||||||
|
if (!report->maxfield)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < report->maxfield; i++)
|
||||||
|
if (report->field[i]->maxusage >= 1)
|
||||||
|
mt_fix_const_field(report->field[i], usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
@@ -1151,6 +1187,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
|
||||||
|
mt_fix_const_fields(hdev, HID_DG_CONTACTID);
|
||||||
|
|
||||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1398,6 +1437,11 @@ static const struct hid_device_id mt_devices[] = {
|
|||||||
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
|
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
|
||||||
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
||||||
|
|
||||||
|
/* LG Melfas panel */
|
||||||
|
{ .driver_data = MT_CLS_LG,
|
||||||
|
HID_USB_DEVICE(USB_VENDOR_ID_LG,
|
||||||
|
USB_DEVICE_ID_LG_MELFAS_MT) },
|
||||||
|
|
||||||
/* MosArt panels */
|
/* MosArt panels */
|
||||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
||||||
|
Reference in New Issue
Block a user