Merge branches 'for-3.7/upstream-fixes', 'for-3.8/hidraw', 'for-3.8/i2c-hid', 'for...
[pandora-kernel.git] / drivers / hid / hid-input.c
index d917c0d..21b196c 100644 (file)
@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev,
        return -EINVAL;
 }
 
-
 /**
  * hidinput_calc_abs_res - calculate an absolute axis resolution
  * @field: the HID report field to calculate resolution for
@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
  * Only exponent 1 length units are processed. Centimeters and inches are
  * converted to millimeters. Degrees are converted to radians.
  */
-static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 {
        __s32 unit_exponent = field->unit_exponent;
        __s32 logical_extents = field->logical_maximum -
@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
        case ABS_X:
        case ABS_Y:
        case ABS_Z:
-               if (field->unit == 0x11) {              /* If centimeters */
+       case ABS_MT_POSITION_X:
+       case ABS_MT_POSITION_Y:
+       case ABS_MT_TOOL_X:
+       case ABS_MT_TOOL_Y:
+       case ABS_MT_TOUCH_MAJOR:
+       case ABS_MT_TOUCH_MINOR:
+               if (field->unit & 0xffffff00)           /* Not a length */
+                       return 0;
+               unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
+               switch (field->unit & 0xf) {
+               case 0x1:                               /* If centimeters */
                        /* Convert to millimeters */
                        unit_exponent += 1;
-               } else if (field->unit == 0x13) {       /* If inches */
+                       break;
+               case 0x3:                               /* If inches */
                        /* Convert to millimeters */
                        prev = physical_extents;
                        physical_extents *= 254;
                        if (physical_extents < prev)
                                return 0;
                        unit_exponent -= 1;
-               } else {
+                       break;
+               default:
                        return 0;
                }
                break;
@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
        }
 
        /* Calculate resolution */
-       return logical_extents / physical_extents;
+       return DIV_ROUND_CLOSEST(logical_extents, physical_extents);
 }
+EXPORT_SYMBOL_GPL(hidinput_calc_abs_res);
 
 #ifdef CONFIG_HID_BATTERY_STRENGTH
 static enum power_supply_property hidinput_battery_props[] = {
@@ -298,6 +310,9 @@ static enum power_supply_property hidinput_battery_props[] = {
 #define HID_BATTERY_QUIRK_FEATURE      (1 << 1) /* ask for feature report */
 
 static const struct hid_device_id hid_battery_quirks[] = {
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+                       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+       HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
          HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                if (code <= 0xf)
                                        code += BTN_JOYSTICK;
                                else
-                                       code += BTN_TRIGGER_HAPPY;
+                                       code += BTN_TRIGGER_HAPPY - 0x10;
+                               break;
+               case HID_GD_GAMEPAD:
+                               if (code <= 0xf)
+                                       code += BTN_GAMEPAD;
+                               else
+                                       code += BTN_TRIGGER_HAPPY - 0x10;
                                break;
-               case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
                default:
                        switch (field->physical) {
                        case HID_GD_MOUSE:
@@ -1146,6 +1166,38 @@ static void report_features(struct hid_device *hid)
                        }
 }
 
+static struct hid_input *hidinput_allocate(struct hid_device *hid)
+{
+       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;
+       }
+
+       input_set_drvdata(input_dev, hid);
+       input_dev->event = hid->ll_driver->hidinput_input_event;
+       input_dev->open = hidinput_open;
+       input_dev->close = hidinput_close;
+       input_dev->setkeycode = hidinput_setkeycode;
+       input_dev->getkeycode = hidinput_getkeycode;
+
+       input_dev->name = hid->name;
+       input_dev->phys = hid->phys;
+       input_dev->uniq = hid->uniq;
+       input_dev->id.bustype = hid->bus;
+       input_dev->id.vendor  = hid->vendor;
+       input_dev->id.product = hid->product;
+       input_dev->id.version = hid->version;
+       input_dev->dev.parent = hid->dev.parent;
+       hidinput->input = input_dev;
+       list_add_tail(&hidinput->list, &hid->inputs);
+
+       return hidinput;
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -1157,7 +1209,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
        struct hid_driver *drv = hid->driver;
        struct hid_report *report;
        struct hid_input *hidinput = NULL;
-       struct input_dev *input_dev;
        int i, j, k;
 
        INIT_LIST_HEAD(&hid->inputs);
@@ -1188,33 +1239,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                continue;
 
                        if (!hidinput) {
-                               hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
-                               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");
+                               hidinput = hidinput_allocate(hid);
+                               if (!hidinput)
                                        goto out_unwind;
-                               }
-
-                               input_set_drvdata(input_dev, hid);
-                               input_dev->event =
-                                       hid->ll_driver->hidinput_input_event;
-                               input_dev->open = hidinput_open;
-                               input_dev->close = hidinput_close;
-                               input_dev->setkeycode = hidinput_setkeycode;
-                               input_dev->getkeycode = hidinput_getkeycode;
-
-                               input_dev->name = hid->name;
-                               input_dev->phys = hid->phys;
-                               input_dev->uniq = hid->uniq;
-                               input_dev->id.bustype = hid->bus;
-                               input_dev->id.vendor  = hid->vendor;
-                               input_dev->id.product = hid->product;
-                               input_dev->id.version = hid->version;
-                               input_dev->dev.parent = hid->dev.parent;
-                               hidinput->input = input_dev;
-                               list_add_tail(&hidinput->list, &hid->inputs);
                        }
 
                        for (i = 0; i < report->maxfield; i++)