aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/joystick/xpad.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 0380597249bb..8804ad30dae2 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -91,6 +91,7 @@
91 91
92#define XTYPE_XBOX 0 92#define XTYPE_XBOX 0
93#define XTYPE_XBOX360 1 93#define XTYPE_XBOX360 1
94#define XTYPE_UNKNOWN 2
94 95
95static int dpad_to_buttons; 96static int dpad_to_buttons;
96module_param(dpad_to_buttons, bool, S_IRUGO); 97module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -138,7 +139,7 @@ static const struct xpad_device {
138 { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, 139 { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
139 { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, 140 { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
140 { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, 141 { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
141 { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX } 142 { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
142}; 143};
143 144
144static const signed short xpad_btn[] = { 145static const signed short xpad_btn[] = {
@@ -173,12 +174,20 @@ static const signed short xpad_abs_pad[] = {
173 -1 /* terminating entry */ 174 -1 /* terminating entry */
174}; 175};
175 176
176/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only 177/* Xbox 360 has a vendor-specific class, so we cannot match it with only
177 * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols, 178 * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
178 * but we need only one of them. */ 179 * match against vendor id as well. Also, some Xbox 360 devices have multiple
180 * interface protocols, we only need protocol 1. */
181#define XPAD_XBOX360_VENDOR(vend) \
182 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
183 .idVendor = (vend), \
184 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
185 .bInterfaceSubClass = 93, \
186 .bInterfaceProtocol = 1
187
179static struct usb_device_id xpad_table [] = { 188static struct usb_device_id xpad_table [] = {
180 { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ 189 { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
181 { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */ 190 { XPAD_XBOX360_VENDOR(0x045e) }, /* Microsoft X-Box 360 controllers */
182 { } 191 { }
183}; 192};
184 193
@@ -645,6 +654,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
645 xpad->xtype = xpad_device[i].xtype; 654 xpad->xtype = xpad_device[i].xtype;
646 if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) 655 if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
647 xpad->dpad_mapping = dpad_to_buttons; 656 xpad->dpad_mapping = dpad_to_buttons;
657 if (xpad->xtype == XTYPE_UNKNOWN)
658 xpad->xtype = (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC);
648 xpad->dev = input_dev; 659 xpad->dev = input_dev;
649 usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); 660 usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
650 strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); 661 strlcat(xpad->phys, "/input0", sizeof(xpad->phys));