diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 10:48:30 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 10:48:30 +0100 |
commit | 617677295b53a40d0e54aac4cbbc216ffbc755dd (patch) | |
tree | 51b9e87213243ed5efff252c8e8d8fec4eebc588 /drivers/hid | |
parent | 5c8d1b68e01a144813e38795fe6dbe7ebb506131 (diff) | |
parent | 6abb7c25775b7fb2225ad0508236d63ca710e65f (diff) |
Merge branch 'master' into for-next
Conflicts:
drivers/devfreq/exynos4_bus.c
Sync with Linus' tree to be able to apply patches that are
against newer code (mvneta).
Diffstat (limited to 'drivers/hid')
28 files changed, 2274 insertions, 917 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index eb325baa738..eae0c7e468c 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -265,6 +265,15 @@ config HID_GYRATION ---help--- Support for Gyration remote control. +config HID_ICADE + tristate "ION iCade arcade controller" + depends on BT_HIDP + ---help--- + Support for the ION iCade arcade controller to work as a joystick. + + To compile this driver as a module, choose M here: the + module will be called hid-icade. + config HID_TWINHAN tristate "Twinhan IR remote control" depends on USB_HID @@ -728,4 +737,6 @@ endif # HID source "drivers/hid/usbhid/Kconfig" +source "drivers/hid/i2c-hid/Kconfig" + endmenu diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index cef68ca859d..b62215716b2 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o +obj-$(CONFIG_HID_ICADE) += hid-icade.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KYE) += hid-kye.o @@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ - hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \ - hid-roccat-savu.o + hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \ + hid-roccat-pyra.o hid-roccat-savu.o obj-$(CONFIG_HID_SAITEK) += hid-saitek.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o @@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ obj-$(CONFIG_USB_KBD) += usbhid/ +obj-$(CONFIG_I2C_HID) += i2c-hid/ diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 06ebdbb6ea0..d0f7662aacc 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | + APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | APPLE_RDESC_JIS }, @@ -522,6 +523,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd3971bf31b..eb2ee11b641 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) }, @@ -1532,9 +1559,13 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { 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) }, @@ -1568,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) }, @@ -1655,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) }, @@ -1669,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) }, @@ -2139,13 +2167,21 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { 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) }, { } }; -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 */ @@ -2182,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 && @@ -2191,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) { @@ -2202,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; /* diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c new file mode 100644 index 00000000000..1d6565e37ba --- /dev/null +++ b/drivers/hid/hid-icade.c @@ -0,0 +1,259 @@ +/* + * ION iCade input driver + * + * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net> + * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <linux/device.h> +#include <linux/hid.h> +#include <linux/module.h> + +#include "hid-ids.h" + +/* + * ↑ A C Y L + * ← → + * ↓ B X Z R + * + * + * UP ON,OFF = w,e + * RT ON,OFF = d,c + * DN ON,OFF = x,z + * LT ON,OFF = a,q + * A ON,OFF = y,t + * B ON,OFF = h,r + * C ON,OFF = u,f + * X ON,OFF = j,n + * Y ON,OFF = i,m + * Z ON,OFF = k,p + * L ON,OFF = o,g + * R ON,OFF = l,v + */ + +/* The translation code uses HID usage instead of input layer + * keys. This code generates a lookup table that makes + * translation quick. + * + * #include <linux/input.h> + * #include <stdio.h> + * #include <assert.h> + * + * #define unk KEY_UNKNOWN + * + * < copy of hid_keyboard[] from hid-input.c > + * + * struct icade_key_translation { + * int from; + * const char *to; + * int press; + * }; + * + * static const struct icade_key_translation icade_keys[] = { + * { KEY_W, "KEY_UP", 1 }, + * { KEY_E, "KEY_UP", 0 }, + * { KEY_D, "KEY_RIGHT", 1 }, + * { KEY_C, "KEY_RIGHT", 0 }, + * { KEY_X, "KEY_DOWN", 1 }, + * { KEY_Z, "KEY_DOWN", 0 }, + * { KEY_A, "KEY_LEFT", 1 }, + * { KEY_Q, "KEY_LEFT", 0 }, + * { KEY_Y, "BTN_A", 1 }, + * { KEY_T, "BTN_A", 0 }, + * { KEY_H, "BTN_B", 1 }, + * { KEY_R, "BTN_B", 0 }, + * { KEY_U, "BTN_C", 1 }, + * { KEY_F, "BTN_C", 0 }, + * { KEY_J, "BTN_X", 1 }, + * { KEY_N, "BTN_X", 0 }, + * { KEY_I, "BTN_Y", 1 }, + * { KEY_M, "BTN_Y", 0 }, + * { KEY_K, "BTN_Z", 1 }, + * { KEY_P, "BTN_Z", 0 }, + * { KEY_O, "BTN_THUMBL", 1 }, + * { KEY_G, "BTN_THUMBL", 0 }, + * { KEY_L, "BTN_THUMBR", 1 }, + * { KEY_V, "BTN_THUMBR", 0 }, + * + * { } + * }; + * + * static int + * usage_for_key (int key) + * { + * int i; + * for (i = 0; i < 256; i++) { + * if (hid_keyboard[i] == key) + * return i; + * } + * assert(0); + * } + * + * int main (int argc, char **argv) + * { + * const struct icade_key_translation *trans; + * int max_usage = 0; + * + * for (trans = icade_keys; trans->from; trans++) { + * int usage = usage_for_key (trans->from); + * max_usage = usage > max_usage ? usage : max_usage; + * } + * + * printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage); + * printf ("struct icade_key {\n"); + * printf ("\tu16 to;\n"); + * printf ("\tu8 press:1;\n"); + * printf ("};\n\n"); + * printf ("static const struct icade_key " + * "icade_usage_table[%d] = {\n", max_usage + 1); + * for (trans = icade_keys; trans->from; trans++) { + * printf ("\t[%d] = { %s, %d },\n", + * usage_for_key (trans->from), trans->to, trans->press); + * } + * printf ("};\n"); + * + * return 0; + * } + */ + +#define ICADE_MAX_USAGE 29 + +struct icade_key { + u16 to; + u8 press:1; +}; + +static const struct icade_key icade_usage_table[30] = { + [26] = { KEY_UP, 1 }, + [8] = { KEY_UP, 0 }, + [7] = { KEY_RIGHT, 1 }, + [6] = { KEY_RIGHT, 0 }, + [27] = { KEY_DOWN, 1 }, + [29] = { KEY_DOWN, 0 }, + [4] = { KEY_LEFT, 1 }, + [20] = { KEY_LEFT, 0 }, + [28] = { BTN_A, 1 }, + [23] = { BTN_A, 0 }, + [11] = { BTN_B, 1 }, + [21] = { BTN_B, 0 }, + [24] = { BTN_C, 1 }, + [9] = { BTN_C, 0 }, + [13] = { BTN_X, 1 }, + [17] = { BTN_X, 0 }, + [12] = { BTN_Y, 1 }, + [16] = { BTN_Y, 0 }, + [14] = { BTN_Z, 1 }, + [19] = { BTN_Z, 0 }, + [18] = { BTN_THUMBL, 1 }, + [10] = { BTN_THUMBL, 0 }, + [15] = { BTN_THUMBR, 1 }, + [25] = { BTN_THUMBR, 0 }, +}; + +static const struct icade_key *icade_find_translation(u16 from) +{ + if (from < 0 || from > ICADE_MAX_USAGE) + return NULL; + return &icade_usage_table[from]; +} + +static int icade_event(struct hid_device *hdev, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + const struct icade_key *trans; + + if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || + !usage->type) + return 0; + + /* We ignore the fake key up, and act only on key down */ + if (!value) + return 1; + + trans = icade_find_translation(usage->hid & HID_USAGE); + + if (!trans) + return 1; + + input_event(field->hidinput->input, usage->type, + trans->to, trans->press); + + return 1; +} + +static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + const struct icade_key *trans; + + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) { + trans = icade_find_translation(usage->hid & HID_USAGE); + + if (!trans) + return -1; + + hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to); + set_bit(trans->to, hi->input->keybit); + + return 1; + } + + /* ignore others */ + return -1; + +} + +static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if (usage->type == EV_KEY) + set_bit(usage->type, hi->input->evbit); + + return -1; +} + +static const struct hid_device_id icade_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, + + { } +}; +MODULE_DEVICE_TABLE(hid, icade_devices); + +static struct hid_driver icade_driver = { + .name = "icade", + .id_table = icade_devices, + .event = icade_event, + .input_mapped = icade_input_mapped, + .input_mapping = icade_input_mapping, +}; + +static int __init icade_init(void) +{ + int ret; + + ret = hid_register_driver(&icade_driver); + if (ret) + pr_err("can't register icade driver\n"); + + return ret; +} + +static void __exit icade_exit(void) +{ + hid_unregister_driver(&icade_driver); +} + +module_init(icade_init); +module_exit(icade_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); +MODULE_DESCRIPTION("ION iCade input driver"); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 269b50912a4..4dfa605e2d1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -118,6 +118,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b @@ -254,6 +257,7 @@ #define USB_VENDOR_ID_DWAV 0x0eef #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 +#define USB_DEVICE_ID_DWAV_TOUCHCONTROLLER 0x0002 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 0x7207 @@ -420,6 +424,9 @@ #define USB_VENDOR_ID_ILITEK 0x222a #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 +#define USB_VENDOR_ID_ION 0x15e4 +#define USB_DEVICE_ID_ICADE 0x0132 + #define USB_VENDOR_ID_HOLTEK 0x1241 #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 @@ -429,11 +436,6 @@ #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 -#define USB_VENDOR_ID_INTEL_8086 0x8086 -#define USB_VENDOR_ID_INTEL_8087 0x8087 -#define USB_DEVICE_ID_SENSOR_HUB_1020 0x1020 -#define USB_DEVICE_ID_SENSOR_HUB_09FA 0x09FA - #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 @@ -600,6 +602,7 @@ #define USB_VENDOR_ID_NOVATEK 0x0603 #define USB_DEVICE_ID_NOVATEK_PCT 0x0600 +#define USB_DEVICE_ID_NOVATEK_MOUSE 0x1602 #define USB_VENDOR_ID_NTRIG 0x1b96 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 @@ -674,7 +677,9 @@ #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 +#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 +#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 #define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a @@ -693,6 +698,9 @@ #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 +#define USB_VENDOR_ID_SIGMATEL 0x066F +#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 + #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 @@ -711,7 +719,6 @@ #define USB_VENDOR_ID_STANTUM_STM 0x0483 #define USB_DEVICE_ID_MTP_STM 0x3261 -#define USB_DEVICE_ID_SENSOR_HUB_7014 0x7014 #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 #define USB_DEVICE_ID_MTP_SITRONIX 0x5001 @@ -759,6 +766,9 @@ #define USB_VENDOR_ID_TOUCHPACK 0x1bfd #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 +#define USB_VENDOR_ID_TPV 0x25aa +#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN 0x8883 + #define USB_VENDOR_ID_TURBOX 0x062a #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d917c0d5368..21b196c394b 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++) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 3acdcfcc |