diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/joystick/xpad.c | 21 |
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 | ||
95 | static int dpad_to_buttons; | 96 | static int dpad_to_buttons; |
96 | module_param(dpad_to_buttons, bool, S_IRUGO); | 97 | module_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 | ||
144 | static const signed short xpad_btn[] = { | 145 | static 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 | |||
179 | static struct usb_device_id xpad_table [] = { | 188 | static 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)); |