diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-04-04 15:31:23 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-04-04 15:31:23 -0400 |
commit | f0fab8e04dfe79376b410b48c817f5fe921b345b (patch) | |
tree | d1163e98f6dfe4ad000ba92b06f15ec27d1b477b /drivers | |
parent | 5550fbaeb3cc88fe2982e9b5351073173d733f30 (diff) | |
parent | 6eae9b0acdb6f03ed87ef882760e0ef8f440dc1a (diff) |
Merge branch 'xbox'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/joystick/xpad.c | 211 |
1 files changed, 187 insertions, 24 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 0380597249bb..d4d289e75dc2 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * X-Box gamepad - v0.0.6 | 2 | * X-Box gamepad driver |
3 | * | 3 | * |
4 | * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> | 4 | * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> |
5 | * 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>, | 5 | * 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>, |
@@ -68,6 +68,8 @@ | |||
68 | * - dance pads will map D-PAD to buttons, not axes | 68 | * - dance pads will map D-PAD to buttons, not axes |
69 | * - pass the module paramater 'dpad_to_buttons' to force | 69 | * - pass the module paramater 'dpad_to_buttons' to force |
70 | * the D-PAD to map to buttons if your pad is not detected | 70 | * the D-PAD to map to buttons if your pad is not detected |
71 | * | ||
72 | * Later changes can be tracked in SCM. | ||
71 | */ | 73 | */ |
72 | 74 | ||
73 | #include <linux/kernel.h> | 75 | #include <linux/kernel.h> |
@@ -77,7 +79,6 @@ | |||
77 | #include <linux/module.h> | 79 | #include <linux/module.h> |
78 | #include <linux/usb/input.h> | 80 | #include <linux/usb/input.h> |
79 | 81 | ||
80 | #define DRIVER_VERSION "v0.0.6" | ||
81 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" | 82 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" |
82 | #define DRIVER_DESC "X-Box pad driver" | 83 | #define DRIVER_DESC "X-Box pad driver" |
83 | 84 | ||
@@ -87,10 +88,12 @@ | |||
87 | but we map them to axes when possible to simplify things */ | 88 | but we map them to axes when possible to simplify things */ |
88 | #define MAP_DPAD_TO_BUTTONS 0 | 89 | #define MAP_DPAD_TO_BUTTONS 0 |
89 | #define MAP_DPAD_TO_AXES 1 | 90 | #define MAP_DPAD_TO_AXES 1 |
90 | #define MAP_DPAD_UNKNOWN -1 | 91 | #define MAP_DPAD_UNKNOWN 2 |
91 | 92 | ||
92 | #define XTYPE_XBOX 0 | 93 | #define XTYPE_XBOX 0 |
93 | #define XTYPE_XBOX360 1 | 94 | #define XTYPE_XBOX360 1 |
95 | #define XTYPE_XBOX360W 2 | ||
96 | #define XTYPE_UNKNOWN 3 | ||
94 | 97 | ||
95 | static int dpad_to_buttons; | 98 | static int dpad_to_buttons; |
96 | module_param(dpad_to_buttons, bool, S_IRUGO); | 99 | module_param(dpad_to_buttons, bool, S_IRUGO); |
@@ -107,8 +110,10 @@ static const struct xpad_device { | |||
107 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 110 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
108 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 111 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
109 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 112 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
113 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | ||
110 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 114 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
111 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 115 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
116 | { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | ||
112 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 117 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
113 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 118 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
114 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 119 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
@@ -135,18 +140,26 @@ static const struct xpad_device { | |||
135 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 140 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
136 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 141 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
137 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 142 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
143 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | ||
138 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 144 | { 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 }, | 145 | { 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 }, | 146 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
141 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX } | 147 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } |
142 | }; | 148 | }; |
143 | 149 | ||
144 | static const signed short xpad_btn[] = { | 150 | /* buttons shared with xbox and xbox360 */ |
145 | BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */ | 151 | static const signed short xpad_common_btn[] = { |
152 | BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */ | ||
146 | BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ | 153 | BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ |
147 | -1 /* terminating entry */ | 154 | -1 /* terminating entry */ |
148 | }; | 155 | }; |
149 | 156 | ||
157 | /* original xbox controllers only */ | ||
158 | static const signed short xpad_btn[] = { | ||
159 | BTN_C, BTN_Z, /* "analog" buttons */ | ||
160 | -1 /* terminating entry */ | ||
161 | }; | ||
162 | |||
150 | /* only used if MAP_DPAD_TO_BUTTONS */ | 163 | /* only used if MAP_DPAD_TO_BUTTONS */ |
151 | static const signed short xpad_btn_pad[] = { | 164 | static const signed short xpad_btn_pad[] = { |
152 | BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ | 165 | BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ |
@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = { | |||
173 | -1 /* terminating entry */ | 186 | -1 /* terminating entry */ |
174 | }; | 187 | }; |
175 | 188 | ||
176 | /* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only | 189 | /* 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, | 190 | * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we |
178 | * but we need only one of them. */ | 191 | * match against vendor id as well. Wired Xbox 360 devices have protocol 1, |
192 | * wireless controllers have protocol 129. */ | ||
193 | #define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ | ||
194 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ | ||
195 | .idVendor = (vend), \ | ||
196 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ | ||
197 | .bInterfaceSubClass = 93, \ | ||
198 | .bInterfaceProtocol = (pr) | ||
199 | #define XPAD_XBOX360_VENDOR(vend) \ | ||
200 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ | ||
201 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } | ||
202 | |||
179 | static struct usb_device_id xpad_table [] = { | 203 | static struct usb_device_id xpad_table [] = { |
180 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | 204 | { 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 */ | 205 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ |
206 | XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ | ||
207 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | ||
208 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ | ||
209 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | ||
182 | { } | 210 | { } |
183 | }; | 211 | }; |
184 | 212 | ||
@@ -188,10 +216,15 @@ struct usb_xpad { | |||
188 | struct input_dev *dev; /* input device interface */ | 216 | struct input_dev *dev; /* input device interface */ |
189 | struct usb_device *udev; /* usb device */ | 217 | struct usb_device *udev; /* usb device */ |
190 | 218 | ||
219 | int pad_present; | ||
220 | |||
191 | struct urb *irq_in; /* urb for interrupt in report */ | 221 | struct urb *irq_in; /* urb for interrupt in report */ |
192 | unsigned char *idata; /* input data */ | 222 | unsigned char *idata; /* input data */ |
193 | dma_addr_t idata_dma; | 223 | dma_addr_t idata_dma; |
194 | 224 | ||
225 | struct urb *bulk_out; | ||
226 | unsigned char *bdata; | ||
227 | |||
195 | #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) | 228 | #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) |
196 | struct urb *irq_out; /* urb for interrupt out report */ | 229 | struct urb *irq_out; /* urb for interrupt out report */ |
197 | unsigned char *odata; /* output data */ | 230 | unsigned char *odata; /* output data */ |
@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
227 | input_report_abs(dev, ABS_X, | 260 | input_report_abs(dev, ABS_X, |
228 | (__s16) le16_to_cpup((__le16 *)(data + 12))); | 261 | (__s16) le16_to_cpup((__le16 *)(data + 12))); |
229 | input_report_abs(dev, ABS_Y, | 262 | input_report_abs(dev, ABS_Y, |
230 | (__s16) le16_to_cpup((__le16 *)(data + 14))); | 263 | ~(__s16) le16_to_cpup((__le16 *)(data + 14))); |
231 | 264 | ||
232 | /* right stick */ | 265 | /* right stick */ |
233 | input_report_abs(dev, ABS_RX, | 266 | input_report_abs(dev, ABS_RX, |
234 | (__s16) le16_to_cpup((__le16 *)(data + 16))); | 267 | (__s16) le16_to_cpup((__le16 *)(data + 16))); |
235 | input_report_abs(dev, ABS_RY, | 268 | input_report_abs(dev, ABS_RY, |
236 | (__s16) le16_to_cpup((__le16 *)(data + 18))); | 269 | ~(__s16) le16_to_cpup((__le16 *)(data + 18))); |
237 | 270 | ||
238 | /* triggers left/right */ | 271 | /* triggers left/right */ |
239 | input_report_abs(dev, ABS_Z, data[10]); | 272 | input_report_abs(dev, ABS_Z, data[10]); |
@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad, | |||
321 | input_report_abs(dev, ABS_X, | 354 | input_report_abs(dev, ABS_X, |
322 | (__s16) le16_to_cpup((__le16 *)(data + 6))); | 355 | (__s16) le16_to_cpup((__le16 *)(data + 6))); |
323 | input_report_abs(dev, ABS_Y, | 356 | input_report_abs(dev, ABS_Y, |
324 | (__s16) le16_to_cpup((__le16 *)(data + 8))); | 357 | ~(__s16) le16_to_cpup((__le16 *)(data + 8))); |
325 | 358 | ||
326 | /* right stick */ | 359 | /* right stick */ |
327 | input_report_abs(dev, ABS_RX, | 360 | input_report_abs(dev, ABS_RX, |
328 | (__s16) le16_to_cpup((__le16 *)(data + 10))); | 361 | (__s16) le16_to_cpup((__le16 *)(data + 10))); |
329 | input_report_abs(dev, ABS_RY, | 362 | input_report_abs(dev, ABS_RY, |
330 | (__s16) le16_to_cpup((__le16 *)(data + 12))); | 363 | ~(__s16) le16_to_cpup((__le16 *)(data + 12))); |
331 | 364 | ||
332 | /* triggers left/right */ | 365 | /* triggers left/right */ |
333 | input_report_abs(dev, ABS_Z, data[4]); | 366 | input_report_abs(dev, ABS_Z, data[4]); |
@@ -336,6 +369,39 @@ static void xpad360_process_packet(struct usb_xpad *xpad, | |||
336 | input_sync(dev); | 369 | input_sync(dev); |
337 | } | 370 | } |
338 | 371 | ||
372 | /* | ||
373 | * xpad360w_process_packet | ||
374 | * | ||
375 | * Completes a request by converting the data into events for the | ||
376 | * input subsystem. It is version for xbox 360 wireless controller. | ||
377 | * | ||
378 | * Byte.Bit | ||
379 | * 00.1 - Status change: The controller or headset has connected/disconnected | ||
380 | * Bits 01.7 and 01.6 are valid | ||
381 | * 01.7 - Controller present | ||
382 | * 01.6 - Headset present | ||
383 | * 01.1 - Pad state (Bytes 4+) valid | ||
384 | * | ||
385 | */ | ||
386 | |||
387 | static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) | ||
388 | { | ||
389 | /* Presence change */ | ||
390 | if (data[0] & 0x08) { | ||
391 | if (data[1] & 0x80) { | ||
392 | xpad->pad_present = 1; | ||
393 | usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); | ||
394 | } else | ||
395 | xpad->pad_present = 0; | ||
396 | } | ||
397 | |||
398 | /* Valid pad data */ | ||
399 | if (!(data[1] & 0x1)) | ||
400 | return; | ||
401 | |||
402 | xpad360_process_packet(xpad, cmd, &data[4]); | ||
403 | } | ||
404 | |||
339 | static void xpad_irq_in(struct urb *urb) | 405 | static void xpad_irq_in(struct urb *urb) |
340 | { | 406 | { |
341 | struct usb_xpad *xpad = urb->context; | 407 | struct usb_xpad *xpad = urb->context; |
@@ -358,10 +424,16 @@ static void xpad_irq_in(struct urb *urb) | |||
358 | goto exit; | 424 | goto exit; |
359 | } | 425 | } |
360 | 426 | ||
361 | if (xpad->xtype == XTYPE_XBOX360) | 427 | switch (xpad->xtype) { |
428 | case XTYPE_XBOX360: | ||
362 | xpad360_process_packet(xpad, 0, xpad->idata); | 429 | xpad360_process_packet(xpad, 0, xpad->idata); |
363 | else | 430 | break; |
431 | case XTYPE_XBOX360W: | ||
432 | xpad360w_process_packet(xpad, 0, xpad->idata); | ||
433 | break; | ||
434 | default: | ||
364 | xpad_process_packet(xpad, 0, xpad->idata); | 435 | xpad_process_packet(xpad, 0, xpad->idata); |
436 | } | ||
365 | 437 | ||
366 | exit: | 438 | exit: |
367 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 439 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
@@ -399,6 +471,23 @@ exit: | |||
399 | __FUNCTION__, retval); | 471 | __FUNCTION__, retval); |
400 | } | 472 | } |
401 | 473 | ||
474 | static void xpad_bulk_out(struct urb *urb) | ||
475 | { | ||
476 | switch (urb->status) { | ||
477 | case 0: | ||
478 | /* success */ | ||
479 | break; | ||
480 | case -ECONNRESET: | ||
481 | case -ENOENT: | ||
482 | case -ESHUTDOWN: | ||
483 | /* this urb is terminated, clean up */ | ||
484 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
485 | break; | ||
486 | default: | ||
487 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
488 | } | ||
489 | } | ||
490 | |||
402 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | 491 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) |
403 | { | 492 | { |
404 | struct usb_endpoint_descriptor *ep_irq_out; | 493 | struct usb_endpoint_descriptor *ep_irq_out; |
@@ -408,7 +497,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
408 | return 0; | 497 | return 0; |
409 | 498 | ||
410 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, | 499 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, |
411 | GFP_ATOMIC, &xpad->odata_dma ); | 500 | GFP_KERNEL, &xpad->odata_dma); |
412 | if (!xpad->odata) | 501 | if (!xpad->odata) |
413 | goto fail1; | 502 | goto fail1; |
414 | 503 | ||
@@ -477,6 +566,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data, | |||
477 | 566 | ||
478 | static int xpad_init_ff(struct usb_xpad *xpad) | 567 | static int xpad_init_ff(struct usb_xpad *xpad) |
479 | { | 568 | { |
569 | if (xpad->xtype != XTYPE_XBOX360) | ||
570 | return 0; | ||
571 | |||
480 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); | 572 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); |
481 | 573 | ||
482 | return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect); | 574 | return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect); |
@@ -574,6 +666,10 @@ static int xpad_open(struct input_dev *dev) | |||
574 | { | 666 | { |
575 | struct usb_xpad *xpad = input_get_drvdata(dev); | 667 | struct usb_xpad *xpad = input_get_drvdata(dev); |
576 | 668 | ||
669 | /* URB was submitted in probe */ | ||
670 | if(xpad->xtype == XTYPE_XBOX360W) | ||
671 | return 0; | ||
672 | |||
577 | xpad->irq_in->dev = xpad->udev; | 673 | xpad->irq_in->dev = xpad->udev; |
578 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) | 674 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) |
579 | return -EIO; | 675 | return -EIO; |
@@ -585,7 +681,8 @@ static void xpad_close(struct input_dev *dev) | |||
585 | { | 681 | { |
586 | struct usb_xpad *xpad = input_get_drvdata(dev); | 682 | struct usb_xpad *xpad = input_get_drvdata(dev); |
587 | 683 | ||
588 | usb_kill_urb(xpad->irq_in); | 684 | if(xpad->xtype != XTYPE_XBOX360W) |
685 | usb_kill_urb(xpad->irq_in); | ||
589 | xpad_stop_output(xpad); | 686 | xpad_stop_output(xpad); |
590 | } | 687 | } |
591 | 688 | ||
@@ -632,7 +729,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
632 | goto fail1; | 729 | goto fail1; |
633 | 730 | ||
634 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | 731 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, |
635 | GFP_ATOMIC, &xpad->idata_dma); | 732 | GFP_KERNEL, &xpad->idata_dma); |
636 | if (!xpad->idata) | 733 | if (!xpad->idata) |
637 | goto fail1; | 734 | goto fail1; |
638 | 735 | ||
@@ -644,7 +741,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
644 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; | 741 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; |
645 | xpad->xtype = xpad_device[i].xtype; | 742 | xpad->xtype = xpad_device[i].xtype; |
646 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) | 743 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) |
647 | xpad->dpad_mapping = dpad_to_buttons; | 744 | xpad->dpad_mapping = !dpad_to_buttons; |
745 | if (xpad->xtype == XTYPE_UNKNOWN) { | ||
746 | if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { | ||
747 | if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) | ||
748 | xpad->xtype = XTYPE_XBOX360W; | ||
749 | else | ||
750 | xpad->xtype = XTYPE_XBOX360; | ||
751 | } else | ||
752 | xpad->xtype = XTYPE_XBOX; | ||
753 | } | ||
648 | xpad->dev = input_dev; | 754 | xpad->dev = input_dev; |
649 | usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); | 755 | usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); |
650 | strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); | 756 | strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); |
@@ -662,11 +768,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
662 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 768 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
663 | 769 | ||
664 | /* set up buttons */ | 770 | /* set up buttons */ |
665 | for (i = 0; xpad_btn[i] >= 0; i++) | 771 | for (i = 0; xpad_common_btn[i] >= 0; i++) |
666 | set_bit(xpad_btn[i], input_dev->keybit); | 772 | set_bit(xpad_common_btn[i], input_dev->keybit); |
667 | if (xpad->xtype == XTYPE_XBOX360) | 773 | if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W)) |
668 | for (i = 0; xpad360_btn[i] >= 0; i++) | 774 | for (i = 0; xpad360_btn[i] >= 0; i++) |
669 | set_bit(xpad360_btn[i], input_dev->keybit); | 775 | set_bit(xpad360_btn[i], input_dev->keybit); |
776 | else | ||
777 | for (i = 0; xpad_btn[i] >= 0; i++) | ||
778 | set_bit(xpad_btn[i], input_dev->keybit); | ||
670 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) | 779 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) |
671 | for (i = 0; xpad_btn_pad[i] >= 0; i++) | 780 | for (i = 0; xpad_btn_pad[i] >= 0; i++) |
672 | set_bit(xpad_btn_pad[i], input_dev->keybit); | 781 | set_bit(xpad_btn_pad[i], input_dev->keybit); |
@@ -703,8 +812,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
703 | goto fail4; | 812 | goto fail4; |
704 | 813 | ||
705 | usb_set_intfdata(intf, xpad); | 814 | usb_set_intfdata(intf, xpad); |
815 | |||
816 | /* | ||
817 | * Submit the int URB immediatly rather than waiting for open | ||
818 | * because we get status messages from the device whether | ||
819 | * or not any controllers are attached. In fact, it's | ||
820 | * exactly the message that a controller has arrived that | ||
821 | * we're waiting for. | ||
822 | */ | ||
823 | if (xpad->xtype == XTYPE_XBOX360W) { | ||
824 | xpad->irq_in->dev = xpad->udev; | ||
825 | error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); | ||
826 | if (error) | ||
827 | goto fail4; | ||
828 | |||
829 | /* | ||
830 | * Setup the message to set the LEDs on the | ||
831 | * controller when it shows up | ||
832 | */ | ||
833 | xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); | ||
834 | if(!xpad->bulk_out) | ||
835 | goto fail5; | ||
836 | |||
837 | xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); | ||
838 | if(!xpad->bdata) | ||
839 | goto fail6; | ||
840 | |||
841 | xpad->bdata[2] = 0x08; | ||
842 | switch (intf->cur_altsetting->desc.bInterfaceNumber) { | ||
843 | case 0: | ||
844 | xpad->bdata[3] = 0x42; | ||
845 | break; | ||
846 | case 2: | ||
847 | xpad->bdata[3] = 0x43; | ||
848 | break; | ||
849 | case 4: | ||
850 | xpad->bdata[3] = 0x44; | ||
851 | break; | ||
852 | case 6: | ||
853 | xpad->bdata[3] = 0x45; | ||
854 | } | ||
855 | |||
856 | ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; | ||
857 | usb_fill_bulk_urb(xpad->bulk_out, udev, | ||
858 | usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), | ||
859 | xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); | ||
860 | } | ||
861 | |||
706 | return 0; | 862 | return 0; |
707 | 863 | ||
864 | fail6: usb_free_urb(xpad->bulk_out); | ||
865 | fail5: usb_kill_urb(xpad->irq_in); | ||
708 | fail4: usb_free_urb(xpad->irq_in); | 866 | fail4: usb_free_urb(xpad->irq_in); |
709 | fail3: xpad_deinit_output(xpad); | 867 | fail3: xpad_deinit_output(xpad); |
710 | fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | 868 | fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); |
@@ -723,6 +881,11 @@ static void xpad_disconnect(struct usb_interface *intf) | |||
723 | xpad_led_disconnect(xpad); | 881 | xpad_led_disconnect(xpad); |
724 | input_unregister_device(xpad->dev); | 882 | input_unregister_device(xpad->dev); |
725 | xpad_deinit_output(xpad); | 883 | xpad_deinit_output(xpad); |
884 | if (xpad->xtype == XTYPE_XBOX360W) { | ||
885 | usb_kill_urb(xpad->bulk_out); | ||
886 | usb_free_urb(xpad->bulk_out); | ||
887 | usb_kill_urb(xpad->irq_in); | ||
888 | } | ||
726 | usb_free_urb(xpad->irq_in); | 889 | usb_free_urb(xpad->irq_in); |
727 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, | 890 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, |
728 | xpad->idata, xpad->idata_dma); | 891 | xpad->idata, xpad->idata_dma); |
@@ -741,7 +904,7 @@ static int __init usb_xpad_init(void) | |||
741 | { | 904 | { |
742 | int result = usb_register(&xpad_driver); | 905 | int result = usb_register(&xpad_driver); |
743 | if (result == 0) | 906 | if (result == 0) |
744 | info(DRIVER_DESC ":" DRIVER_VERSION); | 907 | info(DRIVER_DESC); |
745 | return result; | 908 | return result; |
746 | } | 909 | } |
747 | 910 | ||