]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/hid/hid-multitouch.c
HID: multitouch: add support for Nexio 42" panel
[mirror_ubuntu-bionic-kernel.git] / drivers / hid / hid-multitouch.c
index 13b94619b5d001f58804b6c4596fec74e8448ff5..87690e2726ac3318963e65b3bf65066ef4c25543 100644 (file)
@@ -54,6 +54,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_NO_AREA               (1 << 9)
 #define MT_QUIRK_IGNORE_DUPLICATES     (1 << 10)
 #define MT_QUIRK_HOVERING              (1 << 11)
+#define MT_QUIRK_CONTACT_CNT_ACCURATE  (1 << 12)
 
 struct mt_slot {
        __s32 x, y, cx, cy, p, w, h;
@@ -83,6 +84,7 @@ struct mt_device {
        struct mt_class mtclass;        /* our mt device class */
        struct mt_fields *fields;       /* temporary placeholder for storing the
                                           multitouch fields */
+       __s32 *contactcount;            /* contact count value in the report */
        unsigned last_field_index;      /* last field index of the report */
        unsigned last_slot_field;       /* the last field of a slot */
        unsigned mt_report_id;  /* the report ID of the multitouch device */
@@ -112,6 +114,7 @@ struct mt_device {
 #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER      0x0007
 #define MT_CLS_DUAL_NSMU_CONTACTID             0x0008
 #define MT_CLS_INRANGE_CONTACTNUMBER           0x0009
+#define MT_CLS_ALWAYS_TRUE                     0x000a
 
 /* vendor specific classes */
 #define MT_CLS_3M                              0x0101
@@ -171,6 +174,9 @@ static struct mt_class mt_classes[] = {
        { .name = MT_CLS_INRANGE_CONTACTNUMBER,
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTNUMBER },
+       { .name = MT_CLS_ALWAYS_TRUE,
+               .quirks = MT_QUIRK_ALWAYS_VALID |
+                       MT_QUIRK_CONTACT_CNT_ACCURATE },
 
        /*
         * vendor specific classes
@@ -251,6 +257,9 @@ static ssize_t mt_set_quirks(struct device *dev,
 
        td->mtclass.quirks = val;
 
+       if (!td->contactcount)
+               td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+
        return count;
 }
 
@@ -461,6 +470,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTCOUNT:
+                       td->contactcount = field->value + usage->usage_index;
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTMAX:
@@ -525,6 +535,10 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
  */
 static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
+       if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
+           td->num_received >= td->num_expected)
+               return;
+
        if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
                int slotnum = mt_compute_slot(td, input);
                struct mt_slot *s = &td->curdata;
@@ -635,12 +649,6 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
                        td->curdata.h = value;
                        break;
                case HID_DG_CONTACTCOUNT:
-                       /*
-                        * Includes multi-packet support where subsequent
-                        * packets are sent with zero contactcount.
-                        */
-                       if (value)
-                               td->num_expected = value;
                        break;
                case HID_DG_TOUCH:
                        /* do nothing */
@@ -676,6 +684,13 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
        if (!(hid->claimed & HID_CLAIMED_INPUT))
                return;
 
+       /*
+        * Includes multi-packet support where subsequent
+        * packets are sent with zero contactcount.
+        */
+       if (td->contactcount && *td->contactcount)
+               td->num_expected = *td->contactcount;
+
        for (r = 0; r < report->maxfield; r++) {
                field = report->field[r];
                count = field->report_count;
@@ -750,11 +765,15 @@ static void mt_post_parse_default_settings(struct mt_device *td)
 static void mt_post_parse(struct mt_device *td)
 {
        struct mt_fields *f = td->fields;
+       struct mt_class *cls = &td->mtclass;
 
        if (td->touches_by_report > 0) {
                int field_count_per_touch = f->length / td->touches_by_report;
                td->last_slot_field = f->usages[field_count_per_touch - 1];
        }
+
+       if (!td->contactcount)
+               cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
 }
 
 static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
@@ -1087,6 +1106,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
                        USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
 
+       /* Nexio panels */
+       { .driver_data = MT_CLS_ALWAYS_TRUE,
+               MT_USB_DEVICE(USB_VENDOR_ID_NEXIO,
+                       USB_DEVICE_ID_NEXIO_MULTITOUCH_420)},
+
        /* Panasonic panels */
        { .driver_data = MT_CLS_PANASONIC,
                MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,