Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[cascardo/linux.git] / drivers / hid / wacom_sys.c
index 8593047..6542029 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "wacom_wac.h"
 #include "wacom.h"
+#include <linux/input/mt.h>
 
 #define WAC_MSG_RETRIES                5
 
@@ -70,22 +71,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
 static int wacom_open(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
-       int retval;
-
-       mutex_lock(&wacom->lock);
-       retval = hid_hw_open(wacom->hdev);
-       mutex_unlock(&wacom->lock);
 
-       return retval;
+       return hid_hw_open(wacom->hdev);
 }
 
 static void wacom_close(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
 
-       mutex_lock(&wacom->lock);
        hid_hw_close(wacom->hdev);
-       mutex_unlock(&wacom->lock);
 }
 
 /*
@@ -192,9 +186,15 @@ static void wacom_usage_mapping(struct hid_device *hdev,
        if (!pen && !finger)
                return;
 
-       if (finger && !features->touch_max)
-               /* touch device at least supports one touch point */
-               features->touch_max = 1;
+       /*
+        * Bamboo models do not support HID_DG_CONTACTMAX.
+        * And, Bamboo Pen only descriptor contains touch.
+        */
+       if (features->type != BAMBOO_PT) {
+               /* ISDv4 touch devices at least supports one touch point */
+               if (finger && !features->touch_max)
+                       features->touch_max = 1;
+       }
 
        switch (usage->hid) {
        case HID_GD_X:
@@ -230,6 +230,21 @@ static void wacom_usage_mapping(struct hid_device *hdev,
                wacom_wac_usage_mapping(hdev, field, usage);
 }
 
+static void wacom_post_parse_hid(struct hid_device *hdev,
+                                struct wacom_features *features)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+       if (features->type == HID_GENERIC) {
+               /* Any last-minute generic device setup */
+               if (features->touch_max > 1) {
+                       input_mt_init_slots(wacom_wac->input, wacom_wac->features.touch_max,
+                                   INPUT_MT_DIRECT);
+               }
+       }
+}
+
 static void wacom_parse_hid(struct hid_device *hdev,
                           struct wacom_features *features)
 {
@@ -264,6 +279,8 @@ static void wacom_parse_hid(struct hid_device *hdev,
                                wacom_usage_mapping(hdev, hreport->field[i],
                                                hreport->field[i]->usage + j);
        }
+
+       wacom_post_parse_hid(hdev, features);
 }
 
 static int wacom_hid_set_device_mode(struct hid_device *hdev)
@@ -1129,7 +1146,7 @@ static void wacom_clean_inputs(struct wacom *wacom)
                        input_free_device(wacom->wacom_wac.input);
        }
        if (wacom->wacom_wac.pad_input) {
-               if (wacom->wacom_wac.input_registered)
+               if (wacom->wacom_wac.pad_registered)
                        input_unregister_device(wacom->wacom_wac.pad_input);
                else
                        input_free_device(wacom->wacom_wac.pad_input);
@@ -1151,13 +1168,13 @@ static int wacom_register_inputs(struct wacom *wacom)
        if (!input_dev || !pad_input_dev)
                return -EINVAL;
 
-       error = wacom_setup_input_capabilities(input_dev, wacom_wac);
-       if (error)
-               return error;
-
-       error = input_register_device(input_dev);
-       if (error)
-               return error;
+       error = wacom_setup_pentouch_input_capabilities(input_dev, wacom_wac);
+       if (!error) {
+               error = input_register_device(input_dev);
+               if (error)
+                       return error;
+               wacom_wac->input_registered = true;
+       }
 
        error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
        if (error) {
@@ -1169,22 +1186,23 @@ static int wacom_register_inputs(struct wacom *wacom)
                error = input_register_device(pad_input_dev);
                if (error)
                        goto fail_register_pad_input;
+               wacom_wac->pad_registered = true;
 
                error = wacom_initialize_leds(wacom);
                if (error)
                        goto fail_leds;
        }
 
-       wacom_wac->input_registered = true;
-
        return 0;
 
 fail_leds:
        input_unregister_device(pad_input_dev);
        pad_input_dev = NULL;
+       wacom_wac->pad_registered = false;
 fail_register_pad_input:
        input_unregister_device(input_dev);
        wacom_wac->input = NULL;
+       wacom_wac->input_registered = false;
        return error;
 }
 
@@ -1321,12 +1339,6 @@ static void wacom_calculate_res(struct wacom_features *features)
                                                    features->unitExpo);
 }
 
-static int wacom_hid_report_len(struct hid_report *report)
-{
-       /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
-       return ((report->size - 1) >> 3) + 1 + (report->id > 0);
-}
-
 static size_t wacom_compute_pktlen(struct hid_device *hdev)
 {
        struct hid_report_enum *report_enum;
@@ -1336,7 +1348,7 @@ static size_t wacom_compute_pktlen(struct hid_device *hdev)
        report_enum = hdev->report_enum + HID_INPUT_REPORT;
 
        list_for_each_entry(report, &report_enum->report_list, list) {
-               size_t report_size = wacom_hid_report_len(report);
+               size_t report_size = hid_report_len(report);
                if (report_size > size)
                        size = report_size;
        }