aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorBrian Magnuson <bdmagnuson@gmail.com>2008-04-03 16:19:23 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-04-03 16:19:23 -0400
commit99de0912be6f384fc31c8e8e7ba0850d0d670385 (patch)
tree89b41c3879a023544d174270c0437597d3748bb8 /drivers/input
parentbf8cb3141884138c2e4a2ecb56300ece6e8020a2 (diff)
Input: xpad - add support for wireless xbox360 controllers
Signed-off-by: Brian Magnuson <bdmagnuson@gmail.com> Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/joystick/xpad.c164
1 files changed, 148 insertions, 16 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 7188eec53cc6..ebf8303d6f56 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -92,7 +92,8 @@
92 92
93#define XTYPE_XBOX 0 93#define XTYPE_XBOX 0
94#define XTYPE_XBOX360 1 94#define XTYPE_XBOX360 1
95#define XTYPE_UNKNOWN 2 95#define XTYPE_XBOX360W 2
96#define XTYPE_UNKNOWN 3
96 97
97static int dpad_to_buttons; 98static int dpad_to_buttons;
98module_param(dpad_to_buttons, bool, S_IRUGO); 99module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -109,6 +110,7 @@ static const struct xpad_device {
109 { 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 },
110 { 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 },
111 { 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 },
112 { 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 },
113 { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, 115 { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
114 { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, 116 { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
@@ -186,22 +188,25 @@ static const signed short xpad_abs_pad[] = {
186 188
187/* Xbox 360 has a vendor-specific class, so we cannot match it with only 189/* Xbox 360 has a vendor-specific class, so we cannot match it with only
188 * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we 190 * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
189 * match against vendor id as well. Also, some Xbox 360 devices have multiple 191 * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
190 * interface protocols, we only need protocol 1. */ 192 * wireless controllers have protocol 129. */
191#define XPAD_XBOX360_VENDOR(vend) \ 193#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
192 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ 194 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
193 .idVendor = (vend), \ 195 .idVendor = (vend), \
194 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ 196 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
195 .bInterfaceSubClass = 93, \ 197 .bInterfaceSubClass = 93, \
196 .bInterfaceProtocol = 1 198 .bInterfaceProtocol = (pr)
199#define XPAD_XBOX360_VENDOR(vend) \
200 { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
201 { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
197 202
198static struct usb_device_id xpad_table [] = { 203static struct usb_device_id xpad_table [] = {
199 { 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 */
200 { XPAD_XBOX360_VENDOR(0x045e) }, /* Microsoft X-Box 360 controllers */ 205 XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
201 { XPAD_XBOX360_VENDOR(0x046d) }, /* Logitech X-Box 360 style controllers */ 206 XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
202 { XPAD_XBOX360_VENDOR(0x0738) }, /* Mad Catz X-Box 360 controllers */ 207 XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
203 { XPAD_XBOX360_VENDOR(0x0e6f) }, /* 0x0e6f X-Box 360 controllers */ 208 XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
204 { XPAD_XBOX360_VENDOR(0x1430) }, /* RedOctane X-Box 360 controllers */ 209 XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
205 { } 210 { }
206}; 211};
207 212
@@ -211,10 +216,15 @@ struct usb_xpad {
211 struct input_dev *dev; /* input device interface */ 216 struct input_dev *dev; /* input device interface */
212 struct usb_device *udev; /* usb device */ 217 struct usb_device *udev; /* usb device */
213 218
219 int pad_present;
220
214 struct urb *irq_in; /* urb for interrupt in report */ 221 struct urb *irq_in; /* urb for interrupt in report */
215 unsigned char *idata; /* input data */ 222 unsigned char *idata; /* input data */
216 dma_addr_t idata_dma; 223 dma_addr_t idata_dma;
217 224
225 struct urb *bulk_out;
226 unsigned char *bdata;
227
218#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) 228#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
219 struct urb *irq_out; /* urb for interrupt out report */ 229 struct urb *irq_out; /* urb for interrupt out report */
220 unsigned char *odata; /* output data */ 230 unsigned char *odata; /* output data */
@@ -359,6 +369,39 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
359 input_sync(dev); 369 input_sync(dev);
360} 370}
361 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
387static 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
362static void xpad_irq_in(struct urb *urb) 405static void xpad_irq_in(struct urb *urb)
363{ 406{
364 struct usb_xpad *xpad = urb->context; 407 struct usb_xpad *xpad = urb->context;
@@ -381,10 +424,16 @@ static void xpad_irq_in(struct urb *urb)
381 goto exit; 424 goto exit;
382 } 425 }
383 426
384 if (xpad->xtype == XTYPE_XBOX360) 427 switch (xpad->xtype) {
428 case XTYPE_XBOX360:
385 xpad360_process_packet(xpad, 0, xpad->idata); 429 xpad360_process_packet(xpad, 0, xpad->idata);
386 else 430 break;
431 case XTYPE_XBOX360W:
432 xpad360w_process_packet(xpad, 0, xpad->idata);
433 break;
434 default:
387 xpad_process_packet(xpad, 0, xpad->idata); 435 xpad_process_packet(xpad, 0, xpad->idata);
436 }
388 437
389exit: 438exit:
390 retval = usb_submit_urb (urb, GFP_ATOMIC); 439 retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -422,6 +471,23 @@ exit:
422 __FUNCTION__, retval); 471 __FUNCTION__, retval);
423} 472}
424 473
474static 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
425static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) 491static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
426{ 492{
427 struct usb_endpoint_descriptor *ep_irq_out; 493 struct usb_endpoint_descriptor *ep_irq_out;
@@ -600,6 +666,10 @@ static int xpad_open(struct input_dev *dev)
600{ 666{
601 struct usb_xpad *xpad = input_get_drvdata(dev); 667 struct usb_xpad *xpad = input_get_drvdata(dev);
602 668
669 /* URB was submitted in probe */
670 if(xpad->xtype == XTYPE_XBOX360W)
671 return 0;
672
603 xpad->irq_in->dev = xpad->udev; 673 xpad->irq_in->dev = xpad->udev;
604 if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) 674 if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
605 return -EIO; 675 return -EIO;
@@ -611,7 +681,8 @@ static void xpad_close(struct input_dev *dev)
611{ 681{
612 struct usb_xpad *xpad = input_get_drvdata(dev); 682 struct usb_xpad *xpad = input_get_drvdata(dev);
613 683
614 usb_kill_urb(xpad->irq_in); 684 if(xpad->xtype != XTYPE_XBOX360W)
685 usb_kill_urb(xpad->irq_in);
615 xpad_stop_output(xpad); 686 xpad_stop_output(xpad);
616} 687}
617 688
@@ -671,8 +742,15 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
671 xpad->xtype = xpad_device[i].xtype; 742 xpad->xtype = xpad_device[i].xtype;
672 if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) 743 if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
673 xpad->dpad_mapping = !dpad_to_buttons; 744 xpad->dpad_mapping = !dpad_to_buttons;
674 if (xpad->xtype == XTYPE_UNKNOWN) 745 if (xpad->xtype == XTYPE_UNKNOWN) {
675 xpad->xtype = (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC); 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 }
676 xpad->dev = input_dev; 754 xpad->dev = input_dev;
677 usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); 755 usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
678 strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); 756 strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
@@ -692,7 +770,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
692 /* set up buttons */ 770 /* set up buttons */
693 for (i = 0; xpad_common_btn[i] >= 0; i++) 771 for (i = 0; xpad_common_btn[i] >= 0; i++)
694 set_bit(xpad_common_btn[i], input_dev->keybit); 772 set_bit(xpad_common_btn[i], input_dev->keybit);
695 if (xpad->xtype == XTYPE_XBOX360) 773 if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
696 for (i = 0; xpad360_btn[i] >= 0; i++) 774 for (i = 0; xpad360_btn[i] >= 0; i++)
697 set_bit(xpad360_btn[i], input_dev->keybit); 775 set_bit(xpad360_btn[i], input_dev->keybit);
698 else 776 else
@@ -734,8 +812,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
734 goto fail4; 812 goto fail4;
735 813
736 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
737 return 0; 862 return 0;
738 863
864 fail6: usb_free_urb(xpad->bulk_out);
865 fail5: usb_kill_urb(xpad->irq_in);
739 fail4: usb_free_urb(xpad->irq_in); 866 fail4: usb_free_urb(xpad->irq_in);
740 fail3: xpad_deinit_output(xpad); 867 fail3: xpad_deinit_output(xpad);
741 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);
@@ -754,6 +881,11 @@ static void xpad_disconnect(struct usb_interface *intf)
754 xpad_led_disconnect(xpad); 881 xpad_led_disconnect(xpad);
755 input_unregister_device(xpad->dev); 882 input_unregister_device(xpad->dev);
756 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 }
757 usb_free_urb(xpad->irq_in); 889 usb_free_urb(xpad->irq_in);
758 usb_buffer_free(xpad->udev, XPAD_PKT_LEN, 890 usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
759 xpad->idata, xpad->idata_dma); 891 xpad->idata, xpad->idata_dma);