Merge branch 'for-4.18/multitouch' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Fri, 8 Jun 2018 08:25:50 +0000 (10:25 +0200)
committerJiri Kosina <jkosina@suse.cz>
Fri, 8 Jun 2018 08:25:50 +0000 (10:25 +0200)
- improvement of duplicate usage handling in hid-input from Benjamin Tissoires
- Win 8.1 precisioun touchpad spec implementation from Benjamin Tissoires

drivers/hid/hid-core.c
drivers/hid/hid-generic.c
drivers/hid/hid-gfrm.c
drivers/hid/hid-input.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-multitouch.c
include/linux/hid.h

index 720be70ae74a377eb72781f25b3ad7d8a4a17e33..355dc7e4956261e3421f27ca4521d7aac1515ad5 100644 (file)
@@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle
  * Register a new report for a device.
  */
 
-struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
+struct hid_report *hid_register_report(struct hid_device *device,
+                                      unsigned int type, unsigned int id,
+                                      unsigned int application)
 {
        struct hid_report_enum *report_enum = device->report_enum + type;
        struct hid_report *report;
@@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type,
        report->type = type;
        report->size = 0;
        report->device = device;
+       report->application = application;
        report_enum->report_id_hash[id] = report;
 
        list_add_tail(&report->list, &report_enum->report_list);
@@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 {
        struct hid_report *report;
        struct hid_field *field;
-       unsigned usages;
-       unsigned offset;
-       unsigned i;
+       unsigned int usages;
+       unsigned int offset;
+       unsigned int i;
+       unsigned int application;
+
+       application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
-       report = hid_register_report(parser->device, report_type, parser->global.report_id);
+       report = hid_register_report(parser->device, report_type,
+                                    parser->global.report_id, application);
        if (!report) {
                hid_err(parser->device, "hid_register_report failed\n");
                return -1;
@@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 
        field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
        field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-       field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
+       field->application = application;
 
        for (i = 0; i < usages; i++) {
                unsigned j = i;
index c25b4718de440e403a09c96ea0e161e7ff796a95..3b6eccbc251980a35b0161ab723ea0456d6db2c5 100644 (file)
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
        return true;
 }
 
+static int hid_generic_probe(struct hid_device *hdev,
+                            const struct hid_device_id *id)
+{
+       int ret;
+
+       hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
+       ret = hid_parse(hdev);
+       if (ret)
+               return ret;
+
+       return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id hid_table[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
        { }
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
        .name = "hid-generic",
        .id_table = hid_table,
        .match = hid_generic_match,
+       .probe = hid_generic_probe,
 };
 module_hid_driver(hid_generic);
 
index 075b1c020846594dbe26a908ee04379a7444224e..cf477f8c8f4cdba1c815a7940cb53669e3c04bdf 100644 (file)
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
                 * those reports reach gfrm_raw_event() from hid_input_report().
                 */
                if (!hid_register_report(hdev, HID_INPUT_REPORT,
-                                        GFRM100_SEARCH_KEY_REPORT_ID)) {
+                                        GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
                        ret = -ENOMEM;
                        goto done;
                }
index 930652c25120ee14e57859af3bbce8d5072dab26..ab93dd5927c3af344aeec911fe39bd3621bd787a 100644 (file)
@@ -1110,8 +1110,31 @@ mapped:
 
        set_bit(usage->type, input->evbit);
 
-       while (usage->code <= max && test_and_set_bit(usage->code, bit))
-               usage->code = find_next_zero_bit(bit, max + 1, usage->code);
+       /*
+        * This part is *really* controversial:
+        * - HID aims at being generic so we should do our best to export
+        *   all incoming events
+        * - HID describes what events are, so there is no reason for ABS_X
+        *   to be mapped to ABS_Y
+        * - HID is using *_MISC+N as a default value, but nothing prevents
+        *   *_MISC+N to overwrite a legitimate even, which confuses userspace
+        *   (for instance ABS_MISC + 7 is ABS_MT_SLOT, which has a different
+        *   processing)
+        *
+        * If devices still want to use this (at their own risk), they will
+        * have to use the quirk HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE, but
+        * the default should be a reliable mapping.
+        */
+       while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
+               if (device->quirks & HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE) {
+                       usage->code = find_next_zero_bit(bit,
+                                                        max + 1,
+                                                        usage->code);
+               } else {
+                       device->status |= HID_STAT_DUP_DETECTED;
+                       goto ignore;
+               }
+       }
 
        if (usage->code > max)
                goto ignore;
@@ -1487,15 +1510,56 @@ static void report_features(struct hid_device *hid)
                }
 }
 
-static struct hid_input *hidinput_allocate(struct hid_device *hid)
+static struct hid_input *hidinput_allocate(struct hid_device *hid,
+                                          unsigned int application)
 {
        struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
        struct input_dev *input_dev = input_allocate_device();
-       if (!hidinput || !input_dev) {
-               kfree(hidinput);
-               input_free_device(input_dev);
-               hid_err(hid, "Out of memory during hid input probe\n");
-               return NULL;
+       const char *suffix = NULL;
+
+       if (!hidinput || !input_dev)
+               goto fail;
+
+       if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) &&
+           hid->maxapplication > 1) {
+               switch (application) {
+               case HID_GD_KEYBOARD:
+                       suffix = "Keyboard";
+                       break;
+               case HID_GD_KEYPAD:
+                       suffix = "Keypad";
+                       break;
+               case HID_GD_MOUSE:
+                       suffix = "Mouse";
+                       break;
+               case HID_DG_STYLUS:
+                       suffix = "Pen";
+                       break;
+               case HID_DG_TOUCHSCREEN:
+                       suffix = "Touchscreen";
+                       break;
+               case HID_DG_TOUCHPAD:
+                       suffix = "Touchpad";
+                       break;
+               case HID_GD_SYSTEM_CONTROL:
+                       suffix = "System Control";
+                       break;
+               case HID_CP_CONSUMER_CONTROL:
+                       suffix = "Consumer Control";
+                       break;
+               case HID_GD_WIRELESS_RADIO_CTLS:
+                       suffix = "Wireless Radio Control";
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (suffix) {
+               hidinput->name = kasprintf(GFP_KERNEL, "%s %s",
+                                          hid->name, suffix);
+               if (!hidinput->name)
+                       goto fail;
        }
 
        input_set_drvdata(input_dev, hid);
@@ -1505,7 +1569,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
        input_dev->setkeycode = hidinput_setkeycode;
        input_dev->getkeycode = hidinput_getkeycode;
 
-       input_dev->name = hid->name;
+       input_dev->name = hidinput->name ? hidinput->name : hid->name;
        input_dev->phys = hid->phys;
        input_dev->uniq = hid->uniq;
        input_dev->id.bustype = hid->bus;
@@ -1513,10 +1577,19 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
        input_dev->id.product = hid->product;
        input_dev->id.version = hid->version;
        input_dev->dev.parent = &hid->dev;
+
        hidinput->input = input_dev;
        list_add_tail(&hidinput->list, &hid->inputs);
 
+       INIT_LIST_HEAD(&hidinput->reports);
+
        return hidinput;
+
+fail:
+       kfree(hidinput);
+       input_free_device(input_dev);
+       hid_err(hid, "Out of memory during hid input probe\n");
+       return NULL;
 }
 
 static bool hidinput_has_been_populated(struct hid_input *hidinput)
@@ -1562,6 +1635,7 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid,
 
        list_del(&hidinput->list);
        input_free_device(hidinput->input);
+       kfree(hidinput->name);
 
        for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
                if (k == HID_OUTPUT_REPORT &&
@@ -1594,6 +1668,20 @@ static struct hid_input *hidinput_match(struct hid_report *report)
        return NULL;
 }
 
+static struct hid_input *hidinput_match_application(struct hid_report *report)
+{
+       struct hid_device *hid = report->device;
+       struct hid_input *hidinput;
+
+       list_for_each_entry(hidinput, &hid->inputs, list) {
+               if (hidinput->report &&
+                   hidinput->report->application == report->application)
+                       return hidinput;
+       }
+
+       return NULL;
+}
+
 static inline void hidinput_configure_usages(struct hid_input *hidinput,
                                             struct hid_report *report)
 {
@@ -1616,11 +1704,14 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
        struct hid_driver *drv = hid->driver;
        struct hid_report *report;
        struct hid_input *next, *hidinput = NULL;
+       unsigned int application;
        int i, k;
 
        INIT_LIST_HEAD(&hid->inputs);
        INIT_WORK(&hid->led_work, hidinput_led_worker);
 
+       hid->status &= ~HID_STAT_DUP_DETECTED;
+
        if (!force) {
                for (i = 0; i < hid->maxcollection; i++) {
                        struct hid_collection *col = &hid->collection[i];
@@ -1646,15 +1737,20 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                        if (!report->maxfield)
                                continue;
 
+                       application = report->application;
+
                        /*
                         * Find the previous hidinput report attached
                         * to this report id.
                         */
                        if (hid->quirks & HID_QUIRK_MULTI_INPUT)
                                hidinput = hidinput_match(report);
+                       else if (hid->maxapplication > 1 &&
+                                (hid->quirks & HID_QUIRK_INPUT_PER_APP))
+                               hidinput = hidinput_match_application(report);
 
                        if (!hidinput) {
-                               hidinput = hidinput_allocate(hid);
+                               hidinput = hidinput_allocate(hid, application);
                                if (!hidinput)
                                        goto out_unwind;
                        }
@@ -1663,6 +1759,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 
                        if (hid->quirks & HID_QUIRK_MULTI_INPUT)
                                hidinput->report = report;
+
+                       list_add_tail(&report->hidinput_list,
+                                     &hidinput->reports);
                }
        }
 
@@ -1687,6 +1786,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                goto out_unwind;
        }
 
+       if (hid->status & HID_STAT_DUP_DETECTED)
+               hid_dbg(hid,
+                       "Some usages could not be mapped, please use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE if this is legitimate.\n");
+
        return 0;
 
 out_unwind:
index 42ed887ba0be5d79d67738bcc1520eb8fb8a0190..b454c43861578602e33d066a655eb5205e969533 100644 (file)
@@ -531,12 +531,12 @@ static int magicmouse_probe(struct hid_device *hdev,
 
        if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
                report = hid_register_report(hdev, HID_INPUT_REPORT,
-                       MOUSE_REPORT_ID);
+                       MOUSE_REPORT_ID, 0);
        else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
                report = hid_register_report(hdev, HID_INPUT_REPORT,
-                       TRACKPAD_REPORT_ID);
+                       TRACKPAD_REPORT_ID, 0);
                report = hid_register_report(hdev, HID_INPUT_REPORT,
-                       DOUBLE_REPORT_ID);
+                       DOUBLE_REPORT_ID, 0);
        }
 
        if (!report) {
index dad2fbb0e3f880682ed96dc70b8da5d3b3c07e36..45968f7970f87775fa28cabcacb8577ef4c2aac3 100644 (file)
@@ -81,6 +81,11 @@ MODULE_LICENSE("GPL");
 
 #define MT_BUTTONTYPE_CLICKPAD         0
 
+enum latency_mode {
+       HID_LATENCY_NORMAL = 0,
+       HID_LATENCY_HIGH = 1,
+};
+
 #define MT_IO_FLAGS_RUNNING            0
 #define MT_IO_FLAGS_ACTIVE_SLOTS       1
 #define MT_IO_FLAGS_PENDING_SLOTS      2
@@ -127,11 +132,7 @@ struct mt_device {
        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 */
-       __s16 inputmode;        /* InputMode HID feature, -1 if non-existent */
-       __s16 inputmode_index;  /* InputMode HID feature index in the report */
-       __s16 maxcontact_report_id;     /* Maximum Contact Number HID feature,
-                                  -1 if non-existent */
-       __u8 inputmode_value;  /* InputMode HID feature value */
+       __u8 inputmode_value;   /* InputMode HID feature value */
        __u8 num_received;      /* how many contacts we received */
        __u8 num_expected;      /* expected last contact index */
        __u8 maxcontacts;
@@ -415,32 +416,9 @@ static void mt_feature_mapping(struct hid_device *hdev,
        struct mt_device *td = hid_get_drvdata(hdev);
 
        switch (usage->hid) {
-       case HID_DG_INPUTMODE:
-               /* Ignore if value index is out of bounds. */
-               if (usage->usage_index >= field->report_count) {
-                       dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
-                       break;
-               }
-
-               if (td->inputmode < 0) {
-                       td->inputmode = field->report->id;
-                       td->inputmode_index = usage->usage_index;
-               } else {
-                       /*
-                        * 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.
-                        */
-                       dev_info(&hdev->dev,
-                                "Ignoring the extra HID_DG_INPUTMODE\n");
-               }
-
-               break;
        case HID_DG_CONTACTMAX:
                mt_get_feature(hdev, field->report);
 
-               td->maxcontact_report_id = field->report->id;
                td->maxcontacts = field->value[0];
                if (!td->maxcontacts &&
                    field->logical_maximum <= MT_MAX_MAXCONTACT)
@@ -620,13 +598,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        hid_map_usage(hi, usage, bit, max,
                                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;
+                       /*
+                        * We don't set td->last_slot_field as scan time is
+                        * global to the report.
+                        */
                        return 1;
                case HID_DG_CONTACTCOUNT:
                        /* Ignore if indexes are out of bounds. */
@@ -1181,61 +1162,100 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
                input_sync(field->hidinput->input);
 }
 
-static void mt_set_input_mode(struct hid_device *hdev)
+static bool mt_need_to_apply_feature(struct hid_device *hdev,
+                                    struct hid_field *field,
+                                    struct hid_usage *usage,
+                                    enum latency_mode latency,
+                                    bool surface_switch,
+                                    bool button_switch)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
-       struct hid_report *r;
-       struct hid_report_enum *re;
        struct mt_class *cls = &td->mtclass;
+       struct hid_report *report = field->report;
+       unsigned int index = usage->usage_index;
        char *buf;
        u32 report_len;
+       int max;
 
-       if (td->inputmode < 0)
-               return;
-
-       re = &(hdev->report_enum[HID_FEATURE_REPORT]);
-       r = re->report_id_hash[td->inputmode];
-       if (r) {
+       switch (usage->hid) {
+       case HID_DG_INPUTMODE:
                if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
-                       report_len = hid_report_len(r);
-                       buf = hid_alloc_report_buf(r, GFP_KERNEL);
+                       report_len = hid_report_len(report);
+                       buf = hid_alloc_report_buf(report, GFP_KERNEL);
                        if (!buf) {
-                               hid_err(hdev, "failed to allocate buffer for report\n");
-                               return;
+                               hid_err(hdev,
+                                       "failed to allocate buffer for report\n");
+                               return false;
                        }
-                       hid_hw_raw_request(hdev, r->id, buf, report_len,
+                       hid_hw_raw_request(hdev, report->id, buf, report_len,
                                           HID_FEATURE_REPORT,
                                           HID_REQ_GET_REPORT);
                        kfree(buf);
                }
-               r->field[0]->value[td->inputmode_index] = td->inputmode_value;
-               hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
-       }
-}
 
-static void mt_set_maxcontacts(struct hid_device *hdev)
-{
-       struct mt_device *td = hid_get_drvdata(hdev);
-       struct hid_report *r;
-       struct hid_report_enum *re;
-       int fieldmax, max;
+               field->value[index] = td->inputmode_value;
+               return true;
 
-       if (td->maxcontact_report_id < 0)
-               return;
+       case HID_DG_CONTACTMAX:
+               if (td->mtclass.maxcontacts) {
+                       max = min_t(int, field->logical_maximum,
+                                   td->mtclass.maxcontacts);
+                       if (field->value[index] != max) {
+                               field->value[index] = max;
+                               return true;
+                       }
+               }
+               break;
 
-       if (!td->mtclass.maxcontacts)
-               return;
+       case HID_DG_LATENCYMODE:
+               field->value[index] = latency;
+               return true;
+
+       case HID_DG_SURFACESWITCH:
+               field->value[index] = surface_switch;
+               return true;
+
+       case HID_DG_BUTTONSWITCH:
+               field->value[index] = button_switch;
+               return true;
+       }
 
-       re = &hdev->report_enum[HID_FEATURE_REPORT];
-       r = re->report_id_hash[td->maxcontact_report_id];
-       if (r) {
-               max = td->mtclass.maxcontacts;
-               fieldmax = r->field[0]->logical_maximum;
-               max = min(fieldmax, max);
-               if (r->field[0]->value[0] != max) {
-                       r->field[0]->value[0] = max;
-                       hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
+       return false; /* no need to update the report */
+}
+
+static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
+                        bool surface_switch, bool button_switch)
+{
+       struct hid_report_enum *rep_enum;
+       struct hid_report *rep;
+       struct hid_usage *usage;
+       int i, j;
+       bool update_report;
+
+       rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+       list_for_each_entry(rep, &rep_enum->report_list, list) {
+               update_report = false;
+
+               for (i = 0; i < rep->maxfield; i++) {
+                       /* Ignore if report count is out of bounds. */
+                       if (rep->field[i]->report_count < 1)
+                               continue;
+
+                       for (j = 0; j < rep->field[i]->maxusage; j++) {
+                               usage = &rep->field[i]->usage[j];
+
+                               if (mt_need_to_apply_feature(hdev,
+                                                            rep->field[i],
+                                                            usage,
+                                                            latency,
+                                                            surface_switch,
+                                                            button_switch))
+                                       update_report = true;
+                       }
                }
+
+               if (update_report)
+                       hid_hw_request(hdev, rep, HID_REQ_SET_REPORT);
        }
 }
 
@@ -1274,54 +1294,48 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
        struct mt_device *td = hid_get_drvdata(hdev);
        char *name;
        const char *suffix = NULL;
-       struct hid_field *field = hi->report->field[0];
+       unsigned int application = 0;
+       struct hid_report *report;
        int ret;
 
-       if (hi->report->id == td->mt_report_id) {
-               ret = mt_touch_input_configured(hdev, hi);
-               if (ret)
-                       return ret;
+       list_for_each_entry(report, &hi->reports, hidinput_list) {
+               application = report->application;
+               if (report->id == td->mt_report_id) {
+                       ret = mt_touch_input_configured(hdev, hi);
+                       if (ret)
+                               return ret;
+               }
+
+               /*
+                * some egalax touchscreens have "application == DG_TOUCHSCREEN"
+                * for the stylus. Check this first, and then rely on
+                * the application field.
+                */
+               if (report->field[0]->physical == HID_DG_STYLUS) {
+                       suffix = "Pen";
+                       /* force BTN_STYLUS to allow tablet matching in udev */
+                       __set_bit(BTN_STYLUS, hi->input->keybit);
+               }
        }
 
-       /*
-        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
-        * for the stylus. Check this first, and then rely on the application
-        * field.
-        */
-       if (hi->report->field[0]->physical == HID_DG_STYLUS) {
-               suffix = "Pen";
-               /* force BTN_STYLUS to allow tablet matching in udev */
-               __set_bit(BTN_STYLUS, hi->input->keybit);
-       } else {
-               switch (field->application) {
+       if (!suffix) {
+               switch (application) {
                case HID_GD_KEYBOARD:
-                       suffix = "Keyboard";
-                       break;
                case HID_GD_KEYPAD:
-                       suffix = "Keypad";
-                       break;
                case HID_GD_MOUSE:
-                       suffix = "Mouse";
-                       break;
-               case HID_DG_STYLUS:
-                       suffix = "Pen";
-                       /* force BTN_STYLUS to allow tablet matching in udev */
-                       __set_bit(BTN_STYLUS, hi->input->keybit);
-                       break;
-               case HID_DG_TOUCHSCREEN:
-                       /* we do not set suffix = "Touchscreen" */
-                       break;
                case HID_DG_TOUCHPAD:
-                       suffix = "Touchpad";
-                       break;
                case HID_GD_SYSTEM_CONTROL:
-                       suffix = "System Control";
-                       break;
                case HID_CP_CONSUMER_CONTROL:
-                       suffix = "Consumer Control";
-                       break;
                case HID_GD_WIRELESS_RADIO_CTLS:
-                       suffix = "Wireless Radio Control";
+                       /* already handled by hid core */
+                       break;
+               case HID_DG_TOUCHSCREEN:
+                       /* we do not set suffix = "Touchscreen" */
+                       hi->input->name = hdev->name;
+                       break;
+               case HID_DG_STYLUS:
+                       /* force BTN_STYLUS to allow tablet matching in udev */
+                       __set_bit(BTN_STYLUS, hi->input->keybit);
                        break;
                case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
                        suffix = "Custom Media Keys";
@@ -1434,8 +1448,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
        td->hdev = hdev;
        td->mtclass = *mtclass;
-       td->inputmode = -1;
-       td->maxcontact_report_id = -1;
        td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
        td->cc_index = -1;
        td->scantime_index = -1;
@@ -1459,10 +1471,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        /*
         * This allows the driver to handle different input sensors
-        * that emits events through different reports on the same HID
+        * that emits events through different applications on the same HID
         * device.
         */
-       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+       hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
 
        timer_setup(&td->release_timer, mt_expired_timeout, 0);
 
@@ -1482,8 +1494,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
                dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
                                hdev->name);
 
-       mt_set_maxcontacts(hdev);
-       mt_set_input_mode(hdev);
+       mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
 
        /* release .fields memory as it is not used anymore */
        devm_kfree(&hdev->dev, td->fields);
@@ -1496,8 +1507,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 static int mt_reset_resume(struct hid_device *hdev)
 {
        mt_release_contacts(hdev);
-       mt_set_maxcontacts(hdev);
-       mt_set_input_mode(hdev);
+       mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
        return 0;
 }
 
index 08d92bb005fd8dd8e7bd6dbd6798dee378953d00..41a3d5775394fed48e7b880317eaf6c1944c2817 100644 (file)
@@ -292,9 +292,12 @@ struct hid_item {
 #define HID_DG_CONTACTCOUNT    0x000d0054
 #define HID_DG_CONTACTMAX      0x000d0055
 #define HID_DG_SCANTIME                0x000d0056
+#define HID_DG_SURFACESWITCH   0x000d0057
+#define HID_DG_BUTTONSWITCH    0x000d0058
 #define HID_DG_BUTTONTYPE      0x000d0059
 #define HID_DG_BARRELSWITCH2   0x000d005a
 #define HID_DG_TOOLSERIALNUMBER        0x000d005b
+#define HID_DG_LATENCYMODE     0x000d0060
 
 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS  0xff310076
 /*
@@ -341,10 +344,12 @@ struct hid_item {
 /* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */
 /* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
 #define HID_QUIRK_ALWAYS_POLL                  BIT(10)
+#define HID_QUIRK_INPUT_PER_APP                        BIT(11)
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS          BIT(16)
 #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID                BIT(17)
 #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)
 #define HID_QUIRK_HAVE_SPECIAL_DRIVER          BIT(19)
+#define HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE BIT(20)
 #define HID_QUIRK_FULLSPEED_INTERVAL           BIT(28)
 #define HID_QUIRK_NO_INIT_REPORTS              BIT(29)
 #define HID_QUIRK_NO_IGNORE                    BIT(30)
@@ -464,8 +469,10 @@ struct hid_field {
 
 struct hid_report {
        struct list_head list;
-       unsigned id;                                    /* id of this report */
-       unsigned type;                                  /* report type */
+       struct list_head hidinput_list;
+       unsigned int id;                                /* id of this report */
+       unsigned int type;                              /* report type */
+       unsigned int application;                       /* application usage for this report */
        struct hid_field *field[HID_MAX_FIELDS];        /* fields of the report */
        unsigned maxfield;                              /* maximum valid field index */
        unsigned size;                                  /* size of the report (bits) */
@@ -503,12 +510,15 @@ struct hid_output_fifo {
 
 #define HID_STAT_ADDED         BIT(0)
 #define HID_STAT_PARSED                BIT(1)
+#define HID_STAT_DUP_DETECTED  BIT(2)
 
 struct hid_input {
        struct list_head list;
        struct hid_report *report;
        struct input_dev *input;
+       const char *name;
        bool registered;
+       struct list_head reports;       /* the list of reports */
 };
 
 enum hid_type {
@@ -865,7 +875,9 @@ void hid_output_report(struct hid_report *report, __u8 *data);
 void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype);
 u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 struct hid_device *hid_allocate_device(void);
-struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
+struct hid_report *hid_register_report(struct hid_device *device,
+                                      unsigned int type, unsigned int id,
+                                      unsigned int application);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
 struct hid_report *hid_validate_values(struct hid_device *hid,
                                       unsigned int type, unsigned int id,