]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/hid/hid-multitouch.c
Merge branches 'for-4.10/asus', 'for-4.10/cp2112', 'for-4.10/i2c-hid-nopower', 'for...
[karo-tx-linux.git] / drivers / hid / hid-multitouch.c
index fb6f1f4472795700c1f12889c405b9350b4ebcb0..6dca668068440213d837f69c7763bddbe91e561b 100644 (file)
@@ -108,6 +108,7 @@ struct mt_device {
        int cc_value_index;     /* contact count value index in the field */
        unsigned last_slot_field;       /* the last field of a slot */
        unsigned mt_report_id;  /* the report ID of the multitouch device */
+       unsigned long initial_quirks;   /* initial quirks state */
        __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,
@@ -318,13 +319,10 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
        u8 *buf;
 
        /*
-        * Only fetch the feature report if initial reports are not already
-        * been retrieved. Currently this is only done for Windows 8 touch
-        * devices.
+        * Do not fetch the feature report if the device has been explicitly
+        * marked as non-capable.
         */
-       if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
-               return;
-       if (td->mtclass.name != MT_CLS_WIN_8)
+       if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
                return;
 
        buf = hid_alloc_report_buf(report, GFP_KERNEL);
@@ -567,6 +565,14 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 
        case HID_UP_BUTTON:
                code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
+               /*
+                * MS PTP spec says that external buttons left and right have
+                * usages 2 and 3.
+                */
+               if (cls->name == MT_CLS_WIN_8 &&
+                   field->application == HID_DG_TOUCHPAD &&
+                   (usage->hid & HID_USAGE) > 1)
+                       code--;
                hid_map_usage(hi, usage, bit, max, EV_KEY, code);
                input_set_capability(hi->input, EV_KEY, code);
                return 1;
@@ -842,7 +848,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        if (!td->mtclass.export_all_inputs &&
            field->application != HID_DG_TOUCHSCREEN &&
            field->application != HID_DG_PEN &&
-           field->application != HID_DG_TOUCHPAD)
+           field->application != HID_DG_TOUCHPAD &&
+           field->application != HID_GD_KEYBOARD &&
+           field->application != HID_CP_CONSUMER_CONTROL)
                return -1;
 
        /*
@@ -1083,36 +1091,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
                }
        }
 
-       /* This allows the driver to correctly support devices
-        * that emit events over several HID messages.
-        */
-       hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
-
-       /*
-        * This allows the driver to handle different input sensors
-        * that emits events through different reports on the same HID
-        * device.
-        */
-       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
-       hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
-
-       /*
-        * Handle special quirks for Windows 8 certified devices.
-        */
-       if (id->group == HID_GROUP_MULTITOUCH_WIN_8)
-               /*
-                * Some multitouch screens do not like to be polled for input
-                * reports. Fortunately, the Win8 spec says that all touches
-                * should be sent during each report, making the initialization
-                * of input reports unnecessary.
-                *
-                * In addition some touchpads do not behave well if we read
-                * all feature reports from them. Instead we prevent
-                * initial report fetching and then selectively fetch each
-                * report we are interested in.
-                */
-               hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
-
        td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
        if (!td) {
                dev_err(&hdev->dev, "cannot allocate multitouch data\n");
@@ -1136,6 +1114,39 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
                td->serial_maybe = true;
 
+       /*
+        * Store the initial quirk state
+        */
+       td->initial_quirks = hdev->quirks;
+
+       /* This allows the driver to correctly support devices
+        * that emit events over several HID messages.
+        */
+       hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
+       /*
+        * This allows the driver to handle different input sensors
+        * that emits events through different reports on the same HID
+        * device.
+        */
+       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+       hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+
+       /*
+        * Some multitouch screens do not like to be polled for input
+        * reports. Fortunately, the Win8 spec says that all touches
+        * should be sent during each report, making the initialization
+        * of input reports unnecessary. For Win7 devices, well, let's hope
+        * they will still be happy (this is only be a problem if a touch
+        * was already there while probing the device).
+        *
+        * In addition some touchpads do not behave well if we read
+        * all feature reports from them. Instead we prevent
+        * initial report fetching and then selectively fetch each
+        * report we are interested in.
+        */
+       hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+
        ret = hid_parse(hdev);
        if (ret != 0)
                return ret;
@@ -1204,8 +1215,11 @@ static int mt_resume(struct hid_device *hdev)
 
 static void mt_remove(struct hid_device *hdev)
 {
+       struct mt_device *td = hid_get_drvdata(hdev);
+
        sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
        hid_hw_stop(hdev);
+       hdev->quirks = td->initial_quirks;
 }
 
 /*