aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 12:03:42 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 12:03:42 -0400
commit52d4e661ac92ab8e1a312fe527221a1311fe4cda (patch)
tree907f37beba526bac7dcffbef7253de3b445a2c1e
parentf248488b397d52717f6683e2e53200aa687ffc89 (diff)
parentd057fd4cb892087955568a139d15eae4115a0174 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (21 commits) HID: hidraw_connect() memleak fix HID: add hidraw interface USB HID: provide hook for hidraw write() HID: hiddev: Add 32bit ioctl compatibilty HID: Add GeneralTouch touchscreen to the blacklist HID: add support for Microsoft Wireless Laser Keyboard 6000 Input: add KEY_LOGOFF USBHID: report descriptor fix for MacBook JIS keyboard HID: trivial fixes in hid-debug HID: fix input mapping for Microsoft Ergonomic Keyboard HID: use hid-plff driver for GreenAsia 0e8f:0003 devices USBHID: Add HID_QUIRK_NOGET for ELO Touch Screen 2700 display HID: enable hiddev for the SantaRosa MacBookPro IR receiver USBHID: add CM109 device to blacklist HID: Report usage codes of keys as EV_MSC scancode events HID: ignore all non-LED usages in output fields in hid-input HID: fix whitespace damage HID: add support for Thrustmaster FGT Force Feedback wheel HID: minimal autosuspend support for USB HID devices HID: add support for Microsoft Natural Ergonomic Keyboard 4000 ...
-rw-r--r--drivers/hid/Kconfig19
-rw-r--r--drivers/hid/Makefile2
-rw-r--r--drivers/hid/hid-core.c16
-rw-r--r--drivers/hid/hid-debug.c40
-rw-r--r--drivers/hid/hid-input.c92
-rw-r--r--drivers/hid/hidraw.c401
-rw-r--r--drivers/hid/usbhid/Kconfig11
-rw-r--r--drivers/hid/usbhid/hid-core.c54
-rw-r--r--drivers/hid/usbhid/hid-ff.c5
-rw-r--r--drivers/hid/usbhid/hid-plff.c24
-rw-r--r--drivers/hid/usbhid/hid-quirks.c33
-rw-r--r--drivers/hid/usbhid/hid-tmff.c161
-rw-r--r--drivers/hid/usbhid/hiddev.c12
-rw-r--r--include/linux/hid.h7
-rw-r--r--include/linux/hidraw.h86
-rw-r--r--include/linux/input.h2
16 files changed, 877 insertions, 88 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 19667fcc722a..cacf89e65af4 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -46,6 +46,25 @@ config HID_DEBUG
46 46
47 If unsure, say N 47 If unsure, say N
48 48
49config HIDRAW
50 bool "/dev/hidraw raw HID device support"
51 depends on HID
52 ---help---
53 Say Y here if you want to support HID devices (from the USB
54 specification standpoint) that aren't strictly user interface
55 devices, like monitor controls and Uninterruptable Power Supplies.
56
57 This module supports these devices separately using a separate
58 event interface on /dev/hidraw.
59
60 There is also a /dev/hiddev configuration option in the USB HID
61 configuration menu. In comparison to hiddev, this device does not process
62 the hid events at all (no parsing, no lookups). This lets applications
63 to work on raw hid events when they want to, and avoid using transport-specific
64 userspace libhid/libusb libraries.
65
66 If unsure, say Y.
67
49source "drivers/hid/usbhid/Kconfig" 68source "drivers/hid/usbhid/Kconfig"
50 69
51endif # HID_SUPPORT 70endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 68d1376a53fb..1ac5103f7c93 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -4,7 +4,9 @@
4hid-objs := hid-core.o hid-input.o 4hid-objs := hid-core.o hid-input.o
5 5
6obj-$(CONFIG_HID) += hid.o 6obj-$(CONFIG_HID) += hid.o
7
7hid-$(CONFIG_HID_DEBUG) += hid-debug.o 8hid-$(CONFIG_HID_DEBUG) += hid-debug.o
9hid-$(CONFIG_HIDRAW) += hidraw.o
8 10
9obj-$(CONFIG_USB_HID) += usbhid/ 11obj-$(CONFIG_USB_HID) += usbhid/
10obj-$(CONFIG_USB_MOUSE) += usbhid/ 12obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 317cf8a7b63c..2884b036495a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -30,6 +30,7 @@
30#include <linux/hid.h> 30#include <linux/hid.h>
31#include <linux/hiddev.h> 31#include <linux/hiddev.h>
32#include <linux/hid-debug.h> 32#include <linux/hid-debug.h>
33#include <linux/hidraw.h>
33 34
34/* 35/*
35 * Version Information 36 * Version Information
@@ -979,6 +980,8 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
979 980
980 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) 981 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
981 hid->hiddev_report_event(hid, report); 982 hid->hiddev_report_event(hid, report);
983 if (hid->claimed & HID_CLAIMED_HIDRAW)
984 hidraw_report_event(hid, data, size);
982 985
983 for (n = 0; n < report->maxfield; n++) 986 for (n = 0; n < report->maxfield; n++)
984 hid_input_field(hid, report->field[n], data, interrupt); 987 hid_input_field(hid, report->field[n], data, interrupt);
@@ -990,5 +993,18 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
990} 993}
991EXPORT_SYMBOL_GPL(hid_input_report); 994EXPORT_SYMBOL_GPL(hid_input_report);
992 995
996static int __init hid_init(void)
997{
998 return hidraw_init();
999}
1000
1001static void __exit hid_exit(void)
1002{
1003 hidraw_exit();
1004}
1005
1006module_init(hid_init);
1007module_exit(hid_exit);
1008
993MODULE_LICENSE(DRIVER_LICENSE); 1009MODULE_LICENSE(DRIVER_LICENSE);
994 1010
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index a13757b78980..5c24fe46d8eb 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -34,7 +34,7 @@
34struct hid_usage_entry { 34struct hid_usage_entry {
35 unsigned page; 35 unsigned page;
36 unsigned usage; 36 unsigned usage;
37 char *description; 37 const char *description;
38}; 38};
39 39
40static const struct hid_usage_entry hid_usage_table[] = { 40static const struct hid_usage_entry hid_usage_table[] = {
@@ -365,8 +365,8 @@ void hid_resolv_usage(unsigned usage) {
365} 365}
366EXPORT_SYMBOL_GPL(hid_resolv_usage); 366EXPORT_SYMBOL_GPL(hid_resolv_usage);
367 367
368__inline__ static void tab(int n) { 368static void tab(int n) {
369 while (n--) printk(" "); 369 printk(KERN_DEBUG "%*s", n, "");
370} 370}
371 371
372void hid_dump_field(struct hid_field *field, int n) { 372void hid_dump_field(struct hid_field *field, int n) {
@@ -401,8 +401,8 @@ void hid_dump_field(struct hid_field *field, int n) {
401 tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); 401 tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
402 } 402 }
403 if (field->unit) { 403 if (field->unit) {
404 char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; 404 static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
405 char *units[5][8] = { 405 static const char *units[5][8] = {
406 { "None", "None", "None", "None", "None", "None", "None", "None" }, 406 { "None", "None", "None", "None", "None", "None", "None", "None" },
407 { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, 407 { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
408 { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, 408 { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
@@ -457,7 +457,7 @@ void hid_dump_field(struct hid_field *field, int n) {
457 printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); 457 printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
458 printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); 458 printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
459 printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); 459 printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
460 printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); 460 printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : "");
461 printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); 461 printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
462 printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); 462 printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
463 printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); 463 printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
@@ -470,7 +470,7 @@ void hid_dump_device(struct hid_device *device) {
470 struct hid_report *report; 470 struct hid_report *report;
471 struct list_head *list; 471 struct list_head *list;
472 unsigned i,k; 472 unsigned i,k;
473 static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; 473 static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
474 474
475 if (!hid_debug) 475 if (!hid_debug)
476 return; 476 return;
@@ -501,13 +501,13 @@ void hid_dump_input(struct hid_usage *usage, __s32 value) {
501 if (!hid_debug) 501 if (!hid_debug)
502 return; 502 return;
503 503
504 printk("hid-debug: input "); 504 printk(KERN_DEBUG "hid-debug: input ");
505 hid_resolv_usage(usage->hid); 505 hid_resolv_usage(usage->hid);
506 printk(" = %d\n", value); 506 printk(" = %d\n", value);
507} 507}
508EXPORT_SYMBOL_GPL(hid_dump_input); 508EXPORT_SYMBOL_GPL(hid_dump_input);
509 509
510static char *events[EV_MAX + 1] = { 510static const char *events[EV_MAX + 1] = {
511 [EV_SYN] = "Sync", [EV_KEY] = "Key", 511 [EV_SYN] = "Sync", [EV_KEY] = "Key",
512 [EV_REL] = "Relative", [EV_ABS] = "Absolute", 512 [EV_REL] = "Relative", [EV_ABS] = "Absolute",
513 [EV_MSC] = "Misc", [EV_LED] = "LED", 513 [EV_MSC] = "Misc", [EV_LED] = "LED",
@@ -516,10 +516,10 @@ static char *events[EV_MAX + 1] = {
516 [EV_FF_STATUS] = "ForceFeedbackStatus", 516 [EV_FF_STATUS] = "ForceFeedbackStatus",
517}; 517};
518 518
519static char *syncs[2] = { 519static const char *syncs[2] = {
520 [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", 520 [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
521}; 521};
522static char *keys[KEY_MAX + 1] = { 522static const char *keys[KEY_MAX + 1] = {
523 [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", 523 [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
524 [KEY_1] = "1", [KEY_2] = "2", 524 [KEY_1] = "1", [KEY_2] = "2",
525 [KEY_3] = "3", [KEY_4] = "4", 525 [KEY_3] = "3", [KEY_4] = "4",
@@ -697,7 +697,8 @@ static char *keys[KEY_MAX + 1] = {
697 [KEY_DEL_LINE] = "DeleteLine", 697 [KEY_DEL_LINE] = "DeleteLine",
698 [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", 698 [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
699 [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", 699 [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
700 [KEY_DOCUMENTS] = "Documents", 700 [KEY_DOCUMENTS] = "Documents", [KEY_SPELLCHECK] = "SpellCheck",
701 [KEY_LOGOFF] = "Logoff",
701 [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", 702 [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
702 [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", 703 [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
703 [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", 704 [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
@@ -715,7 +716,7 @@ static char *keys[KEY_MAX + 1] = {
715 [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", 716 [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
716}; 717};
717 718
718static char *relatives[REL_MAX + 1] = { 719static const char *relatives[REL_MAX + 1] = {
719 [REL_X] = "X", [REL_Y] = "Y", 720 [REL_X] = "X", [REL_Y] = "Y",
720 [REL_Z] = "Z", [REL_RX] = "Rx", 721 [REL_Z] = "Z", [REL_RX] = "Rx",
721 [REL_RY] = "Ry", [REL_RZ] = "Rz", 722 [REL_RY] = "Ry", [REL_RZ] = "Rz",
@@ -723,7 +724,7 @@ static char *relatives[REL_MAX + 1] = {
723 [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", 724 [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
724}; 725};
725 726
726static char *absolutes[ABS_MAX + 1] = { 727static const char *absolutes[ABS_MAX + 1] = {
727 [ABS_X] = "X", [ABS_Y] = "Y", 728 [ABS_X] = "X", [ABS_Y] = "Y",
728 [ABS_Z] = "Z", [ABS_RX] = "Rx", 729 [ABS_Z] = "Z", [ABS_RX] = "Rx",
729 [ABS_RY] = "Ry", [ABS_RZ] = "Rz", 730 [ABS_RY] = "Ry", [ABS_RZ] = "Rz",
@@ -739,12 +740,12 @@ static char *absolutes[ABS_MAX + 1] = {
739 [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", 740 [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
740}; 741};
741 742
742static char *misc[MSC_MAX + 1] = { 743static const char *misc[MSC_MAX + 1] = {
743 [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", 744 [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
744 [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" 745 [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData"
745}; 746};
746 747
747static char *leds[LED_MAX + 1] = { 748static const char *leds[LED_MAX + 1] = {
748 [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", 749 [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
749 [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", 750 [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
750 [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", 751 [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
@@ -752,16 +753,16 @@ static char *leds[LED_MAX + 1] = {
752 [LED_MISC] = "Misc", 753 [LED_MISC] = "Misc",
753}; 754};
754 755
755static char *repeats[REP_MAX + 1] = { 756static const char *repeats[REP_MAX + 1] = {
756 [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" 757 [REP_DELAY] = "Delay", [REP_PERIOD] = "Period"
757}; 758};
758 759
759static char *sounds[SND_MAX + 1] = { 760static const char *sounds[SND_MAX + 1] = {
760 [SND_CLICK] = "Click", [SND_BELL] = "Bell", 761 [SND_CLICK] = "Click", [SND_BELL] = "Bell",
761 [SND_TONE] = "Tone" 762 [SND_TONE] = "Tone"
762}; 763};
763 764
764static char **names[EV_MAX + 1] = { 765static const char **names[EV_MAX + 1] = {
765 [EV_SYN] = syncs, [EV_KEY] = keys, 766 [EV_SYN] = syncs, [EV_KEY] = keys,
766 [EV_REL] = relatives, [EV_ABS] = absolutes, 767 [EV_REL] = relatives, [EV_ABS] = absolutes,
767 [EV_MSC] = misc, [EV_LED] = leds, 768 [EV_MSC] = misc, [EV_LED] = leds,
@@ -777,4 +778,3 @@ void hid_resolv_event(__u8 type, __u16 code) {
777 names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); 778 names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
778} 779}
779EXPORT_SYMBOL_GPL(hid_resolv_event); 780EXPORT_SYMBOL_GPL(hid_resolv_event);
780
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 8edbd30cf795..0c3e12c1794c 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -53,7 +53,7 @@ static const unsigned char hid_keyboard[256] = {
53 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, 53 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
54 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 54 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
55 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 55 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
56 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 56 unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
57 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 57 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
58 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 58 unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
59 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 59 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
@@ -86,6 +86,10 @@ static const struct {
86#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) 86#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
87#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) 87#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
88 88
89/* hardware needing special handling due to colliding MSVENDOR page usages */
90#define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418)
91#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9))
92
89#ifdef CONFIG_USB_HIDINPUT_POWERBOOK 93#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
90 94
91struct hidinput_key_translation { 95struct hidinput_key_translation {
@@ -295,7 +299,7 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode,
295{ 299{
296 struct hid_device *hid = dev->private; 300 struct hid_device *hid = dev->private;
297 struct hid_usage *usage; 301 struct hid_usage *usage;
298 302
299 usage = hidinput_find_key(hid, scancode, 0); 303 usage = hidinput_find_key(hid, scancode, 0);
300 if (usage) { 304 if (usage) {
301 *keycode = usage->code; 305 *keycode = usage->code;
@@ -310,15 +314,15 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
310 struct hid_device *hid = dev->private; 314 struct hid_device *hid = dev->private;
311 struct hid_usage *usage; 315 struct hid_usage *usage;
312 int old_keycode; 316 int old_keycode;
313 317
314 if (keycode < 0 || keycode > KEY_MAX) 318 if (keycode < 0 || keycode > KEY_MAX)
315 return -EINVAL; 319 return -EINVAL;
316 320
317 usage = hidinput_find_key(hid, scancode, 0); 321 usage = hidinput_find_key(hid, scancode, 0);
318 if (usage) { 322 if (usage) {
319 old_keycode = usage->code; 323 old_keycode = usage->code;
320 usage->code = keycode; 324 usage->code = keycode;
321 325
322 clear_bit(old_keycode, dev->keybit); 326 clear_bit(old_keycode, dev->keybit);
323 set_bit(usage->code, dev->keybit); 327 set_bit(usage->code, dev->keybit);
324 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); 328 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
@@ -326,10 +330,10 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
326 * by another key */ 330 * by another key */
327 if (hidinput_find_key (hid, 0, old_keycode)) 331 if (hidinput_find_key (hid, 0, old_keycode))
328 set_bit(old_keycode, dev->keybit); 332 set_bit(old_keycode, dev->keybit);
329 333
330 return 0; 334 return 0;
331 } 335 }
332 336
333 return -EINVAL; 337 return -EINVAL;
334} 338}
335 339
@@ -351,6 +355,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
351 if (field->flags & HID_MAIN_ITEM_CONSTANT) 355 if (field->flags & HID_MAIN_ITEM_CONSTANT)
352 goto ignore; 356 goto ignore;
353 357
358 /* only LED usages are supported in output fields */
359 if (field->report_type == HID_OUTPUT_REPORT &&
360 (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
361 dbg_hid_line(" [non-LED output field] ");
362 goto ignore;
363 }
364
354 switch (usage->hid & HID_USAGE_PAGE) { 365 switch (usage->hid & HID_USAGE_PAGE) {
355 366
356 case HID_UP_UNDEFINED: 367 case HID_UP_UNDEFINED:
@@ -595,6 +606,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
595 case 0x0f6: map_key_clear(KEY_NEXT); break; 606 case 0x0f6: map_key_clear(KEY_NEXT); break;
596 case 0x0fa: map_key_clear(KEY_BACK); break; 607 case 0x0fa: map_key_clear(KEY_BACK); break;
597 608
609 case 0x182: map_key_clear(KEY_BOOKMARKS); break;
598 case 0x183: map_key_clear(KEY_CONFIG); break; 610 case 0x183: map_key_clear(KEY_CONFIG); break;
599 case 0x184: map_key_clear(KEY_WORDPROCESSOR); break; 611 case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
600 case 0x185: map_key_clear(KEY_EDITOR); break; 612 case 0x185: map_key_clear(KEY_EDITOR); break;
@@ -611,9 +623,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
611 case 0x192: map_key_clear(KEY_CALC); break; 623 case 0x192: map_key_clear(KEY_CALC); break;
612 case 0x194: map_key_clear(KEY_FILE); break; 624 case 0x194: map_key_clear(KEY_FILE); break;
613 case 0x196: map_key_clear(KEY_WWW); break; 625 case 0x196: map_key_clear(KEY_WWW); break;
626 case 0x19c: map_key_clear(KEY_LOGOFF); break;
614 case 0x19e: map_key_clear(KEY_COFFEE); break; 627 case 0x19e: map_key_clear(KEY_COFFEE); break;
615 case 0x1a6: map_key_clear(KEY_HELP); break; 628 case 0x1a6: map_key_clear(KEY_HELP); break;
616 case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; 629 case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
630 case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
631 case 0x1b6: map_key_clear(KEY_MEDIA); break;
632 case 0x1b7: map_key_clear(KEY_SOUND); break;
617 case 0x1bc: map_key_clear(KEY_MESSENGER); break; 633 case 0x1bc: map_key_clear(KEY_MESSENGER); break;
618 case 0x1bd: map_key_clear(KEY_INFO); break; 634 case 0x1bd: map_key_clear(KEY_INFO); break;
619 case 0x201: map_key_clear(KEY_NEW); break; 635 case 0x201: map_key_clear(KEY_NEW); break;
@@ -720,8 +736,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
720 736
721 case HID_UP_MSVENDOR: 737 case HID_UP_MSVENDOR:
722 738
723 /* special case - Chicony Chicony KU-0418 tactical pad */ 739 /* Unfortunately, there are multiple devices which
724 if (device->vendor == 0x04f2 && device->product == 0x0418) { 740 * emit usages from MSVENDOR page that require different
741 * handling. If this list grows too much in the future,
742 * more general handling will have to be introduced here
743 * (i.e. another blacklist).
744 */
745
746 /* Chicony Chicony KU-0418 tactical pad */
747 if (IS_CHICONY_TACTICAL_PAD(device)) {
725 set_bit(EV_REP, input->evbit); 748 set_bit(EV_REP, input->evbit);
726 switch(usage->hid & HID_USAGE) { 749 switch(usage->hid & HID_USAGE) {
727 case 0xff01: map_key_clear(BTN_1); break; 750 case 0xff01: map_key_clear(BTN_1); break;
@@ -737,6 +760,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
737 case 0xff0b: map_key_clear(BTN_B); break; 760 case 0xff0b: map_key_clear(BTN_B); break;
738 default: goto ignore; 761 default: goto ignore;
739 } 762 }
763
764 /* Microsoft Natural Ergonomic Keyboard 4000 */
765 } else if (IS_MS_KB(device)) {
766 switch(usage->hid & HID_USAGE) {
767 case 0xfd06:
768 map_key_clear(KEY_CHAT);
769 break;
770 case 0xfd07:
771 map_key_clear(KEY_PHONE);
772 break;
773 case 0xff05:
774 set_bit(EV_REP, input->evbit);
775 map_key_clear(KEY_F13);
776 set_bit(KEY_F14, input->keybit);
777 set_bit(KEY_F15, input->keybit);
778 set_bit(KEY_F16, input->keybit);
779 set_bit(KEY_F17, input->keybit);
780 set_bit(KEY_F18, input->keybit);
781 default: goto ignore;
782 }
740 } else { 783 } else {
741 goto ignore; 784 goto ignore;
742 } 785 }
@@ -888,6 +931,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
888 set_bit(KEY_VOLUMEDOWN, input->keybit); 931 set_bit(KEY_VOLUMEDOWN, input->keybit);
889 } 932 }
890 933
934 if (usage->type == EV_KEY) {
935 set_bit(EV_MSC, input->evbit);
936 set_bit(MSC_SCAN, input->mscbit);
937 }
938
891 hid_resolv_event(usage->type, usage->code); 939 hid_resolv_event(usage->type, usage->code);
892 940
893 dbg_hid_line("\n"); 941 dbg_hid_line("\n");
@@ -991,6 +1039,29 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
991 return; 1039 return;
992 } 1040 }
993 1041
1042 /* Handling MS keyboards special buttons */
1043 if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
1044 int key = 0;
1045 static int last_key = 0;
1046 switch (value) {
1047 case 0x01: key = KEY_F14; break;
1048 case 0x02: key = KEY_F15; break;
1049 case 0x04: key = KEY_F16; break;
1050 case 0x08: key = KEY_F17; break;
1051 case 0x10: key = KEY_F18; break;
1052 default: break;
1053 }
1054 if (key) {
1055 input_event(input, usage->type, key, 1);
1056 last_key = key;
1057 } else {
1058 input_event(input, usage->type, last_key, 0);
1059 }
1060 }
1061 /* report the usage code as scancode if the key status has changed */
1062 if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
1063 input_event(input, EV_MSC, MSC_SCAN, usage->hid);
1064
994 input_event(input, usage->type, usage->code, value); 1065 input_event(input, usage->type, usage->code, value);
995 1066
996 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) 1067 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -1051,6 +1122,9 @@ int hidinput_connect(struct hid_device *hid)
1051 int i, j, k; 1122 int i, j, k;
1052 int max_report_type = HID_OUTPUT_REPORT; 1123 int max_report_type = HID_OUTPUT_REPORT;
1053 1124
1125 if (hid->quirks & HID_QUIRK_IGNORE_HIDINPUT)
1126 return -1;
1127
1054 INIT_LIST_HEAD(&hid->inputs); 1128 INIT_LIST_HEAD(&hid->inputs);
1055 1129
1056 for (i = 0; i < hid->maxcollection; i++) 1130 for (i = 0; i < hid->maxcollection; i++)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
new file mode 100644
index 000000000000..8503197a8131
--- /dev/null
+++ b/drivers/hid/hidraw.c
@@ -0,0 +1,401 @@
1/*
2 * HID raw devices, giving access to raw HID events.
3 *
4 * In comparison to hiddev, this device does not process the
5 * hid events at all (no parsing, no lookups). This lets applications
6 * to work on raw hid events as they want to, and avoids a need to
7 * use a transport-specific userspace libhid/libusb libraries.
8 *
9 * Copyright (c) 2007 Jiri Kosina
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms and conditions of the GNU General Public License,
15 * version 2, as published by the Free Software Foundation.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <linux/fs.h>
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/kernel.h>
26#include <linux/init.h>
27#include <linux/cdev.h>
28#include <linux/poll.h>
29#include <linux/device.h>
30#include <linux/major.h>
31#include <linux/hid.h>
32#include <linux/mutex.h>
33
34#include <linux/hidraw.h>
35
36static int hidraw_major;
37static struct cdev hidraw_cdev;
38static struct class *hidraw_class;
39static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
40static DEFINE_SPINLOCK(minors_lock);
41
42static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
43{
44 struct hidraw_list *list = file->private_data;
45 int ret = 0, len;
46 char *report;
47 DECLARE_WAITQUEUE(wait, current);
48
49 while (ret == 0) {
50
51 mutex_lock(&list->read_mutex);
52
53 if (list->head == list->tail) {
54 add_wait_queue(&list->hidraw->wait, &wait);
55 set_current_state(TASK_INTERRUPTIBLE);
56
57 while (list->head == list->tail) {
58 if (file->f_flags & O_NONBLOCK) {
59 ret = -EAGAIN;
60 break;
61 }
62 if (signal_pending(current)) {
63 ret = -ERESTARTSYS;
64 break;
65 }
66 if (!list->hidraw->exist) {
67 ret = -EIO;
68 break;
69 }
70
71 /* allow O_NONBLOCK to work well from other threads */
72 mutex_unlock(&list->read_mutex);
73 schedule();
74 mutex_lock(&list->read_mutex);
75 set_current_state(TASK_INTERRUPTIBLE);
76 }
77
78 set_current_state(TASK_RUNNING);
79 remove_wait_queue(&list->hidraw->wait, &wait);
80 }
81
82 if (ret)
83 goto out;
84
85 report = list->buffer[list->tail].value;
86 len = list->buffer[list->tail].len > count ?
87 count : list->buffer[list->tail].len;
88
89 if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
90 ret = -EFAULT;
91 goto out;
92 }
93 ret += len;
94
95 kfree(list->buffer[list->tail].value);
96 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
97 }
98out:
99 mutex_unlock(&list->read_mutex);
100 return ret;
101}
102
103/* the first byte is expected to be a report number */
104static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
105{
106 unsigned int minor = iminor(file->f_path.dentry->d_inode);
107 struct hid_device *dev = hidraw_table[minor]->hid;
108 __u8 *buf;
109 int ret = 0;
110
111 if (!dev->hid_output_raw_report)
112 return -ENODEV;
113
114 if (count > HID_MIN_BUFFER_SIZE) {
115 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
116 current->pid);
117 return -EINVAL;
118 }
119
120 if (count < 2) {
121 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
122 current->pid);
123 return -EINVAL;
124 }
125
126 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
127 if (!buf)
128 return -ENOMEM;
129
130 if (copy_from_user(buf, buffer, count)) {
131 ret = -EFAULT;
132 goto out;
133 }
134
135 ret = dev->hid_output_raw_report(dev, buf, count);
136out:
137 kfree(buf);
138 return ret;
139}
140
141static unsigned int hidraw_poll(struct file *file, poll_table *wait)
142{
143 struct hidraw_list *list = file->private_data;
144
145 poll_wait(file, &list->hidraw->wait, wait);
146 if (list->head != list->tail)
147 return POLLIN | POLLRDNORM;
148 if (!list->hidraw->exist)
149 return POLLERR | POLLHUP;
150 return 0;
151}
152
153static int hidraw_open(struct inode *inode, struct file *file)
154{
155 unsigned int minor = iminor(inode);
156 struct hidraw *dev;
157 struct hidraw_list *list;
158 int err = 0;
159
160 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
161 err = -ENOMEM;
162 goto out;
163 }
164
165 spin_lock(&minors_lock);
166 if (!hidraw_table[minor]) {
167 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
168 minor);
169 kfree(list);
170 err = -ENODEV;
171 goto out_unlock;
172 }
173
174 list->hidraw = hidraw_table[minor];
175 mutex_init(&list->read_mutex);
176 list_add_tail(&list->node, &hidraw_table[minor]->list);
177 file->private_data = list;
178
179 dev = hidraw_table[minor];
180 if (!dev->open++)
181 dev->hid->hid_open(dev->hid);
182
183out_unlock:
184 spin_unlock(&minors_lock);
185out:
186 return err;
187
188}
189
190static int hidraw_release(struct inode * inode, struct file * file)
191{
192 unsigned int minor = iminor(inode);
193 struct hidraw *dev;
194 struct hidraw_list *list = file->private_data;
195
196 if (!hidraw_table[minor]) {
197 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
198 minor);
199 return -ENODEV;
200 }
201
202 list_del(&list->node);
203 dev = hidraw_table[minor];
204 if (!dev->open--) {
205 if (list->hidraw->exist)
206 dev->hid->hid_close(dev->hid);
207 else
208 kfree(list->hidraw);
209 }
210
211 return 0;
212}
213
214static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
215{
216 unsigned int minor = iminor(inode);
217 struct hidraw *dev = hidraw_table[minor];
218 void __user *user_arg = (void __user*) arg;
219
220 switch (cmd) {
221 case HIDIOCGRDESCSIZE:
222 if (put_user(dev->hid->rsize, (int __user *)arg))
223 return -EFAULT;
224 return 0;
225
226 case HIDIOCGRDESC:
227 {
228 __u32 len;
229
230 if (get_user(len, (int __user *)arg))
231 return -EFAULT;
232 if (copy_to_user(*((__u8 **)(user_arg +
233 sizeof(__u32))),
234 dev->hid->rdesc, len))
235 return -EFAULT;
236 return 0;
237 }
238 case HIDIOCGRAWINFO:
239 {
240 struct hidraw_devinfo dinfo;
241
242 dinfo.bustype = dev->hid->bus;
243 dinfo.vendor = dev->hid->vendor;
244 dinfo.product = dev->hid->product;
245 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
246 return -EFAULT;
247
248 return 0;
249 }
250 default:
251 printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
252 cmd);
253 }
254 return -EINVAL;
255}
256
257static const struct file_operations hidraw_ops = {
258 .owner = THIS_MODULE,
259 .read = hidraw_read,
260 .write = hidraw_write,
261 .poll = hidraw_poll,
262 .open = hidraw_open,
263 .release = hidraw_release,
264 .ioctl = hidraw_ioctl,
265};
266
267void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
268{
269 struct hidraw *dev = hid->hidraw;
270 struct hidraw_list *list;
271
272 list_for_each_entry(list, &dev->list, node) {
273 list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
274 list->buffer[list->head].len = len;
275 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
276 kill_fasync(&list->fasync, SIGIO, POLL_IN);
277 }
278
279 wake_up_interruptible(&dev->wait);
280}
281EXPORT_SYMBOL_GPL(hidraw_report_event);
282
283int hidraw_connect(struct hid_device *hid)
284{
285 int minor, result;
286 struct hidraw *dev;
287
288 /* TODO currently we accept any HID device. This should later
289 * probably be fixed to accept only those devices which provide
290 * non-input applications
291 */
292
293 dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
294 if (!dev)
295 return -ENOMEM;
296
297 result = -EINVAL;
298
299 spin_lock(&minors_lock);
300
301 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
302 if (hidraw_table[minor])
303 continue;
304 hidraw_table[minor] = dev;
305 result = 0;
306 break;
307 }
308
309 spin_unlock(&minors_lock);
310
311 if (result) {
312 kfree(dev);
313 goto out;
314 }
315
316 dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
317 "%s%d", "hidraw", minor);
318
319 if (IS_ERR(dev->dev)) {
320 spin_lock(&minors_lock);
321 hidraw_table[minor] = NULL;
322 spin_unlock(&minors_lock);
323 result = PTR_ERR(dev->dev);
324 kfree(dev);
325 goto out;
326 }
327
328 init_waitqueue_head(&dev->wait);
329 INIT_LIST_HEAD(&dev->list);
330
331 dev->hid = hid;
332 dev->minor = minor;
333
334 dev->exist = 1;
335 hid->hidraw = dev;
336
337out:
338 return result;
339
340}
341EXPORT_SYMBOL_GPL(hidraw_connect);
342
343void hidraw_disconnect(struct hid_device *hid)
344{
345 struct hidraw *hidraw = hid->hidraw;
346
347 hidraw->exist = 0;
348
349 spin_lock(&minors_lock);
350 hidraw_table[hidraw->minor] = NULL;
351 spin_unlock(&minors_lock);
352
353 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
354
355 if (hidraw->open) {
356 hid->hid_close(hid);
357 wake_up_interruptible(&hidraw->wait);
358 } else {
359 kfree(hidraw);
360 }
361}
362EXPORT_SYMBOL_GPL(hidraw_disconnect);
363
364int __init hidraw_init(void)
365{
366 int result;
367 dev_t dev_id;
368
369 result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
370 HIDRAW_MAX_DEVICES, "hidraw");
371
372 hidraw_major = MAJOR(dev_id);
373
374 if (result < 0) {
375 printk(KERN_WARNING "hidraw: can't get major number\n");
376 result = 0;
377 goto out;
378 }
379
380 hidraw_class = class_create(THIS_MODULE, "hidraw");
381 if (IS_ERR(hidraw_class)) {
382 result = PTR_ERR(hidraw_class);
383 unregister_chrdev(hidraw_major, "hidraw");
384 goto out;
385 }
386
387 cdev_init(&hidraw_cdev, &hidraw_ops);
388 cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
389out:
390 return result;
391}
392
393void __exit hidraw_exit(void)
394{
395 dev_t dev_id = MKDEV(hidraw_major, 0);
396
397 cdev_del(&hidraw_cdev);
398 class_destroy(hidraw_class);
399 unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
400
401}
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 1b4b572f899b..c557d7040a69 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -71,19 +71,20 @@ config LOGITECH_FF
71 force feedback. 71 force feedback.
72 72
73config PANTHERLORD_FF 73config PANTHERLORD_FF
74 bool "PantherLord USB/PS2 2in1 Adapter support" 74 bool "PantherLord/GreenAsia based device support"
75 depends on HID_FF 75 depends on HID_FF
76 select INPUT_FF_MEMLESS if USB_HID 76 select INPUT_FF_MEMLESS if USB_HID
77 help 77 help
78 Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want 78 Say Y here if you have a PantherLord/GreenAsia based game controller
79 to enable force feedback support for it. 79 or adapter and want to enable force feedback support for it.
80 80
81config THRUSTMASTER_FF 81config THRUSTMASTER_FF
82 bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" 82 bool "ThrustMaster devices support (EXPERIMENTAL)"
83 depends on HID_FF && EXPERIMENTAL 83 depends on HID_FF && EXPERIMENTAL
84 select INPUT_FF_MEMLESS if USB_HID 84 select INPUT_FF_MEMLESS if USB_HID
85 help 85 help
86 Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, 86 Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
87 a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel,
87 and want to enable force feedback support for it. 88 and want to enable force feedback support for it.
88 Note: if you say N here, this device will still be supported, but without 89 Note: if you say N here, this device will still be supported, but without
89 force feedback. 90 force feedback.
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 0a1f2b52a12f..b38e559b7a46 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -32,6 +32,7 @@
32#include <linux/hid.h> 32#include <linux/hid.h>
33#include <linux/hiddev.h> 33#include <linux/hiddev.h>
34#include <linux/hid-debug.h> 34#include <linux/hid-debug.h>
35#include <linux/hidraw.h>
35#include "usbhid.h" 36#include "usbhid.h"
36 37
37/* 38/*
@@ -512,7 +513,16 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
512 513
513int usbhid_open(struct hid_device *hid) 514int usbhid_open(struct hid_device *hid)
514{ 515{
515 ++hid->open; 516 struct usbhid_device *usbhid = hid->driver_data;
517 int res;
518
519 if (!hid->open++) {
520 res = usb_autopm_get_interface(usbhid->intf);
521 if (res < 0) {
522 hid->open--;
523 return -EIO;
524 }
525 }
516 if (hid_start_in(hid)) 526 if (hid_start_in(hid))
517 hid_io_error(hid); 527 hid_io_error(hid);
518 return 0; 528 return 0;
@@ -522,8 +532,10 @@ void usbhid_close(struct hid_device *hid)
522{ 532{
523 struct usbhid_device *usbhid = hid->driver_data; 533 struct usbhid_device *usbhid = hid->driver_data;
524 534
525 if (!--hid->open) 535 if (!--hid->open) {
526 usb_kill_urb(usbhid->urbin); 536 usb_kill_urb(usbhid->urbin);
537 usb_autopm_put_interface(usbhid->intf);
538 }
527} 539}
528 540
529/* 541/*
@@ -628,6 +640,28 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
628 return 0; 640 return 0;
629} 641}
630 642
643static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count)
644{
645 struct usbhid_device *usbhid = hid->driver_data;
646 struct usb_device *dev = hid_to_usb_dev(hid);
647 struct usb_interface *intf = usbhid->intf;
648 struct usb_host_interface *interface = intf->cur_altsetting;
649 int ret;
650
651 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
652 HID_REQ_SET_REPORT,
653 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
654 cpu_to_le16(((HID_OUTPUT_REPORT + 1) << 8) | *buf),
655 interface->desc.bInterfaceNumber, buf + 1, count - 1,
656 USB_CTRL_SET_TIMEOUT);
657
658 /* count also the report id */
659 if (ret > 0)
660 ret++;
661
662 return ret;
663}
664
631static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) 665static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
632{ 666{
633 struct usbhid_device *usbhid = hid->driver_data; 667 struct usbhid_device *usbhid = hid->driver_data;
@@ -871,6 +905,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
871 hid->hiddev_hid_event = hiddev_hid_event; 905 hid->hiddev_hid_event = hiddev_hid_event;
872 hid->hiddev_report_event = hiddev_report_event; 906 hid->hiddev_report_event = hiddev_report_event;
873#endif 907#endif
908 hid->hid_output_raw_report = usbhid_output_raw_report;
874 return hid; 909 return hid;
875 910
876fail: 911fail:
@@ -909,6 +944,8 @@ static void hid_disconnect(struct usb_interface *intf)
909 hidinput_disconnect(hid); 944 hidinput_disconnect(hid);
910 if (hid->claimed & HID_CLAIMED_HIDDEV) 945 if (hid->claimed & HID_CLAIMED_HIDDEV)
911 hiddev_disconnect(hid); 946 hiddev_disconnect(hid);
947 if (hid->claimed & HID_CLAIMED_HIDRAW)
948 hidraw_disconnect(hid);
912 949
913 usb_free_urb(usbhid->urbin); 950 usb_free_urb(usbhid->urbin);
914 usb_free_urb(usbhid->urbctrl); 951 usb_free_urb(usbhid->urbctrl);
@@ -941,11 +978,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
941 hid->claimed |= HID_CLAIMED_INPUT; 978 hid->claimed |= HID_CLAIMED_INPUT;
942 if (!hiddev_connect(hid)) 979 if (!hiddev_connect(hid))
943 hid->claimed |= HID_CLAIMED_HIDDEV; 980 hid->claimed |= HID_CLAIMED_HIDDEV;
981 if (!hidraw_connect(hid))
982 hid->claimed |= HID_CLAIMED_HIDRAW;
944 983
945 usb_set_intfdata(intf, hid); 984 usb_set_intfdata(intf, hid);
946 985
947 if (!hid->claimed) { 986 if (!hid->claimed) {
948 printk ("HID device not claimed by input or hiddev\n"); 987 printk ("HID device claimed by neither input, hiddev nor hidraw\n");
949 hid_disconnect(intf); 988 hid_disconnect(intf);
950 return -ENODEV; 989 return -ENODEV;
951 } 990 }
@@ -961,10 +1000,16 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
961 1000
962 if (hid->claimed & HID_CLAIMED_INPUT) 1001 if (hid->claimed & HID_CLAIMED_INPUT)
963 printk("input"); 1002 printk("input");
964 if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) 1003 if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
1004 hid->claimed & HID_CLAIMED_HIDRAW))
965 printk(","); 1005 printk(",");
966 if (hid->claimed & HID_CLAIMED_HIDDEV) 1006 if (hid->claimed & HID_CLAIMED_HIDDEV)
967 printk("hiddev%d", hid->minor); 1007 printk("hiddev%d", hid->minor);
1008 if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
1009 (hid->claimed & HID_CLAIMED_HIDRAW))
1010 printk(",");
1011 if (hid->claimed & HID_CLAIMED_HIDRAW)
1012 printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
968 1013
969 c = "Device"; 1014 c = "Device";
970 for (i = 0; i < hid->maxcollection; i++) { 1015 for (i = 0; i < hid->maxcollection; i++) {
@@ -1048,6 +1093,7 @@ static struct usb_driver hid_driver = {
1048 .pre_reset = hid_pre_reset, 1093 .pre_reset = hid_pre_reset,
1049 .post_reset = hid_post_reset, 1094 .post_reset = hid_post_reset,
1050 .id_table = hid_usb_ids, 1095 .id_table = hid_usb_ids,
1096 .supports_autosuspend = 1,
1051}; 1097};
1052 1098
1053static int __init hid_init(void) 1099static int __init hid_init(void)
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
index 23431fbbc3d7..22329feb3b5a 100644
--- a/drivers/hid/usbhid/hid-ff.c
+++ b/drivers/hid/usbhid/hid-ff.c
@@ -62,11 +62,14 @@ static struct hid_ff_initializer inits[] = {
62 { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */ 62 { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
63#endif 63#endif
64#ifdef CONFIG_PANTHERLORD_FF 64#ifdef CONFIG_PANTHERLORD_FF
65 { 0x810, 0x0001, hid_plff_init }, 65 { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
66 { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc. USB Joystick " */
66#endif 67#endif
67#ifdef CONFIG_THRUSTMASTER_FF 68#ifdef CONFIG_THRUSTMASTER_FF
68 { 0x44f, 0xb300, hid_tmff_init }, 69 { 0x44f, 0xb300, hid_tmff_init },
69 { 0x44f, 0xb304, hid_tmff_init }, 70 { 0x44f, 0xb304, hid_tmff_init },
71 { 0x44f, 0xb651, hid_tmff_init }, /* FGT Rumble Force Wheel */
72 { 0x44f, 0xb654, hid_tmff_init }, /* FGT Force Feedback Wheel */
70#endif 73#endif
71#ifdef CONFIG_ZEROPLUS_FF 74#ifdef CONFIG_ZEROPLUS_FF
72 { 0xc12, 0x0005, hid_zpff_init }, 75 { 0xc12, 0x0005, hid_zpff_init },
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c
index d6a8f2b49bd2..9eb83cf9d22b 100644
--- a/drivers/hid/usbhid/hid-plff.c
+++ b/drivers/hid/usbhid/hid-plff.c
@@ -1,5 +1,15 @@
1/* 1/*
2 * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices 2 * Force feedback support for PantherLord/GreenAsia based devices
3 *
4 * The devices are distributed under various names and the same USB device ID
5 * can be used in both adapters and actual game controllers.
6 *
7 * 0810:0001 "Twin USB Joystick"
8 * - tested with PantherLord USB/PS2 2in1 Adapter
9 * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT)
10 *
11 * 0e8f:0003 "GreenAsia Inc. USB Joystick "
12 * - tested with Köng Gaming gamepad
3 * 13 *
4 * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> 14 * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
5 */ 15 */
@@ -67,11 +77,11 @@ int hid_plff_init(struct hid_device *hid)
67 struct input_dev *dev; 77 struct input_dev *dev;
68 int error; 78 int error;
69 79
70 /* The device contains 2 output reports (one for each 80 /* The device contains one output report per physical device, all
71 HID_QUIRK_MULTI_INPUT device), both containing 1 field, which 81 containing 1 field, which contains 4 ff00.0002 usages and 4 16bit
72 contains 4 ff00.0002 usages and 4 16bit absolute values. 82 absolute values.
73 83
74 The 2 input reports also contain a field which contains 84 The input reports also contain a field which contains
75 8 ff00.0001 usages and 8 boolean values. Their meaning is 85 8 ff00.0001 usages and 8 boolean values. Their meaning is
76 currently unknown. */ 86 currently unknown. */
77 87
@@ -122,8 +132,8 @@ int hid_plff_init(struct hid_device *hid)
122 usbhid_submit_report(hid, plff->report, USB_DIR_OUT); 132 usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
123 } 133 }
124 134
125 printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " 135 printk(KERN_INFO "hid-plff: Force feedback for PantherLord/GreenAsia "
126 "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); 136 "devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
127 137
128 return 0; 138 return 0;
129} 139}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 6b21a214f419..41a59a80e7ed 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -61,6 +61,7 @@
61#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c 61#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
62#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a 62#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
63#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b 63#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
64#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
64 65
65#define USB_VENDOR_ID_ASUS 0x0b05 66#define USB_VENDOR_ID_ASUS 0x0b05
66#define USB_DEVICE_ID_ASUS_LCM 0x1726 67#define USB_DEVICE_ID_ASUS_LCM 0x1726
@@ -86,6 +87,9 @@
86 87
87#define USB_VENDOR_ID_CIDC 0x1677 88#define USB_VENDOR_ID_CIDC 0x1677
88 89
90#define USB_VENDOR_ID_CMEDIA 0x0d8c
91#define USB_DEVICE_ID_CM109 0x000e
92
89#define USB_VENDOR_ID_CODEMERCS 0x07c0 93#define USB_VENDOR_ID_CODEMERCS 0x07c0
90#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 94#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
91#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff 95#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff
@@ -104,12 +108,17 @@
104#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 108#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
105#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 109#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
106 110
111#define USB_VENDOR_ID_ELO 0x04E7
112#define USB_DEVICE_ID_ELO_TS2700 0x0020
113
107#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f 114#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
108#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 115#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
109 116
110#define USB_VENDOR_ID_GAMERON 0x0810 117#define USB_VENDOR_ID_GAMERON 0x0810
111#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 118#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
112 119
120#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
121
113#define USB_VENDOR_ID_GLAB 0x06c2 122#define USB_VENDOR_ID_GLAB 0x06c2
114#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 123#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
115#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 124#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -373,6 +382,7 @@ static const struct hid_blacklist {
373 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 382 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
374 383
375 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, 384 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
385 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
376 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT }, 386 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
377 387
378 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, 388 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
@@ -387,11 +397,16 @@ static const struct hid_blacklist {
387 { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE}, 397 { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
388 { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, 398 { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
389 { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE }, 399 { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
400 { USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
390 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, 401 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
391 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE }, 402 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
392 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, 403 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
393 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, 404 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
394 { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, 405 { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
406 { USB_VENDOR_ID_GENERAL_TOUCH, 0x0001, HID_QUIRK_IGNORE },
407 { USB_VENDOR_ID_GENERAL_TOUCH, 0x0002, HID_QUIRK_IGNORE },
408 { USB_VENDOR_ID_GENERAL_TOUCH, 0x0003, HID_QUIRK_IGNORE },
409 { USB_VENDOR_ID_GENERAL_TOUCH, 0x0004, HID_QUIRK_IGNORE },
395 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, 410 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
396 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, 411 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
397 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, 412 { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
@@ -507,6 +522,7 @@ static const struct hid_blacklist {
507 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, 522 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
508 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, 523 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
509 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, 524 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
525 { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
510 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, 526 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
511 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET }, 527 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
512 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, 528 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
@@ -614,6 +630,8 @@ static const struct hid_rdesc_blacklist {
614 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH }, 630 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
615 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH }, 631 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
616 632
633 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
634
617 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX }, 635 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
618 636
619 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX }, 637 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
@@ -927,6 +945,18 @@ static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
927 printk(KERN_INFO "Fixing up Cypress report descriptor\n"); 945 printk(KERN_INFO "Fixing up Cypress report descriptor\n");
928} 946}
929 947
948/*
949 * MacBook JIS keyboard has wrong logical maximum
950 */
951static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
952{
953 if (rsize >= 60 && rdesc[53] == 0x65
954 && rdesc[59] == 0x65) {
955 printk(KERN_INFO "Fixing up MacBook JIS keyboard report descriptor\n");
956 rdesc[53] = rdesc[59] = 0xe7;
957 }
958}
959
930 960
931static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize) 961static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
932{ 962{
@@ -941,6 +971,9 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
941 971
942 if (quirks & HID_QUIRK_RDESC_PETALYNX) 972 if (quirks & HID_QUIRK_RDESC_PETALYNX)
943 usbhid_fixup_petalynx_descriptor(rdesc, rsize); 973 usbhid_fixup_petalynx_descriptor(rdesc, rsize);
974
975 if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
976 usbhid_fixup_macbook_descriptor(rdesc, rsize);
944} 977}
945 978
946/** 979/**
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index 555bb48b4295..69882a726e99 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -36,16 +36,39 @@
36#include "usbhid.h" 36#include "usbhid.h"
37 37
38/* Usages for thrustmaster devices I know about */ 38/* Usages for thrustmaster devices I know about */
39#define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) 39#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
40 40
41struct dev_type {
42 u16 idVendor;
43 u16 idProduct;
44 const signed short *ff;
45};
46
47static const signed short ff_rumble[] = {
48 FF_RUMBLE,
49 -1
50};
51
52static const signed short ff_joystick[] = {
53 FF_CONSTANT,
54 -1
55};
56
57static const struct dev_type devices[] = {
58 { 0x44f, 0xb300, ff_rumble },
59 { 0x44f, 0xb304, ff_rumble },
60 { 0x44f, 0xb651, ff_rumble }, /* FGT Rumble Force Wheel */
61 { 0x44f, 0xb654, ff_joystick }, /* FGT Force Feedback Wheel */
62};
41 63
42struct tmff_device { 64struct tmff_device {
43 struct hid_report *report; 65 struct hid_report *report;
44 struct hid_field *rumble; 66 struct hid_field *ff_field;
45}; 67};
46 68
47/* Changes values from 0 to 0xffff into values from minimum to maximum */ 69/* Changes values from 0 to 0xffff into values from minimum to maximum */
48static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) 70static inline int hid_tmff_scale_u16(unsigned int in,
71 int minimum, int maximum)
49{ 72{
50 int ret; 73 int ret;
51 74
@@ -57,22 +80,57 @@ static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum)
57 return ret; 80 return ret;
58} 81}
59 82
83/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
84static inline int hid_tmff_scale_s8(int in,
85 int minimum, int maximum)
86{
87 int ret;
88
89 ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
90 if (ret < minimum)
91 return minimum;
92 if (ret > maximum)
93 return maximum;
94 return ret;
95}
96
60static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) 97static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
61{ 98{
62 struct hid_device *hid = input_get_drvdata(dev); 99 struct hid_device *hid = input_get_drvdata(dev);
63 struct tmff_device *tmff = data; 100 struct tmff_device *tmff = data;
101 struct hid_field *ff_field = tmff->ff_field;
102 int x, y;
64 int left, right; /* Rumbling */ 103 int left, right; /* Rumbling */
65 104
66 left = hid_tmff_scale(effect->u.rumble.weak_magnitude, 105 switch (effect->type) {
67 tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); 106 case FF_CONSTANT:
68 right = hid_tmff_scale(effect->u.rumble.strong_magnitude, 107 x = hid_tmff_scale_s8(effect->u.ramp.start_level,
69 tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); 108 ff_field->logical_minimum,
70 109 ff_field->logical_maximum);
71 tmff->rumble->value[0] = left; 110 y = hid_tmff_scale_s8(effect->u.ramp.end_level,
72 tmff->rumble->value[1] = right; 111 ff_field->logical_minimum,
73 dbg_hid("(left,right)=(%08x, %08x)\n", left, right); 112 ff_field->logical_maximum);
74 usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); 113
75 114 dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
115 ff_field->value[0] = x;
116 ff_field->value[1] = y;
117 usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
118 break;
119
120 case FF_RUMBLE:
121 left = hid_tmff_scale_u16(effect->u.rumble.weak_magnitude,
122 ff_field->logical_minimum,
123 ff_field->logical_maximum);
124 right = hid_tmff_scale_u16(effect->u.rumble.strong_magnitude,
125 ff_field->logical_minimum,
126 ff_field->logical_maximum);
127
128 dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
129 ff_field->value[0] = left;
130 ff_field->value[1] = right;
131 usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
132 break;
133 }
76 return 0; 134 return 0;
77} 135}
78 136
@@ -82,14 +140,16 @@ int hid_tmff_init(struct hid_device *hid)
82 struct list_head *pos; 140 struct list_head *pos;
83 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 141 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
84 struct input_dev *input_dev = hidinput->input; 142 struct input_dev *input_dev = hidinput->input;
143 const signed short *ff_bits = ff_joystick;
85 int error; 144 int error;
145 int i;
86 146
87 tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); 147 tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
88 if (!tmff) 148 if (!tmff)
89 return -ENOMEM; 149 return -ENOMEM;
90 150
91 /* Find the report to use */ 151 /* Find the report to use */
92 __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { 152 list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
93 struct hid_report *report = (struct hid_report *)pos; 153 struct hid_report *report = (struct hid_report *)pos;
94 int fieldnum; 154 int fieldnum;
95 155
@@ -100,48 +160,65 @@ int hid_tmff_init(struct hid_device *hid)
100 continue; 160 continue;
101 161
102 switch (field->usage[0].hid) { 162 switch (field->usage[0].hid) {
103 case THRUSTMASTER_USAGE_RUMBLE_LR: 163 case THRUSTMASTER_USAGE_FF:
104 if (field->report_count < 2) { 164 if (field->report_count < 2) {
105 warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); 165 warn("ignoring FF field with report_count < 2");
106 continue; 166 continue;
107 } 167 }
108 168
109 if (field->logical_maximum == field->logical_minimum) { 169 if (field->logical_maximum == field->logical_minimum) {
110 warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); 170 warn("ignoring FF field with logical_maximum == logical_minimum");
111 continue; 171 continue;
112 } 172 }
113 173
114 if (tmff->report && tmff->report != report) { 174 if (tmff->report && tmff->report != report) {
115 warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); 175 warn("ignoring FF field in other report");
116 continue; 176 continue;
117 } 177 }
118 178
119 if (tmff->rumble && tmff->rumble != field) { 179 if (tmff->ff_field && tmff->ff_field != field) {
120 warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); 180 warn("ignoring duplicate FF field");
121 continue; 181 continue;
182 }
183
184 tmff->report = report;
185 tmff->ff_field = field;
186
187 for (i = 0; i < ARRAY_SIZE(devices); i++) {
188 if (input_dev->id.vendor == devices[i].idVendor &&
189 input_dev->id.product == devices[i].idProduct) {
190 ff_bits = devices[i].ff;
191 break;
122 } 192 }
193 }
123 194
124 tmff->report = report; 195 for (i = 0; ff_bits[i] >= 0; i++)
125 tmff->rumble = field; 196 set_bit(ff_bits[i], input_dev->ffbit);
126 197
127 set_bit(FF_RUMBLE, input_dev->ffbit); 198 break;
128 break;
129 199
130 default: 200 default:
131 warn("ignoring unknown output usage %08x", field->usage[0].hid); 201 warn("ignoring unknown output usage %08x", field->usage[0].hid);
132 continue; 202 continue;
133 } 203 }
134 } 204 }
135 } 205 }
136 206
137 error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); 207 if (!tmff->report) {
138 if (error) { 208 err("cant find FF field in output reports\n");
139 kfree(tmff); 209 error = -ENODEV;
140 return error; 210 goto fail;
141 } 211 }
142 212
143 info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); 213 error = input_ff_create_memless(input_dev, tmff, hid_tmff_play);
214 if (error)
215 goto fail;
144 216
217 info("Force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>");
145 return 0; 218 return 0;
219
220 fail:
221 kfree(tmff);
222 return error;
146} 223}
147 224
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index e793127f971e..9837adcb17e9 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -34,6 +34,7 @@
34#include <linux/usb.h> 34#include <linux/usb.h>
35#include <linux/hid.h> 35#include <linux/hid.h>
36#include <linux/hiddev.h> 36#include <linux/hiddev.h>
37#include <linux/compat.h>
37#include "usbhid.h" 38#include "usbhid.h"
38 39
39#ifdef CONFIG_USB_DYNAMIC_MINORS 40#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -738,6 +739,14 @@ inval:
738 return -EINVAL; 739 return -EINVAL;
739} 740}
740 741
742#ifdef CONFIG_COMPAT
743static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
744{
745 struct inode *inode = file->f_path.dentry->d_inode;
746 return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
747}
748#endif
749
741static const struct file_operations hiddev_fops = { 750static const struct file_operations hiddev_fops = {
742 .owner = THIS_MODULE, 751 .owner = THIS_MODULE,
743 .read = hiddev_read, 752 .read = hiddev_read,
@@ -747,6 +756,9 @@ static const struct file_operations hiddev_fops = {
747 .release = hiddev_release, 756 .release = hiddev_release,
748 .ioctl = hiddev_ioctl, 757 .ioctl = hiddev_ioctl,
749 .fasync = hiddev_fasync, 758 .fasync = hiddev_fasync,
759#ifdef CONFIG_COMPAT
760 .compat_ioctl = hiddev_compat_ioctl,
761#endif
750}; 762};
751 763
752static struct usb_class_driver hiddev_class = { 764static struct usb_class_driver hiddev_class = {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 898103b401f1..55e51f9f76cb 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -276,6 +276,7 @@ struct hid_item {
276#define HID_QUIRK_HIDINPUT 0x00200000 276#define HID_QUIRK_HIDINPUT 0x00200000
277#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000 277#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
278#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000 278#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
279#define HID_QUIRK_IGNORE_HIDINPUT 0x01000000
279 280
280/* 281/*
281 * Separate quirks for runtime report descriptor fixup 282 * Separate quirks for runtime report descriptor fixup
@@ -285,6 +286,7 @@ struct hid_item {
285#define HID_QUIRK_RDESC_LOGITECH 0x00000002 286#define HID_QUIRK_RDESC_LOGITECH 0x00000002
286#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004 287#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
287#define HID_QUIRK_RDESC_PETALYNX 0x00000008 288#define HID_QUIRK_RDESC_PETALYNX 0x00000008
289#define HID_QUIRK_RDESC_MACBOOK_JIS 0x00000010
288 290
289/* 291/*
290 * This is the global environment of the parser. This information is 292 * This is the global environment of the parser. This information is
@@ -403,6 +405,7 @@ struct hid_control_fifo {
403 405
404#define HID_CLAIMED_INPUT 1 406#define HID_CLAIMED_INPUT 1
405#define HID_CLAIMED_HIDDEV 2 407#define HID_CLAIMED_HIDDEV 2
408#define HID_CLAIMED_HIDRAW 4
406 409
407#define HID_CTRL_RUNNING 1 410#define HID_CTRL_RUNNING 1
408#define HID_OUT_RUNNING 2 411#define HID_OUT_RUNNING 2
@@ -438,6 +441,7 @@ struct hid_device { /* device report descriptor */
438 441
439 struct list_head inputs; /* The list of inputs */ 442 struct list_head inputs; /* The list of inputs */
440 void *hiddev; /* The hiddev structure */ 443 void *hiddev; /* The hiddev structure */
444 void *hidraw;
441 int minor; /* Hiddev minor number */ 445 int minor; /* Hiddev minor number */
442 446
443 wait_queue_head_t wait; /* For sleeping */ 447 wait_queue_head_t wait; /* For sleeping */
@@ -458,6 +462,9 @@ struct hid_device { /* device report descriptor */
458 void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, 462 void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
459 struct hid_usage *, __s32); 463 struct hid_usage *, __s32);
460 void (*hiddev_report_event) (struct hid_device *, struct hid_report *); 464 void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
465
466 /* handler for raw output data, used by hidraw */
467 int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
461#ifdef CONFIG_USB_HIDINPUT_POWERBOOK 468#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
462 unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; 469 unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
463 unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; 470 unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
new file mode 100644
index 000000000000..6676cd5e9954
--- /dev/null
+++ b/include/linux/hidraw.h
@@ -0,0 +1,86 @@
1#ifndef _HIDRAW_H
2#define _HIDRAW_H
3
4/*
5 * Copyright (c) 2007 Jiri Kosina
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18struct hidraw_report_descriptor {
19 __u32 size;
20 __u8 *value;
21};
22
23struct hidraw_devinfo {
24 __u32 bustype;
25 __s16 vendor;
26 __s16 product;
27};
28
29/* ioctl interface */
30#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
31#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
32#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
33
34#define HIDRAW_FIRST_MINOR 0
35#define HIDRAW_MAX_DEVICES 64
36/* number of reports to buffer */
37#define HIDRAW_BUFFER_SIZE 64
38
39
40/* kernel-only API declarations */
41#ifdef __KERNEL__
42
43#include <linux/hid.h>
44
45struct hidraw {
46 unsigned int minor;
47 int exist;
48 int open;
49 wait_queue_head_t wait;
50 struct hid_device *hid;
51 struct device *dev;
52 struct list_head list;
53};
54
55struct hidraw_report {
56 __u8 *value;
57 int len;
58};
59
60struct hidraw_list {
61 struct hidraw_report buffer[HIDRAW_BUFFER_SIZE];
62 int head;
63 int tail;
64 struct fasync_struct *fasync;
65 struct hidraw *hidraw;
66 struct list_head node;
67 struct mutex read_mutex;
68};
69
70#ifdef CONFIG_HIDRAW
71int hidraw_init(void);
72void hidraw_exit(void);
73void hidraw_report_event(struct hid_device *, u8 *, int);
74int hidraw_connect(struct hid_device *);
75void hidraw_disconnect(struct hid_device *);
76#else
77static inline int hidraw_init(void) { return 0; }
78static inline void hidraw_exit(void) { }
79static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
80static inline int hidraw_connect(struct hid_device *hid) { return -1; }
81static inline void hidraw_disconnect(struct hid_device *hid) { }
82#endif
83
84#endif
85
86#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index 6eb3aead7f1d..52d1bd434a50 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -523,6 +523,8 @@ struct input_absinfo {
523#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ 523#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
524#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ 524#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
525#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ 525#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
526#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
527#define KEY_LOGOFF 0x1b1 /* AL Logoff */
526 528
527#define KEY_DEL_EOL 0x1c0 529#define KEY_DEL_EOL 0x1c0
528#define KEY_DEL_EOS 0x1c1 530#define KEY_DEL_EOS 0x1c1