]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/input/tablet/wacom_sys.c
Merge tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / input / tablet / wacom_sys.c
index aaf23aeae2ea428b4a26ea0cd99f20eeac32c964..79b69ea47f747abd035d2eb44cad9d724699ddd7 100644 (file)
@@ -221,39 +221,6 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
        return logical_extents / physical_extents;
 }
 
-/*
- * The physical dimension specified by the HID descriptor is likely not in
- * the "100th of a mm" units expected by wacom_calculate_touch_res. This
- * function adjusts the value of [xy]_phy based on the unit and exponent
- * provided by the HID descriptor. If an error occurs durring conversion
- * (e.g. from the unit being left unspecified) [xy]_phy is not modified.
- */
-static void wacom_fix_phy_from_hid(struct wacom_features *features)
-{
-       int xres = wacom_calc_hid_res(features->x_max, features->x_phy,
-                                       features->unit, features->unitExpo);
-       int yres = wacom_calc_hid_res(features->y_max, features->y_phy,
-                                       features->unit, features->unitExpo);
-
-       if (xres > 0 && yres > 0) {
-               features->x_phy = (100 * features->x_max) / xres;
-               features->y_phy = (100 * features->y_max) / yres;
-       }
-}
-
-/*
- * Static values for max X/Y and resolution of Pen interface is stored in
- * features. This mean physical size of active area can be computed.
- * This is useful to do when Pen and Touch have same active area of tablet.
- * This means for Touch device, we only need to find max X/Y value and we
- * have enough information to compute resolution of touch.
- */
-static void wacom_set_phy_from_res(struct wacom_features *features)
-{
-       features->x_phy = (features->x_max * 100) / features->x_resolution;
-       features->y_phy = (features->y_max * 100) / features->y_resolution;
-}
-
 static int wacom_parse_logical_collection(unsigned char *report,
                                          struct wacom_features *features)
 {
@@ -265,8 +232,6 @@ static int wacom_parse_logical_collection(unsigned char *report,
                features->pktlen = WACOM_PKGLEN_BBTOUCH3;
                features->device_type = BTN_TOOL_FINGER;
 
-               wacom_set_phy_from_res(features);
-
                features->x_max = features->y_max =
                        get_unaligned_le16(&report[10]);
 
@@ -640,9 +605,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
                }
        }
        error = wacom_parse_hid(intf, hid_desc, features);
-       if (error)
-               goto out;
-       wacom_fix_phy_from_hid(features);
 
  out:
        return error;
@@ -1228,7 +1190,6 @@ static void wacom_wireless_work(struct work_struct *work)
                        *((struct wacom_features *)id->driver_info);
                wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
                wacom_wac2->features.device_type = BTN_TOOL_FINGER;
-               wacom_set_phy_from_res(&wacom_wac2->features);
                wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
                error = wacom_register_input(wacom2);
                if (error)
@@ -1251,6 +1212,33 @@ fail1:
        return;
 }
 
+/*
+ * Not all devices report physical dimensions from HID.
+ * Compute the default from hardcoded logical dimension
+ * and resolution before driver overwrites them.
+ */
+static void wacom_set_default_phy(struct wacom_features *features)
+{
+       if (features->x_resolution) {
+               features->x_phy = (features->x_max * 100) /
+                                       features->x_resolution;
+               features->y_phy = (features->y_max * 100) /
+                                       features->y_resolution;
+       }
+}
+
+static void wacom_calculate_res(struct wacom_features *features)
+{
+       features->x_resolution = wacom_calc_hid_res(features->x_max,
+                                                   features->x_phy,
+                                                   features->unit,
+                                                   features->unitExpo);
+       features->y_resolution = wacom_calc_hid_res(features->y_max,
+                                                   features->y_phy,
+                                                   features->unit,
+                                                   features->unitExpo);
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
@@ -1297,6 +1285,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
+       /* set the default size in case we do not get them from hid */
+       wacom_set_default_phy(features);
+
        /* Retrieve the physical and logical size for touch devices */
        error = wacom_retrieve_hid_descriptor(intf, features);
        if (error)
@@ -1312,8 +1303,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
                        features->device_type = BTN_TOOL_FINGER;
                        features->pktlen = WACOM_PKGLEN_BBTOUCH3;
 
-                       wacom_set_phy_from_res(features);
-
                        features->x_max = 4096;
                        features->y_max = 4096;
                } else {
@@ -1323,6 +1312,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        wacom_setup_device_quirks(features);
 
+       /* set unit to "100th of a mm" for devices not reported by HID */
+       if (!features->unit) {
+               features->unit = 0x11;
+               features->unitExpo = 16 - 3;
+       }
+       wacom_calculate_res(features);
+
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
        if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
@@ -1334,7 +1330,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
                                " Pen" : " Finger",
                        sizeof(wacom_wac->name));
 
-
                other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
                if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
                        other_dev = dev;
@@ -1366,8 +1361,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        usb_set_intfdata(intf, wacom);
 
        if (features->quirks & WACOM_QUIRK_MONITOR) {
-               if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+               if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
+                       error = -EIO;
                        goto fail5;
+               }
        }
 
        return 0;
@@ -1422,8 +1419,8 @@ static int wacom_resume(struct usb_interface *intf)
        wacom_query_tablet_data(intf, features);
        wacom_led_control(wacom);
 
-       if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR)
-            && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+       if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) &&
+           usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
                rv = -EIO;
 
        mutex_unlock(&wacom->lock);