diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 12:00:48 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 12:00:48 -0800 |
commit | fd62c5450324af7f6cc12897b09b77285cd48a92 (patch) | |
tree | d4390981348e5a08e31a50fe9cb0da0715cf005c /drivers/hid/hid-input.c | |
parent | a2013a13e68354e0c8f3696b69701803e13fb737 (diff) | |
parent | 818b930bc15077fc00ff16bb22c5df1857f05afa (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID subsystem updates from Jiri Kosina:
1) Support for HID over I2C bus has been added by Benjamin Tissoires.
ACPI device discovery is still in the works.
2) Support for Win8 Multitiouch protocol is being added, most work done
by Benjamin Tissoires as well
3) EIO/ERESTARTSYS is fixed in hiddev/hidraw, fixes by Andrew Duggan
and Jiri Kosina
4) ION iCade driver added by Bastien Nocera
5) Support for a couple new Roccat devices has been added by Stefan
Achatz
6) HID sensor hubs are now auto-detected instead of having to list all
the VID/PID combinations in the blacklist array
7) other random fixes and support for new device IDs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (65 commits)
HID: i2c-hid: add mutex protecting open/close race
Revert "HID: sensors: add to special driver list"
HID: sensors: autodetect USB HID sensor hubs
HID: hidp: fallback to input session properly if hid is blacklisted
HID: i2c-hid: fix ret_count check
HID: i2c-hid: fix i2c_hid_get_raw_report count mismatches
HID: i2c-hid: remove extra .irq field in struct i2c_hid
HID: i2c-hid: reorder allocation/free of buffers
HID: i2c-hid: fix memory corruption due to missing hid declaration
HID: i2c-hid: remove superfluous include
HID: i2c-hid: remove unneeded test in i2c_hid_remove
HID: i2c-hid: i2c_hid_get_report may fail
HID: i2c-hid: also call i2c_hid_free_buffers in i2c_hid_remove
HID: i2c-hid: fix error messages
HID: i2c-hid: fix return paths
HID: i2c-hid: remove unused static declarations
HID: i2c-hid: fix i2c_hid_dbg macro
HID: i2c-hid: fix checkpatch.pl warning
HID: i2c-hid: enhance Kconfig
HID: i2c-hid: change I2C name
...
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r-- | drivers/hid/hid-input.c | 97 |
1 files changed, 62 insertions, 35 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d917c0d53685..21b196c394b1 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -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[] = { @@ -299,6 +311,9 @@ static enum power_supply_property hidinput_battery_props[] = { 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 }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, @@ -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++) |