summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig102
-rw-r--r--drivers/hid/Makefile11
-rw-r--r--drivers/hid/hid-a4tech.c4
-rw-r--r--drivers/hid/hid-apple.c8
-rw-r--r--drivers/hid/hid-belkin.c4
-rw-r--r--drivers/hid/hid-cherry.c4
-rw-r--r--drivers/hid/hid-chicony.c4
-rw-r--r--drivers/hid/hid-core.c24
-rw-r--r--drivers/hid/hid-cypress.c4
-rw-r--r--drivers/hid/hid-debug.c23
-rw-r--r--drivers/hid/hid-drff.c8
-rw-r--r--drivers/hid/hid-ezkey.c4
-rw-r--r--drivers/hid/hid-gaff.c8
-rw-r--r--drivers/hid/hid-gyration.c4
-rw-r--r--drivers/hid/hid-ids.h16
-rw-r--r--drivers/hid/hid-kensington.c4
-rw-r--r--drivers/hid/hid-kye.c4
-rw-r--r--drivers/hid/hid-lg.c6
-rw-r--r--drivers/hid/hid-lgff.c16
-rw-r--r--drivers/hid/hid-microsoft.c4
-rw-r--r--drivers/hid/hid-monterey.c4
-rw-r--r--drivers/hid/hid-ntrig.c251
-rw-r--r--drivers/hid/hid-petalynx.c4
-rw-r--r--drivers/hid/hid-pl.c4
-rw-r--r--drivers/hid/hid-samsung.c43
-rw-r--r--drivers/hid/hid-sjoy.c180
-rw-r--r--drivers/hid/hid-sony.c4
-rw-r--r--drivers/hid/hid-sunplus.c4
-rw-r--r--drivers/hid/hid-tmff.c27
-rw-r--r--drivers/hid/hid-topseed.c4
-rw-r--r--drivers/hid/hid-twinhan.c147
-rw-r--r--drivers/hid/hid-wacom.c259
-rw-r--r--drivers/hid/hid-zpff.c11
-rw-r--r--drivers/hid/hidraw.c5
-rw-r--r--drivers/hid/usbhid/hid-core.c12
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/hid/usbhid/hiddev.c13
37 files changed, 1109 insertions, 127 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 05950a783560..111afbe8de03 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -101,9 +101,16 @@ config HID_CYPRESS
---help---
Support for cypress mouse and barcode readers.
-config DRAGONRISE_FF
- tristate "DragonRise Inc. force feedback support"
+config HID_DRAGONRISE
+ tristate "DragonRise Inc. support" if EMBEDDED
depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Say Y here if you have DragonRise Inc.game controllers.
+
+config DRAGONRISE_FF
+ bool "DragonRise Inc. force feedback support"
+ depends on HID_DRAGONRISE
select INPUT_FF_MEMLESS
---help---
Say Y here if you want to enable force feedback support for DragonRise Inc.
@@ -130,6 +137,13 @@ config HID_GYRATION
---help---
Support for Gyration remote control.
+config HID_TWINHAN
+ tristate "Twinhan" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for Twinhan IR remote control.
+
config HID_KENSINGTON
tristate "Kensington" if EMBEDDED
depends on USB_HID
@@ -145,7 +159,7 @@ config HID_LOGITECH
Support for Logitech devices that are not fully compliant with HID standard.
config LOGITECH_FF
- bool "Logitech force feedback"
+ bool "Logitech force feedback support"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
@@ -154,6 +168,7 @@ config LOGITECH_FF
- Logitech WingMan Cordless RumblePad 2
- Logitech WingMan Force 3D
- Logitech Formula Force EX
+ - Logitech WingMan Formula Force GP
- Logitech MOMO Force wheel
and if you want to enable force feedback for them.
@@ -161,7 +176,7 @@ config LOGITECH_FF
force feedback.
config LOGIRUMBLEPAD2_FF
- bool "Logitech Rumblepad 2 force feedback"
+ bool "Logitech Rumblepad 2 force feedback support"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
@@ -196,11 +211,19 @@ config HID_PANTHERLORD
---help---
Support for PantherLord/GreenAsia based device support.
+config HID_PANTHERLORD
+ tristate "Pantherlord support" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Say Y here if you have a PantherLord/GreenAsia based game controller
+ or adapter.
+
config PANTHERLORD_FF
bool "Pantherlord force feedback support"
depends on HID_PANTHERLORD
select INPUT_FF_MEMLESS
- help
+ ---help---
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter and want to enable force feedback support for it.
@@ -232,15 +255,38 @@ config HID_SUNPLUS
---help---
Support for Sunplus wireless desktop.
-config GREENASIA_FF
- tristate "GreenAsia (Product ID 0x12) force feedback support"
+config HID_GREENASIA
+ tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED
depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Say Y here if you have a GreenAsia (Product ID 0x12) based game
+ controller or adapter.
+
+config GREENASIA_FF
+ bool "GreenAsia (Product ID 0x12) force feedback support"
+ depends on HID_GREENASIA
select INPUT_FF_MEMLESS
---help---
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
(like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
and want to enable force feedback support for it.
+config HID_SMARTJOYPLUS
+ tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for SmartJoy PLUS PS2/USB adapter.
+
+config SMARTJOYPLUS_FF
+ bool "SmartJoy PLUS PS2/USB adapter force feedback support"
+ depends on HID_SMARTJOYPLUS
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
+ enable force feedback support for it.
+
config HID_TOPSEED
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
depends on USB_HID
@@ -248,21 +294,45 @@ config HID_TOPSEED
---help---
Say Y if you have a TopSeed Cyberlink remote control.
-config THRUSTMASTER_FF
- tristate "ThrustMaster devices support"
+config HID_THRUSTMASTER
+ tristate "ThrustMaster devices support" if EMBEDDED
depends on USB_HID
- select INPUT_FF_MEMLESS
- help
+ default !EMBEDDED
+ ---help---
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
- a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
+ a THRUSTMASTER Ferrari GT Rumble Wheel.
-config ZEROPLUS_FF
- tristate "Zeroplus based game controller support"
- depends on USB_HID
+config THRUSTMASTER_FF
+ bool "ThrustMaster devices force feedback support"
+ depends on HID_THRUSTMASTER
select INPUT_FF_MEMLESS
- help
+ ---help---
+ Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 3,
+ a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT
+ Rumble Force or Force Feedback Wheel.
+
+config HID_WACOM
+ tristate "Wacom Bluetooth devices support" if EMBEDDED
+ depends on BT_HIDP
+ default !EMBEDDED
+ ---help---
+ Support for Wacom Graphire Bluetooth tablet.
+
+config HID_ZEROPLUS
+ tristate "Zeroplus based game controller support" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
Say Y here if you have a Zeroplus based game controller.
+config ZEROPLUS_FF
+ bool "Zeroplus based game controller force feedback support"
+ depends on HID_ZEROPLUS
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you have a Zeroplus based game controller and want
+ to have force feedback support for it.
+
endmenu
endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cf3687d1ed63..0de2dff5542c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
-obj-$(CONFIG_DRAGONRISE_FF) += hid-drff.o
+obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
@@ -37,12 +37,15 @@ obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
+obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
-obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
-obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
+obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
+obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
-obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
+obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
+obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
+obj-$(CONFIG_HID_WACOM) += hid-wacom.o
obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
index 42ea359e94cf..df474c699fb8 100644
--- a/drivers/hid/hid-a4tech.c
+++ b/drivers/hid/hid-a4tech.c
@@ -145,12 +145,12 @@ static struct hid_driver a4_driver = {
.remove = a4_remove,
};
-static int a4_init(void)
+static int __init a4_init(void)
{
return hid_register_driver(&a4_driver);
}
-static void a4_exit(void)
+static void __exit a4_exit(void)
{
hid_unregister_driver(&a4_driver);
}
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index acbce5745b0c..4b96e7a898cf 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -436,10 +436,6 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
- /* Apple wireless Mighty Mouse */
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
- .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
-
{ }
};
MODULE_DEVICE_TABLE(hid, apple_devices);
@@ -455,7 +451,7 @@ static struct hid_driver apple_driver = {
.input_mapped = apple_input_mapped,
};
-static int apple_init(void)
+static int __init apple_init(void)
{
int ret;
@@ -466,7 +462,7 @@ static int apple_init(void)
return ret;
}
-static void apple_exit(void)
+static void __exit apple_exit(void)
{
hid_unregister_driver(&apple_driver);
}
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c
index 2f6723133a4b..4ce7aa3a519f 100644
--- a/drivers/hid/hid-belkin.c
+++ b/drivers/hid/hid-belkin.c
@@ -88,12 +88,12 @@ static struct hid_driver belkin_driver = {
.probe = belkin_probe,
};
-static int belkin_init(void)
+static int __init belkin_init(void)
{
return hid_register_driver(&belkin_driver);
}
-static void belkin_exit(void)
+static void __exit belkin_exit(void)
{
hid_unregister_driver(&belkin_driver);
}
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c
index ab8209e7e45c..7e597d7f770f 100644
--- a/drivers/hid/hid-cherry.c
+++ b/drivers/hid/hid-cherry.c
@@ -70,12 +70,12 @@ static struct hid_driver ch_driver = {
.input_mapping = ch_input_mapping,
};
-static int ch_init(void)
+static int __init ch_init(void)
{
return hid_register_driver(&ch_driver);
}
-static void ch_exit(void)
+static void __exit ch_exit(void)
{
hid_unregister_driver(&ch_driver);
}
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
index 7f91076d8493..8965ad93d510 100644
--- a/drivers/hid/hid-chicony.c
+++ b/drivers/hid/hid-chicony.c
@@ -63,12 +63,12 @@ static struct hid_driver ch_driver = {
.input_mapping = ch_input_mapping,
};
-static int ch_init(void)
+static int __init ch_init(void)
{
return hid_register_driver(&ch_driver);
}
-static void ch_exit(void)
+static void __exit ch_exit(void)
{
hid_unregister_driver(&ch_driver);
}
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 86c2ff2429d8..342b7d36d7bb 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1072,8 +1072,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
*/
int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
{
- struct hid_report_enum *report_enum = hid->report_enum + type;
- struct hid_driver *hdrv = hid->driver;
+ struct hid_report_enum *report_enum;
+ struct hid_driver *hdrv;
struct hid_report *report;
char *buf;
unsigned int i;
@@ -1081,6 +1081,8 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
if (!hid || !hid->driver)
return -ENODEV;
+ report_enum = hid->report_enum + type;
+ hdrv = hid->driver;
if (!size) {
dbg_hid("empty report\n");
@@ -1308,6 +1310,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
@@ -1327,13 +1330,17 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ }
};
@@ -1636,12 +1643,8 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
@@ -1708,6 +1711,11 @@ static bool hid_ignore(struct hid_device *hdev)
hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST)
return true;
break;
+ case USB_VENDOR_ID_SOUNDGRAPH:
+ if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST &&
+ hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
+ return true;
+ break;
}
if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
index 9d6d3b91773b..62e9cb10e88c 100644
--- a/drivers/hid/hid-cypress.c
+++ b/drivers/hid/hid-cypress.c
@@ -141,12 +141,12 @@ static struct hid_driver cp_driver = {
.probe = cp_probe,
};
-static int cp_init(void)
+static int __init cp_init(void)
{
return hid_register_driver(&cp_driver);
}
-static void cp_exit(void)
+static void __exit cp_exit(void)
{
hid_unregister_driver(&cp_driver);
}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 06e87dc77796..6abd0369aedb 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -145,6 +145,14 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x44, "BarrelSwitch"},
{0, 0x45, "Eraser"},
{0, 0x46, "TabletPick"},
+ {0, 0x47, "Confidence"},
+ {0, 0x48, "Width"},
+ {0, 0x49, "Height"},
+ {0, 0x51, "ContactID"},
+ {0, 0x52, "InputMode"},
+ {0, 0x53, "DeviceIndex"},
+ {0, 0x54, "ContactCount"},
+ {0, 0x55, "ContactMaximumNumber"},
{ 15, 0, "PhysicalInterfaceDevice" },
{0, 0x00, "Undefined"},
{0, 0x01, "Physical_Interface_Device"},
@@ -592,9 +600,11 @@ static const char *events[EV_MAX + 1] = {
[EV_FF_STATUS] = "ForceFeedbackStatus",
};
-static const char *syncs[2] = {
+static const char *syncs[3] = {
[SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
+ [SYN_MT_REPORT] = "MT Report",
};
+
static const char *keys[KEY_MAX + 1] = {
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
@@ -812,8 +822,17 @@ static const char *absolutes[ABS_MAX + 1] = {
[ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
[ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
- [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
+ [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
[ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
+ [ABS_MT_TOUCH_MAJOR] = "MTMajor",
+ [ABS_MT_TOUCH_MINOR] = "MTMinor",
+ [ABS_MT_WIDTH_MAJOR] = "MTMajorW",
+ [ABS_MT_WIDTH_MINOR] = "MTMinorW",
+ [ABS_MT_ORIENTATION] = "MTOrientation",
+ [ABS_MT_POSITION_X] = "MTPositionX",
+ [ABS_MT_POSITION_Y] = "MTPositionY",
+ [ABS_MT_TOOL_TYPE] = "MTToolType",
+ [ABS_MT_BLOB_ID] = "MTBlobID",
};
static const char *misc[MSC_MAX + 1] = {
diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-drff.c
index 34f3eb65100b..a239d20ad7a5 100644
--- a/drivers/hid/hid-drff.c
+++ b/drivers/hid/hid-drff.c
@@ -32,6 +32,8 @@
#include <linux/hid.h>
#include "hid-ids.h"
+
+#ifdef CONFIG_DRAGONRISE_FF
#include "usbhid/usbhid.h"
struct drff_device {
@@ -135,6 +137,12 @@ static int drff_init(struct hid_device *hid)
return 0;
}
+#else
+static inline int drff_init(struct hid_device *hid)
+{
+ return 0;
+}
+#endif
static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c
index 0a1fe054799b..ca1163e9d42d 100644
--- a/drivers/hid/hid-ezkey.c
+++ b/drivers/hid/hid-ezkey.c
@@ -78,12 +78,12 @@ static struct hid_driver ez_driver = {
.event = ez_event,
};
-static int ez_init(void)
+static int __init ez_init(void)
{
return hid_register_driver(&ez_driver);
}
-static void ez_exit(void)
+static void __exit ez_exit(void)
{
hid_unregister_driver(&ez_driver);
}
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
index 510ad3ab8d33..8a11ccddaf2e 100644
--- a/drivers/hid/hid-gaff.c
+++ b/drivers/hid/hid-gaff.c
@@ -31,6 +31,8 @@
#include <linux/usb.h>
#include <linux/hid.h>
#include "hid-ids.h"
+
+#ifdef CONFIG_GREENASIA_FF
#include "usbhid/usbhid.h"
struct gaff_device {
@@ -130,6 +132,12 @@ static int gaff_init(struct hid_device *hid)
return 0;
}
+#else
+static inline int gaff_init(struct hid_device *hdev)
+{
+ return 0;
+}
+#endif
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
index d42d222097a8..cab13e8c7d29 100644
--- a/drivers/hid/hid-gyration.c
+++ b/drivers/hid/hid-gyration.c
@@ -81,12 +81,12 @@ static struct hid_driver gyration_driver = {
.event = gyration_event,
};
-static int gyration_init(void)
+static int __init gyration_init(void)
{
return hid_register_driver(&gyration_driver);
}
-static void gyration_exit(void)
+static void __exit gyration_exit(void)
{
hid_unregister_driver(&gyration_driver);
}
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 4d5ee2bbc62b..adbef5d069c4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -296,6 +296,7 @@
#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
+#define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
@@ -359,6 +360,9 @@
#define USB_VENDOR_ID_PETALYNX 0x18b1
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+#define USB_VENDOR_ID_PHILIPS 0x0471
+#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
+
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
@@ -376,11 +380,8 @@
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2 0x0036
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3 0x0034
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4 0x0044
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5 0x0045
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
#define USB_VENDOR_ID_SUN 0x0430
#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
@@ -403,6 +404,9 @@
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+#define USB_VENDOR_ID_TWINHAN 0x6253
+#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
+
#define USB_VENDOR_ID_UCLOGIC 0x5543
#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042
@@ -414,8 +418,10 @@
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_WACOM 0x056a
+#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
#define USB_VENDOR_ID_WISEGROUP 0x0925
+#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201
diff --git a/drivers/hid/hid-kensington.c b/drivers/hid/hid-kensington.c
index 7353bd79cbe9..a5b4016e9bd7 100644
--- a/drivers/hid/hid-kensington.c
+++ b/drivers/hid/hid-kensington.c
@@ -48,12 +48,12 @@ static struct hid_driver ks_driver = {
.input_mapping = ks_input_mapping,
};
-static int ks_init(void)
+static int __init ks_init(void)
{
return hid_register_driver(&ks_driver);
}
-static void ks_exit(void)
+static void __exit ks_exit(void)
{
hid_unregister_driver(&ks_driver);
}
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c
index 72ee3fec56d9..f8871712b7b5 100644
--- a/drivers/hid/hid-kye.c
+++ b/drivers/hid/hid-kye.c
@@ -54,12 +54,12 @@ static struct hid_driver kye_driver = {
.report_fixup = kye_report_fixup,
};
-static int kye_init(void)
+static int __init kye_init(void)
{
return hid_register_driver(&kye_driver);
}
-static void kye_exit(void)
+static void __exit kye_exit(void)
{
hid_unregister_driver(&kye_driver);
}
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 7afbaa0efd18..0f870a3243ed 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -299,6 +299,8 @@ static const struct hid_device_id lg_devices[] = {
.driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
.driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
+ .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
.driver_data = LG_FF2 },
{ }
@@ -315,12 +317,12 @@ static struct hid_driver lg_driver = {
.probe = lg_probe,
};
-static int lg_init(void)
+static int __init lg_init(void)
{
return hid_register_driver(&lg_driver);
}
-static void lg_exit(void)
+static void __exit lg_exit(void)
{
hid_unregister_driver(&lg_driver);
}
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index 51aff08e10ce..987abebe0829 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -50,6 +50,12 @@ static const signed short ff_joystick[] = {
-1
};
+static const signed short ff_joystick_ac[] = {
+ FF_CONSTANT,
+ FF_AUTOCENTER,
+ -1
+};
+
static const signed short ff_wheel[] = {
FF_CONSTANT,
FF_AUTOCENTER,
@@ -60,8 +66,9 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble },
{ 0x046d, 0xc283, ff_joystick },
- { 0x046d, 0xc286, ff_joystick },
- { 0x046d, 0xc294, ff_joystick },
+ { 0x046d, 0xc286, ff_joystick_ac },
+ { 0x046d, 0xc293, ff_joystick },
+ { 0x046d, 0xc294, ff_wheel },
{ 0x046d, 0xc295, ff_joystick },
{ 0x046d, 0xca03, ff_wheel },
};
@@ -144,11 +151,6 @@ int lgff_init(struct hid_device* hid)
/* Check that the report looks ok */
report = list_entry(report_list->next, struct hid_report, list);
- if (!report) {
- err_hid("NULL output report");
- return -1;
- }
-
field = report->field[0];
if (!field) {
err_hid("NULL field");
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 5e9e37a0506d..359cc447c6c6 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -197,12 +197,12 @@ static struct hid_driver ms_driver = {
.probe = ms_probe,
};
-static int ms_init(void)
+static int __init ms_init(void)
{
return hid_register_driver(&ms_driver);
}
-static void ms_exit(void)
+static void __exit ms_exit(void)
{
hid_unregister_driver(&ms_driver);
}
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c
index 240f87618be6..2cd05aa244b9 100644
--- a/drivers/hid/hid-monterey.c
+++ b/drivers/hid/hid-monterey.c
@@ -65,12 +65,12 @@ static struct hid_driver mr_driver = {
.input_mapping = mr_input_mapping,
};
-static int mr_init(void)
+static int __init mr_init(void)
{
return hid_register_driver(&mr_driver);
}
-static void mr_exit(void)
+static void __exit mr_exit(void)
{
hid_unregister_driver(&mr_driver);
}
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index c5b252be9c21..49ce69d7bba7 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -1,13 +1,8 @@
/*
- * HID driver for some ntrig "special" devices
+ * HID driver for N-Trig touchscreens
*
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2008 Rafi Rubin
+ * Copyright (c) 2009 Stephane Chatty
*
*/
@@ -29,15 +24,79 @@
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
+struct ntrig_data {
+ __s32 x, y, id, w, h;
+ char reading_a_point, found_contact_id;
+ char pen_active;
+ char finger_active;
+ char inverted;
+};
+
+/*
+ * this driver is aimed at two firmware versions in circulation:
+ * - dual pen/finger single touch
+ * - finger multitouch, pen not working
+ */
+
static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
- (usage->hid & 0xff) == 0x47) {
- nt_map_key_clear(BTN_TOOL_DOUBLETAP);
- return 1;
+ switch (usage->hid & HID_USAGE_PAGE) {
+
+ case HID_UP_GENDESK:
+ switch (usage->hid) {
+ case HID_GD_X:
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_POSITION_X);
+ input_set_abs_params(hi->input, ABS_X,
+ field->logical_minimum,
+ field->logical_maximum, 0, 0);
+ return 1;
+ case HID_GD_Y:
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(hi->input, ABS_Y,
+ field->logical_minimum,
+ field->logical_maximum, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case HID_UP_DIGITIZER:
+ switch (usage->hid) {
+ /* we do not want to map these for now */
+ case HID_DG_CONTACTID: /* value is useless */
+ case HID_DG_INPUTMODE:
+ case HID_DG_DEVICEINDEX:
+ case HID_DG_CONTACTCOUNT:
+ case HID_DG_CONTACTMAX:
+ return -1;
+
+ /* original mapping by Rafi Rubin */
+ case HID_DG_CONFIDENCE:
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+
+ /* width/height mapped on TouchMajor/TouchMinor/Orientation */
+ case HID_DG_WIDTH:
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_TOUCH_MAJOR);
+ return 1;
+ case HID_DG_HEIGHT:
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_TOUCH_MINOR);
+ input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+ 0, 1, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case 0xff000000:
+ /* we do not want to map these: no input-oriented meaning */
+ return -1;
}
+
return 0;
}
@@ -51,6 +110,163 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
+
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int ntrig_event (struct hid_device *hid, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct input_dev *input = field->hidinput->input;
+ struct ntrig_data *nd = hid_get_drvdata(hid);
+
+ if (hid->claimed & HID_CLAIMED_INPUT) {
+ switch (usage->hid) {
+
+ case HID_DG_INRANGE:
+ if (field->application & 0x3)
+ nd->pen_active = (value != 0);
+ else
+ nd->finger_active = (value != 0);
+ return 0;
+
+ case HID_DG_INVERT:
+ nd->inverted = value;
+ return 0;
+
+ case HID_GD_X:
+ nd->x = value;
+ nd->reading_a_point = 1;
+ break;
+ case HID_GD_Y:
+ nd->y = value;
+ break;
+ case HID_DG_CONTACTID:
+ nd->id = value;
+ /* we receive this only when in multitouch mode */
+ nd->found_contact_id = 1;
+ break;
+ case HID_DG_WIDTH:
+ nd->w = value;
+ break;
+ case HID_DG_HEIGHT:
+ nd->h = value;
+ /*
+ * when in single touch mode, this is the last
+ * report received in a finger event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (!nd->found_contact_id) {
+ if (nd->pen_active && nd->finger_active) {
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
+ }
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ /*
+ * when in single touch mode, this is the last
+ * report received in a pen event. We want
+ * to emit a normal (X, Y) position
+ */
+ if (! nd->found_contact_id) {
+ if (nd->pen_active && nd->finger_active) {
+ input_report_key(input,
+ nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
+ , 0);
+ input_report_key(input,
+ nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
+ , 1);
+ }
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ input_event(input, EV_ABS, ABS_PRESSURE, value);
+ }
+ break;
+ case 0xff000002:
+ /*
+ * we receive this when the device is in multitouch
+ * mode. The first of the three values tagged with
+ * this usage tells if the contact point is real
+ * or a placeholder
+ */
+ if (!nd->reading_a_point || value != 1)
+ break;
+ /* emit a normal (X, Y) for the first point only */
+ if (nd->id == 0) {
+ input_event(input, EV_ABS, ABS_X, nd->x);
+ input_event(input, EV_ABS, ABS_Y, nd->y);
+ }
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+ if (nd->w > nd->h) {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 1);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, nd->w);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, nd->h);
+ } else {
+ input_event(input, EV_ABS,
+ ABS_MT_ORIENTATION, 0);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MAJOR, nd->h);
+ input_event(input, EV_ABS,
+ ABS_MT_TOUCH_MINOR, nd->w);
+ }
+ input_mt_sync(field->hidinput->input);
+ nd->reading_a_point = 0;
+ nd->found_contact_id = 0;
+ break;
+
+ default:
+ /* fallback to the generic hidinput handling */
+ return 0;
+ }
+ }
+
+ /* we have handled the hidinput part, now remains hiddev */
+ if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+ hid->hiddev_hid_event(hid, field, usage, value);
+
+ return 1;
+}
+
+static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+ struct ntrig_data *nd;
+
+ nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
+ if (!nd) {
+ dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
+ return -ENOMEM;
+ }
+ nd->reading_a_point = 0;
+ nd->found_contact_id = 0;
+ hid_set_drvdata(hdev, nd);
+
+ ret = hid_parse(hdev);
+ if (!ret)
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+ if (ret)
+ kfree (nd);
+
+ return ret;
+}
+
+static void ntrig_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
static const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
@@ -58,19 +274,28 @@ static const struct hid_device_id ntrig_devices[] = {
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
+static const struct hid_usage_id ntrig_grabbed_usages[] = {
+ { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+ { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
static struct hid_driver ntrig_driver = {
.name = "ntrig",
.id_table = ntrig_devices,
+ .probe = ntrig_probe,
+ .remove = ntrig_remove,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
+ .usage_table = ntrig_grabbed_usages,
+ .event = ntrig_event,
};
-static int ntrig_init(void)
+static int __init ntrig_init(void)
{
return hid_register_driver(&ntrig_driver);
}
-static void ntrig_exit(void)
+static void __exit ntrig_exit(void)
{
hid_unregister_driver(&ntrig_driver);
}
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c
index 2e83e8ff891a..500fbd0652dc 100644
--- a/drivers/hid/hid-petalynx.c
+++ b/drivers/hid/hid-petalynx.c
@@ -105,12 +105,12 @@ static struct hid_driver pl_driver = {
.probe = pl_probe,
};
-static int pl_init(void)
+static int __init pl_init(void)
{
return hid_register_driver(&pl_driver);
}
-static void pl_exit(void)
+static void __exit pl_exit(void)
{
hid_unregister_driver(&pl_driver);
}
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
index 4db9a3483760..c6d7dbc935b1 100644
--- a/drivers/hid/hid-pl.c
+++ b/drivers/hid/hid-pl.c
@@ -217,12 +217,12 @@ static struct hid_driver pl_driver = {
.probe = pl_probe,
};
-static int pl_init(void)
+static int __init pl_init(void)
{
return hid_register_driver(&pl_driver);
}
-static void pl_exit(void)
+static void __exit pl_exit(void)
{
hid_unregister_driver(&pl_driver);
}
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c
index 07083aa6c19a..5b222eed0692 100644
--- a/drivers/hid/hid-samsung.c
+++ b/drivers/hid/hid-samsung.c
@@ -25,25 +25,48 @@
/*
* Samsung IrDA remote controller (reports as Cypress USB Mouse).
*
+ * There are several variants for 0419:0001:
+ *
+ * 1. 184 byte report descriptor
* Vendor specific report #4 has a size of 48 bit,
* and therefore is not accepted when inspecting the descriptors.
* As a workaround we reinterpret the report as:
* Variable type, count 6, size 8 bit, log. maximum 255
* The burden to reconstruct the data is moved into user space.
+ *
+ * 2. 203 byte report descriptor
+ * Report #4 has an array field with logical range 0..18 instead of 1..15.
+ *
+ * 3. 135 byte report descriptor
+ * Report #4 has an array field with logical range 0..17 instead of 1..14.
*/
static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
- if (rsize >= 182 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
+ if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
rdesc[182] == 0x40) {
- dev_info(&hdev->dev, "fixing up Samsung IrDA report "
- "descriptor\n");
+ dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
+ "descriptor\n", 184);
rdesc[176] = 0xff;
rdesc[178] = 0x08;
rdesc[180] = 0x06;
rdesc[182] = 0x42;
+ } else
+ if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 &&
+ rdesc[194] == 0x25 && rdesc[195] == 0x12) {
+ dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
+ "descriptor\n", 203);
+ rdesc[193] = 0x1;
+ rdesc[195] = 0xf;
+ } else
+ if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 &&
+ rdesc[126] == 0x25 && rdesc[127] == 0x11) {
+ dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
+ "descriptor\n", 135);
+ rdesc[125] = 0x1;
+ rdesc[127] = 0xe;
}
}
@@ -51,6 +74,7 @@ static int samsung_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int ret;
+ unsigned int cmask = HID_CONNECT_DEFAULT;
ret = hid_parse(hdev);
if (ret) {
@@ -58,8 +82,13 @@ static int samsung_probe(struct hid_device *hdev,
goto err_free;
}
- ret = hid_hw_start(hdev, (HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT) |
- HID_CONNECT_HIDDEV_FORCE);
+ if (hdev->rsize == 184) {
+ /* disable hidinput, force hiddev */
+ cmask = (cmask & ~HID_CONNECT_HIDINPUT) |
+ HID_CONNECT_HIDDEV_FORCE;
+ }
+
+ ret = hid_hw_start(hdev, cmask);
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err_free;
@@ -83,12 +112,12 @@ static struct hid_driver samsung_driver = {
.probe = samsung_probe,
};
-static int samsung_init(void)
+static int __init samsung_init(void)
{
return hid_register_driver(&samsung_driver);
}
-static void samsung_exit(void)
+static void __exit samsung_exit(void)
{
hid_unregister_driver(&samsung_driver);
}
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c
new file mode 100644
index 000000000000..203c438b016f
--- /dev/null
+++ b/drivers/hid/hid-sjoy.c
@@ -0,0 +1,180 @@
+/*
+ * Force feedback support for SmartJoy PLUS PS2->USB adapter
+ *
+ * Copyright (c) 2009 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * Based of hid-pl.c and hid-gaff.c
+ * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com>
+ * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
+ */
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define DEBUG */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "hid-ids.h"
+
+#ifdef CONFIG_SMARTJOYPLUS_FF
+#include "usbhid/usbhid.h"
+
+struct sjoyff_device {
+ struct hid_report *report;
+};
+
+static int hid_sjoyff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct sjoyff_device *sjoyff = data;
+ u32 left, right;
+
+ left = effect->u.rumble.strong_magnitude;
+ right = effect->u.rumble.weak_magnitude;
+ dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
+
+ left = left * 0xff / 0xffff;
+ right = (right != 0); /* on/off only */
+
+ sjoyff->report->field[0]->value[1] = right;
+ sjoyff->report->field[0]->value[2] = left;
+ dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
+ usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+
+ return 0;
+}
+
+static int sjoyff_init(struct hid_device *hid)
+{
+ struct sjoyff_device *sjoyff;
+ struct hid_report *report;
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+ struct hid_input, list);
+ struct list_head *report_list =
+ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct list_head *report_ptr = report_list;
+ struct input_dev *dev;
+ int error;
+
+ if (list_empty(report_list)) {
+ dev_err(&hid->dev, "no output reports found\n");
+ return -ENODEV;
+ }
+
+ report_ptr = report_ptr->next;
+
+ if (report_ptr == report_list) {
+ dev_err(&hid->dev, "required output report is "
+ "missing\n");
+ return -ENODEV;
+ }
+
+ report = list_entry(report_ptr, struct hid_report, list);
+ if (report->maxfield < 1) {
+ dev_err(&hid->dev, "no fields in the report\n");
+ return -ENODEV;
+ }
+
+ if (report->field[0]->report_count < 3) {
+ dev_err(&hid->dev, "not enough values in the field\n");
+ return -ENODEV;
+ }
+
+ sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
+ if (!sjoyff)
+ return -ENOMEM;
+
+ dev = hidinput->input;
+
+ set_bit(FF_RUMBLE, dev->ffbit);
+
+ error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+ if (error) {
+ kfree(sjoyff);
+ return error;
+ }
+
+ sjoyff->report = report;
+ sjoyff->report->field[0]->value[0] = 0x01;
+ sjoyff->report->field[0]->value[1] = 0x00;
+ sjoyff->report->field[0]->value[2] = 0x00;
+ usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+
+ dev_info(&hid->dev,
+ "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
+
+ return 0;
+}
+#else
+static inline int sjoyff_init(struct hid_device *hid)
+{
+ return 0;
+}
+#endif
+
+static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ sjoyff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id sjoy_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, sjoy_devices);
+
+static struct hid_driver sjoy_driver = {
+ .name = "smartjoyplus",
+ .id_table = sjoy_devices,
+ .probe = sjoy_probe,
+};
+
+static int __init sjoy_init(void)
+{
+ return hid_register_driver(&sjoy_driver);
+}
+
+static void __exit sjoy_exit(void)
+{
+ hid_unregister_driver(&sjoy_driver);
+}
+
+module_init(sjoy_init);
+module_exit(sjoy_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jussi Kivilinna");
+
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index c2599388a350..4e8450228a24 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -135,12 +135,12 @@ static struct hid_driver sony_driver = {
.report_fixup = sony_report_fixup,
};
-static int sony_init(void)
+static int __init sony_init(void)
{
return hid_register_driver(&sony_driver);
}
-static void sony_exit(void)
+static void __exit sony_exit(void)
{
hid_unregister_driver(&sony_driver);
}
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c
index e0a8fd36a85b..438107d9f1b2 100644
--- a/drivers/hid/hid-sunplus.c
+++ b/drivers/hid/hid-sunplus.c
@@ -65,12 +65,12 @@ static struct hid_driver sp_driver = {
.input_mapping = sp_input_mapping,
};
-static int sp_init(void)
+static int __init sp_init(void)
{
return hid_register_driver(&sp_driver);
}
-static void sp_exit(void)
+static void __exit sp_exit(void)
{
hid_unregister_driver(&sp_driver);
}
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index 7c1f7b50330c..167ea746fb9c 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -33,11 +33,6 @@
#include "hid-ids.h"
-#include "usbhid/usbhid.h"
-
-/* Usages for thrustmaster devices I know about */
-#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
-
static const signed short ff_rumble[] = {
FF_RUMBLE,
-1
@@ -48,6 +43,12 @@ static const signed short ff_joystick[] = {
-1
};
+#ifdef CONFIG_THRUSTMASTER_FF
+#include "usbhid/usbhid.h"
+
+/* Usages for thrustmaster devices I know about */
+#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
+
struct tmff_device {
struct hid_report *report;
struct hid_field *ff_field;
@@ -209,6 +210,12 @@ fail:
kfree(tmff);
return error;
}
+#else
+static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits)
+{
+ return 0;
+}
+#endif
static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
@@ -236,7 +243,11 @@ err:
static const struct hid_device_id tm_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300),
.driver_data = (unsigned long)ff_rumble },
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), /* FireStorm Dual Power 2 (and 3) */
+ .driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323), /* Dual Trigger 3-in-1 (PC Mode) */
+ .driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324), /* Dual Trigger 3-in-1 (PS3 Mode) */
.driver_data = (unsigned long)ff_rumble },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651), /* FGT Rumble Force Wheel */
.driver_data = (unsigned long)ff_rumble },
@@ -252,12 +263,12 @@ static struct hid_driver tm_driver = {
.probe = tm_probe,
};
-static int tm_init(void)
+static int __init tm_init(void)
{
return hid_register_driver(&tm_driver);
}
-static void tm_exit(void)
+static void __exit tm_exit(void)
{
hid_unregister_driver(&tm_driver);
}
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c
index 152ccfabeba5..6925eda1081a 100644
--- a/drivers/hid/hid-topseed.c
+++ b/drivers/hid/hid-topseed.c
@@ -60,12 +60,12 @@ static struct hid_driver ts_driver = {
.input_mapping = ts_input_mapping,
};
-static int ts_init(void)
+static int __init ts_init(void)
{
return hid_register_driver(&ts_driver);
}
-static void ts_exit(void)
+static void __exit ts_exit(void)
{
hid_unregister_driver(&ts_driver);
}
diff --git a/drivers/hid/hid-twinhan.c b/drivers/hid/hid-twinhan.c
new file mode 100644
index 000000000000..b05f602c051e
--- /dev/null
+++ b/drivers/hid/hid-twinhan.c
@@ -0,0 +1,147 @@
+/*
+ * HID driver for TwinHan IR remote control
+ *
+ * Based on hid-gyration.c
+ *
+ * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org>
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Remote control key layout + listing:
+ *
+ * Full Screen Power
+ * KEY_SCREEN KEY_POWER2
+ *
+ * 1 2 3
+ * KEY_NUMERIC_1 KEY_NUMERIC_2 KEY_NUMERIC_3
+ *
+ * 4 5 6
+ * KEY_NUMERIC_4 KEY_NUMERIC_5 KEY_NUMERIC_6
+ *
+ * 7 8 9
+ * KEY_NUMERIC_7 KEY_NUMERIC_8 KEY_NUMERIC_9
+ *
+ * REC 0 Favorite
+ * KEY_RECORD KEY_NUMERIC_0 KEY_FAVORITES
+ *
+ * Rewind Forward
+ * KEY_REWIND CH+ KEY_FORWARD
+ * KEY_CHANNELUP
+ *
+ * VOL- > VOL+
+ * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP
+ *
+ * CH-
+ * KEY_CHANNELDOWN
+ * Recall Stop
+ * KEY_RESTART KEY_STOP
+ *
+ * Timeshift/Pause Mute Cancel
+ * KEY_PAUSE KEY_MUTE KEY_CANCEL
+ *
+ * Capture Preview EPG
+ * KEY_PRINT KEY_PROGRAM KEY_EPG
+ *
+ * Record List Tab Teletext
+ * KEY_LIST KEY_TAB KEY_TEXT
+ */
+
+#define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ /* Map all keys from Twinhan Remote */
+ case 0x004: th_map_key_clear(KEY_TEXT); break;
+ case 0x006: th_map_key_clear(KEY_RESTART); break;
+ case 0x008: th_map_key_clear(KEY_EPG); break;
+ case 0x00c: th_map_key_clear(KEY_REWIND); break;
+ case 0x00e: th_map_key_clear(KEY_PROGRAM); break;
+ case 0x00f: th_map_key_clear(KEY_LIST); break;
+ case 0x010: th_map_key_clear(KEY_MUTE); break;
+ case 0x011: th_map_key_clear(KEY_FORWARD); break;
+ case 0x013: th_map_key_clear(KEY_PRINT); break;
+ case 0x017: th_map_key_clear(KEY_PAUSE); break;
+ case 0x019: th_map_key_clear(KEY_FAVORITES); break;
+ case 0x01d: th_map_key_clear(KEY_SCREEN); break;
+ case 0x01e: th_map_key_clear(KEY_NUMERIC_1); break;
+ case 0x01f: th_map_key_clear(KEY_NUMERIC_2); break;
+ case 0x020: th_map_key_clear(KEY_NUMERIC_3); break;
+ case 0x021: th_map_key_clear(KEY_NUMERIC_4); break;
+ case 0x022: th_map_key_clear(KEY_NUMERIC_5); break;
+ case 0x023: th_map_key_clear(KEY_NUMERIC_6); break;
+ case 0x024: th_map_key_clear(KEY_NUMERIC_7); break;
+ case 0x025: th_map_key_clear(KEY_NUMERIC_8); break;
+ case 0x026: th_map_key_clear(KEY_NUMERIC_9); break;
+ case 0x027: th_map_key_clear(KEY_NUMERIC_0); break;
+ case 0x028: th_map_key_clear(KEY_PLAY); break;
+ case 0x029: th_map_key_clear(KEY_CANCEL); break;
+ case 0x02b: th_map_key_clear(KEY_TAB); break;
+ /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */
+ case 0x03f: th_map_key_clear(KEY_POWER2); break;
+ case 0x04a: th_map_key_clear(KEY_RECORD); break;
+ case 0x04b: th_map_key_clear(KEY_CHANNELUP); break;
+ case 0x04d: th_map_key_clear(KEY_STOP); break;
+ case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break;
+ /* Volume down = 0x0e1 + 0x051 */
+ case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break;
+ /* Volume up = 0x0e1 + 0x052 */
+ case 0x052: th_map_key_clear(KEY_VOLUMEUP); break;
+ /* Kill the extra keys used for multi-key "power" and "volume" keys
+ * as well as continuously to release CTRL,ALT,META,... keys */
+ case 0x0e0:
+ case 0x0e1:
+ case 0x0e2:
+ case 0x0e3:
+ case 0x0e4:
+ case 0x0e5:
+ case 0x0e6:
+ case 0x0e7:
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+static const struct hid_device_id twinhan_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, twinhan_devices);
+
+static struct hid_driver twinhan_driver = {
+ .name = "twinhan",
+ .id_table = twinhan_devices,
+ .input_mapping = twinhan_input_mapping,
+};
+
+static int twinhan_init(void)
+{
+ return hid_register_driver(&twinhan_driver);
+}
+
+static void twinhan_exit(void)
+{
+ hid_unregister_driver(&twinhan_driver);
+}
+
+module_init(twinhan_init);
+module_exit(twinhan_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
new file mode 100644
index 000000000000..747542172242
--- /dev/null
+++ b/drivers/hid/hid-wacom.c
@@ -0,0 +1,259 @@
+/*
+ * Bluetooth Wacom Tablet support
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
+ * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
+ */
+
+/*
+ * 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"
+
+struct wacom_data {
+ __u16 tool;
+ unsigned char butstate;
+};
+
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
+{
+ struct wacom_data *wdata = hid_get_drvdata(hdev);
+ struct hid_input *hidinput;
+ struct input_dev *input;
+ unsigned char *data = (unsigned char *) raw_data;
+ int tool, x, y, rw;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT))
+ return 0;
+
+ tool = 0;
+ hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+ input = hidinput->input;
+
+ /* Check if this is a tablet report */
+ if (data[0] != 0x03)
+ return 0;
+
+ /* Get X & Y positions */
+ x = le16_to_cpu(*(__le16 *) &data[2]);
+ y = le16_to_cpu(*(__le16 *) &data[4]);
+
+ /* Get current tool identifier */
+ if (data[1] & 0x90) { /* If pen is in the in/active area */
+ switch ((data[1] >> 5) & 3) {
+ case 0: /* Pen */
+ tool = BTN_TOOL_PEN;
+ break;
+
+ case 1: /* Rubber */
+ tool = BTN_TOOL_RUBBER;
+ break;
+
+ case 2: /* Mouse with wheel */
+ case 3: /* Mouse without wheel */
+ tool = BTN_TOOL_MOUSE;
+ break;
+ }
+
+ /* Reset tool if out of active tablet area */
+ if (!(data[1] & 0x10))
+ tool = 0;
+ }
+
+ /* If tool changed, notify input subsystem */
+ if (wdata->tool != tool) {
+ if (wdata->tool) {
+ /* Completely reset old tool state */
+ if (wdata->tool == BTN_TOOL_MOUSE) {
+ input_report_key(input, BTN_LEFT, 0);
+ input_report_key(input, BTN_RIGHT, 0);
+ input_report_key(input, BTN_MIDDLE, 0);
+ input_report_abs(input, ABS_DISTANCE,
+ input->absmax[ABS_DISTANCE]);
+ } else {
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_key(input, BTN_STYLUS, 0);
+ input_report_key(input, BTN_STYLUS2, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ }
+ input_report_key(input, wdata->tool, 0);
+ input_sync(input);
+ }
+ wdata->tool = tool;
+ if (tool)
+ input_report_key(input, tool, 1);
+ }
+
+ if (tool) {
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+
+ switch ((data[1] >> 5) & 3) {
+ case 2: /* Mouse with wheel */
+ input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
+ rw = (data[6] & 0x01) ? -1 :
+ (data[6] & 0x02) ? 1 : 0;
+ input_report_rel(input, REL_WHEEL, rw);
+ /* fall through */
+
+ case 3: /* Mouse without wheel */
+ input_report_key(input, BTN_LEFT, data[1] & 0x01);
+ input_report_key(input, BTN_RIGHT, data[1] & 0x02);
+ /* Compute distance between mouse and tablet */
+ rw = 44 - (data[6] >> 2);
+ if (rw < 0)
+ rw = 0;
+ else if (rw > 31)
+ rw = 31;
+ input_report_abs(input, ABS_DISTANCE, rw);
+ break;
+
+ default:
+ input_report_abs(input, ABS_PRESSURE,
+ data[6] | (((__u16) (data[1] & 0x08)) << 5));
+ input_report_key(input, BTN_TOUCH, data[1] & 0x01);
+ input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+ input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
+ break;
+ }
+
+ input_sync(input);
+ }
+
+ /* Report the state of the two buttons at the top of the tablet
+ * as two extra fingerpad keys (buttons 4 & 5). */
+ rw = data[7] & 0x03;
+ if (rw != wdata->butstate) {
+ wdata->butstate = rw;
+ input_report_key(input, BTN_0, rw & 0x02);
+ input_report_key(input, BTN_1, rw & 0x01);
+ input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+ input_sync(input);
+ }
+
+ return 1;
+}
+
+static int wacom_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ struct hid_input *hidinput;
+ struct input_dev *input;
+ struct wacom_data *wdata;
+ int ret;
+
+ wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
+ if (wdata == NULL) {
+ dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
+ return -ENOMEM;
+ }
+
+ hid_set_drvdata(hdev, wdata);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+ input = hidinput->input;
+
+ /* Basics */
+ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+ input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
+ BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+ input->relbit[0] |= BIT(REL_WHEEL);
+ set_bit(BTN_TOOL_PEN, input->keybit);
+ set_bit(BTN_TOUCH, input->keybit);
+ set_bit(BTN_STYLUS, input->keybit);
+ set_bit(BTN_STYLUS2, input->keybit);
+ set_bit(BTN_LEFT, input->keybit);
+ set_bit(BTN_RIGHT, input->keybit);
+ set_bit(BTN_MIDDLE, input->keybit);
+
+ /* Pad */
+ input->evbit[0] |= BIT(EV_MSC);
+ input->mscbit[0] |= BIT(MSC_SERIAL);
+
+ /* Distance, rubber and mouse */
+ input->absbit[0] |= BIT(ABS_DISTANCE);
+ set_bit(BTN_TOOL_RUBBER, input->keybit);
+ set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+ input->absmax[ABS_PRESSURE] = 511;
+ input->absmax[ABS_DISTANCE] = 32;
+
+ input->absmax[ABS_X] = 16704;
+ input->absmax[ABS_Y] = 12064;
+ input->absfuzz[ABS_X] = 4;
+ input->absfuzz[ABS_Y] = 4;
+
+ return 0;
+err_free:
+ kfree(wdata);
+ return ret;
+}
+
+static void wacom_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
+static const struct hid_device_id wacom_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, wacom_devices);
+
+static struct hid_driver wacom_driver = {
+ .name = "wacom",
+ .id_table = wacom_devices,
+ .probe = wacom_probe,
+ .remove = wacom_remove,
+ .raw_event = wacom_raw_event,
+};
+
+static int __init wacom_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&wacom_driver);
+ if (ret)
+ printk(KERN_ERR "can't register wacom driver\n");
+ printk(KERN_ERR "wacom driver registered\n");
+ return ret;
+}
+
+static void __exit wacom_exit(void)
+{
+ hid_unregister_driver(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
index 85a198a18537..a79f0d78c6be 100644
--- a/drivers/hid/hid-zpff.c
+++ b/drivers/hid/hid-zpff.c
@@ -27,6 +27,7 @@
#include "hid-ids.h"
+#ifdef CONFIG_ZEROPLUS_FF
#include "usbhid/usbhid.h"
struct zpff_device {
@@ -108,6 +109,12 @@ static int zpff_init(struct hid_device *hid)
return 0;
}
+#else
+static inline int zpff_init(struct hid_device *hid)
+{
+ return 0;
+}
+#endif
static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
@@ -145,12 +152,12 @@ static struct hid_driver zp_driver = {
.probe = zp_probe,
};
-static int zp_init(void)
+static int __init zp_init(void)
{
return hid_register_driver(&zp_driver);
}
-static void zp_exit(void)
+static void __exit zp_exit(void)
{
hid_unregister_driver(&zp_driver);
}
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 00ccf4b1985d..0c6639ea03dd 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -349,10 +349,7 @@ int hidraw_connect(struct hid_device *hid)
int minor, result;
struct hidraw *dev;
- /* TODO currently we accept any HID device. This should later
- * probably be fixed to accept only those devices which provide
- * non-input applications
- */
+ /* we accept any HID device, no matter the applications */
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
if (!dev)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 708aa52d0753..1b0e07a67d6d 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -22,7 +22,6 @@
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
@@ -490,7 +489,8 @@ static void hid_ctrl(struct urb *urb)
wake_up(&usbhid->wait);
}
-void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report,
+ unsigned char dir)
{
int head;
struct usbhid_device *usbhid = hid->driver_data;
@@ -982,7 +982,6 @@ static int usbhid_start(struct hid_device *hid)
setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
spin_lock_init(&usbhid->lock);
- spin_lock_init(&usbhid->lock);
usbhid->intf = intf;
usbhid->ifnum = interface->desc.bInterfaceNumber;
@@ -1228,12 +1227,11 @@ static int hid_post_reset(struct usb_interface *intf)
struct hid_device *hid = usb_get_intfdata(intf);
struct usbhid_device *usbhid = hid->driver_data;
int status;
-
+
spin_lock_irq(&usbhid->lock);
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock);
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
- /* FIXME: Any more reinitialization needed? */
status = hid_start_in(hid);
if (status < 0)
hid_io_error(hid);
@@ -1245,14 +1243,14 @@ static int hid_post_reset(struct usb_interface *intf)
int usbhid_get_power(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
-
+
return usb_autopm_get_interface(usbhid->intf);
}
void usbhid_put_power(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
-
+
usb_autopm_put_interface(usbhid->intf);
}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index d8f7423f363e..0d9045aa2c4b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -201,7 +201,7 @@ int usbhid_quirks_init(char **quirks_param)
u32 quirks;
int n = 0, m;
- for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+ for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) {
m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
&idVendor, &idProduct, &quirks);
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index e9b436d2d944..4d1dc0cf1401 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -44,7 +44,7 @@
#define HIDDEV_MINOR_BASE 96
#define HIDDEV_MINORS 16
#endif
-#define HIDDEV_BUFFER_SIZE 64
+#define HIDDEV_BUFFER_SIZE 2048
struct hiddev {
int exist;
@@ -527,8 +527,10 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
goto goodreturn;
case HIDIOCGCOLLECTIONINDEX:
+ i = field->usage[uref->usage_index].collection_index;
+ unlock_kernel();
kfree(uref_multi);
- return field->usage[uref->usage_index].collection_index;
+ return i;
case HIDIOCGUSAGES:
for (i = 0; i < uref_multi->num_values; i++)
uref_multi->values[i] =
@@ -850,8 +852,14 @@ static const struct file_operations hiddev_fops = {
#endif
};
+static char *hiddev_nodename(struct device *dev)
+{
+ return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
+}
+
static struct usb_class_driver hiddev_class = {
.name = "hiddev%d",
+ .nodename = hiddev_nodename,
.fops = &hiddev_fops,
.minor_base = HIDDEV_MINOR_BASE,
};
@@ -955,7 +963,6 @@ static int hiddev_usbd_probe(struct usb_interface *intf,
return -ENODEV;
}
-
static /* const */ struct usb_driver hiddev_driver = {
.name = "hiddev",
.probe = hiddev_usbd_probe,