aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/input/hid-core.c35
-rw-r--r--include/linux/hid.h1
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index e07a30490726..84983d1b7164 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -768,6 +768,9 @@ void usbhid_init_reports(struct hid_device *hid)
768#define USB_VENDOR_ID_PANTHERLORD 0x0810 768#define USB_VENDOR_ID_PANTHERLORD 0x0810
769#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 769#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
770 770
771#define USB_VENDOR_ID_SONY 0x054c
772#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
773
771/* 774/*
772 * Alphabetically sorted blacklist by quirk type. 775 * Alphabetically sorted blacklist by quirk type.
773 */ 776 */
@@ -949,6 +952,8 @@ static const struct hid_blacklist {
949 952
950 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, 953 { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
951 954
955 { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
956
952 { 0, 0 } 957 { 0, 0 }
953}; 958};
954 959
@@ -1013,6 +1018,32 @@ static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
1013 } 1018 }
1014} 1019}
1015 1020
1021/*
1022 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1023 * to "operational". Without this, the ps3 controller will not report any
1024 * events.
1025 */
1026static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
1027{
1028 int result;
1029 char *buf = kmalloc(18, GFP_KERNEL);
1030
1031 if (!buf)
1032 return;
1033
1034 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1035 HID_REQ_GET_REPORT,
1036 USB_DIR_IN | USB_TYPE_CLASS |
1037 USB_RECIP_INTERFACE,
1038 (3 << 8) | 0xf2, ifnum, buf, 17,
1039 USB_CTRL_GET_TIMEOUT);
1040
1041 if (result < 0)
1042 err("%s failed: %d\n", __func__, result);
1043
1044 kfree(buf);
1045}
1046
1016static struct hid_device *usb_hid_configure(struct usb_interface *intf) 1047static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1017{ 1048{
1018 struct usb_host_interface *interface = intf->cur_altsetting; 1049 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1303,6 +1334,10 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
1303 if ((hid->claimed & HID_CLAIMED_INPUT)) 1334 if ((hid->claimed & HID_CLAIMED_INPUT))
1304 hid_ff_init(hid); 1335 hid_ff_init(hid);
1305 1336
1337 if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
1338 hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
1339 intf->cur_altsetting->desc.bInterfaceNumber);
1340
1306 printk(KERN_INFO); 1341 printk(KERN_INFO);
1307 1342
1308 if (hid->claimed & HID_CLAIMED_INPUT) 1343 if (hid->claimed & HID_CLAIMED_INPUT)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 93173fe45634..d26b08f461f2 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -266,6 +266,7 @@ struct hid_item {
266#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 266#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
267#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 267#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
268#define HID_QUIRK_IGNORE_MOUSE 0x00040000 268#define HID_QUIRK_IGNORE_MOUSE 0x00040000
269#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
269 270
270/* 271/*
271 * This is the global environment of the parser. This information is 272 * This is the global environment of the parser. This information is