aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-dummy.c3
-rw-r--r--drivers/hid/hid-sony.c111
-rw-r--r--drivers/hid/usbhid/hid-core.c30
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--include/linux/hid.h1
8 files changed, 123 insertions, 33 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 52b617bf2b93..7ced6476026a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -182,6 +182,13 @@ config HID_SAMSUNG
182 ---help--- 182 ---help---
183 Support for Samsung IR remote. 183 Support for Samsung IR remote.
184 184
185config HID_SONY
186 tristate "Sony"
187 default m
188 depends on USB_HID
189 ---help---
190 Support for Sony PS3 controller.
191
185config HID_SUNPLUS 192config HID_SUNPLUS
186 tristate "Sunplus" 193 tristate "Sunplus"
187 default m 194 default m
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 0141ff88008e..4f39b9431ebe 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
25obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o 25obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
26obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o 26obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
27obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 27obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
28obj-$(CONFIG_HID_SONY) += hid-sony.o
28obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o 29obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
29 30
30obj-$(CONFIG_USB_HID) += usbhid/ 31obj-$(CONFIG_USB_HID) += usbhid/
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 1b43af072ce0..f527e332b596 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1195,6 +1195,7 @@ static const struct hid_device_id hid_blacklist[] = {
1195 { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, 1195 { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
1196 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, 1196 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
1197 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, 1197 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
1198 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
1198 { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, 1199 { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
1199 1200
1200 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, 1201 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index cd21dcc41816..1ef3111f7fe7 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
43#ifdef CONFIG_HID_SAMSUNG_MODULE 43#ifdef CONFIG_HID_SAMSUNG_MODULE
44 HID_COMPAT_CALL_DRIVER(samsung); 44 HID_COMPAT_CALL_DRIVER(samsung);
45#endif 45#endif
46#ifdef CONFIG_HID_SONY_MODULE
47 HID_COMPAT_CALL_DRIVER(sony);
48#endif
46#ifdef CONFIG_HID_SUNPLUS_MODULE 49#ifdef CONFIG_HID_SUNPLUS_MODULE
47 HID_COMPAT_CALL_DRIVER(sunplus); 50 HID_COMPAT_CALL_DRIVER(sunplus);
48#endif 51#endif
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
new file mode 100644
index 000000000000..97668c68f0a6
--- /dev/null
+++ b/drivers/hid/hid-sony.c
@@ -0,0 +1,111 @@
1/*
2 * HID driver for some sony "special" devices
3 *
4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7 * Copyright (c) 2006-2007 Jiri Kosina
8 * Copyright (c) 2007 Paul Walmsley
9 * Copyright (c) 2008 Jiri Slaby
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
16 * any later version.
17 */
18
19#include <linux/device.h>
20#include <linux/hid.h>
21#include <linux/module.h>
22#include <linux/usb.h>
23
24#include "hid-ids.h"
25
26/*
27 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
28 * to "operational". Without this, the ps3 controller will not report any
29 * events.
30 */
31static int sony_set_operational(struct hid_device *hdev)
32{
33 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
34 struct usb_device *dev = interface_to_usbdev(intf);
35 __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
36 int ret;
37 char *buf = kmalloc(18, GFP_KERNEL);
38
39 if (!buf)
40 return -ENOMEM;
41
42 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
43 HID_REQ_GET_REPORT,
44 USB_DIR_IN | USB_TYPE_CLASS |
45 USB_RECIP_INTERFACE,
46 (3 << 8) | 0xf2, ifnum, buf, 17,
47 USB_CTRL_GET_TIMEOUT);
48 if (ret < 0)
49 dev_err(&hdev->dev, "can't set operational mode\n");
50
51 kfree(buf);
52
53 return ret;
54}
55
56static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
57{
58 int ret;
59
60 hdev->quirks |= HID_QUIRK_HIDDEV;
61
62 ret = hid_parse(hdev);
63 if (ret) {
64 dev_err(&hdev->dev, "parse failed\n");
65 goto err_free;
66 }
67
68 ret = hid_hw_start(hdev);
69 if (ret) {
70 dev_err(&hdev->dev, "hw start failed\n");
71 goto err_free;
72 }
73
74 ret = sony_set_operational(hdev);
75 if (ret)
76 goto err_stop;
77
78 return 0;
79err_stop:
80 hid_hw_stop(hdev);
81err_free:
82 return ret;
83}
84
85static const struct hid_device_id sony_devices[] = {
86 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
87 { }
88};
89MODULE_DEVICE_TABLE(hid, sony_devices);
90
91static struct hid_driver sony_driver = {
92 .name = "sony",
93 .id_table = sony_devices,
94 .probe = sony_probe,
95};
96
97static int sony_init(void)
98{
99 return hid_register_driver(&sony_driver);
100}
101
102static void sony_exit(void)
103{
104 hid_unregister_driver(&sony_driver);
105}
106
107module_init(sony_init);
108module_exit(sony_exit);
109MODULE_LICENSE("GPL");
110
111HID_COMPAT_LOAD_DRIVER(sony);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index e900d597bc2d..b41d0110a75e 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -670,32 +670,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
670 usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); 670 usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
671} 671}
672 672
673/*
674 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
675 * to "operational". Without this, the ps3 controller will not report any
676 * events.
677 */
678static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
679{
680 int result;
681 char *buf = kmalloc(18, GFP_KERNEL);
682
683 if (!buf)
684 return;
685
686 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
687 HID_REQ_GET_REPORT,
688 USB_DIR_IN | USB_TYPE_CLASS |
689 USB_RECIP_INTERFACE,
690 (3 << 8) | 0xf2, ifnum, buf, 17,
691 USB_CTRL_GET_TIMEOUT);
692
693 if (result < 0)
694 err_hid("%s failed: %d\n", __func__, result);
695
696 kfree(buf);
697}
698
699static int usbhid_start_finish(struct hid_device *hid) 673static int usbhid_start_finish(struct hid_device *hid)
700{ 674{
701 struct usb_interface *intf = to_usb_interface(hid->dev.parent); 675 struct usb_interface *intf = to_usb_interface(hid->dev.parent);
@@ -723,10 +697,6 @@ static int usbhid_start_finish(struct hid_device *hid)
723 if ((hid->claimed & HID_CLAIMED_INPUT)) 697 if ((hid->claimed & HID_CLAIMED_INPUT))
724 hid_ff_init(hid); 698 hid_ff_init(hid);
725 699
726 if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
727 hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
728 intf->cur_altsetting->desc.bInterfaceNumber);
729
730 printk(KERN_INFO); 700 printk(KERN_INFO);
731 701
732 if (hid->claimed & HID_CLAIMED_INPUT) 702 if (hid->claimed & HID_CLAIMED_INPUT)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f66d2e43b5d5..a154a7dc1e63 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -46,8 +46,6 @@ static const struct hid_blacklist {
46 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, 46 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
47 { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, 47 { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
48 48
49 { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
50
51 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, 49 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
52 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, 50 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
53 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, 51 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 9eac330a1dfa..43aa51a7fa95 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -262,7 +262,6 @@ struct hid_item {
262#define HID_QUIRK_BADPAD 0x00000020 262#define HID_QUIRK_BADPAD 0x00000020
263#define HID_QUIRK_MULTI_INPUT 0x00000040 263#define HID_QUIRK_MULTI_INPUT 0x00000040
264#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 264#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
265#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
266#define HID_QUIRK_RESET_LEDS 0x00100000 265#define HID_QUIRK_RESET_LEDS 0x00100000
267#define HID_QUIRK_HIDINPUT 0x00200000 266#define HID_QUIRK_HIDINPUT 0x00200000
268#define HID_QUIRK_IGNORE_HIDINPUT 0x01000000 267#define HID_QUIRK_IGNORE_HIDINPUT 0x01000000