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-core.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial (diff) | |
parent | Merge branches 'for-3.7/upstream-fixes', 'for-3.8/hidraw', 'for-3.8/i2c-hid', 'for-3.8/multitouch', 'for-3.8/roccat', 'for-3.8/sensors' and 'for-3.8/upstream' into for-linus (diff) | |
download | linux-dev-fd62c5450324af7f6cc12897b09b77285cd48a92.tar.xz linux-dev-fd62c5450324af7f6cc12897b09b77285cd48a92.zip |
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-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f4109fd657ff..eb2ee11b6412 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report); static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) { struct hid_field *field; + int i; if (report->maxfield == HID_MAX_FIELDS) { hid_err(report->device, "too many fields in report\n"); @@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned field->value = (s32 *)(field->usage + usages); field->report = report; + for (i = 0; i < usages; i++) + field->usage[i].usage_index = i; + return field; } @@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item) static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) { + __u32 raw_value; switch (item->tag) { case HID_GLOBAL_ITEM_TAG_PUSH: @@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) return 0; case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: - parser->global.unit_exponent = item_sdata(item); + /* Units exponent negative numbers are given through a + * two's complement. + * See "6.2.2.7 Global Items" for more information. */ + raw_value = item_udata(item); + if (!(raw_value & 0xfffffff0)) + parser->global.unit_exponent = hid_snto32(raw_value, 4); + else + parser->global.unit_exponent = raw_value; return 0; case HID_GLOBAL_ITEM_TAG_UNIT: @@ -713,7 +725,12 @@ static int hid_scan_report(struct hid_device *hid) hid_scan_usage(hid, u); break; } - } + } else if (page == HID_UP_SENSOR && + item.type == HID_ITEM_TYPE_MAIN && + item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION && + (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL && + hid->bus == BUS_USB) + hid->group = HID_GROUP_SENSOR_HUB; } return 0; @@ -865,6 +882,12 @@ static s32 snto32(__u32 value, unsigned n) return value & (1 << (n - 1)) ? value | (-1 << n) : value; } +s32 hid_snto32(__u32 value, unsigned n) +{ + return snto32(value, n); +} +EXPORT_SYMBOL_GPL(hid_snto32); + /* * Convert a signed 32-bit integer to a signed n-bit integer. */ @@ -1465,6 +1488,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect); * there is a proper autodetection and autoloading in place (based on presence * of HID_DG_CONTACTID), so those devices don't need to be added to this list, * as we are doing the right thing in hid_scan_usage(). + * + * Autodetection for (USB) HID sensor hubs exists too. If a collection of type + * physical is found inside a usage page of type sensor, hid-sensor-hub will be + * used as a driver. See hid_scan_report(). */ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, @@ -1538,6 +1565,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, @@ -1571,10 +1599,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) }, - { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, @@ -1658,6 +1683,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, @@ -1672,7 +1698,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, @@ -2150,8 +2175,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { } }; -static bool hid_ignore(struct hid_device *hdev) +bool hid_ignore(struct hid_device *hdev) { + if (hdev->quirks & HID_QUIRK_NO_IGNORE) + return false; + if (hdev->quirks & HID_QUIRK_IGNORE) + return true; + switch (hdev->vendor) { case USB_VENDOR_ID_CODEMERCS: /* ignore all Code Mercenaries IOWarrior devices */ @@ -2188,7 +2218,16 @@ static bool hid_ignore(struct hid_device *hdev) if (hdev->product == USB_DEVICE_ID_JESS_YUREX && hdev->type == HID_TYPE_USBNONE) return true; - break; + break; + case USB_VENDOR_ID_DWAV: + /* These are handled by usbtouchscreen. hdev->type is probably + * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match + * usbtouchscreen. */ + if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER || + hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) && + hdev->type != HID_TYPE_USBMOUSE) + return true; + break; } if (hdev->type == HID_TYPE_USBMOUSE && @@ -2197,6 +2236,7 @@ static bool hid_ignore(struct hid_device *hdev) return !!hid_match_id(hdev, hid_ignore_list); } +EXPORT_SYMBOL_GPL(hid_ignore); int hid_add_device(struct hid_device *hdev) { @@ -2208,8 +2248,7 @@ int hid_add_device(struct hid_device *hdev) /* we need to kill them here, otherwise they will stay allocated to * wait for coming driver */ - if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) - && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE))) + if (hid_ignore(hdev)) return -ENODEV; /* |