diff options
Diffstat (limited to 'drivers/input/joystick/xpad.c')
| -rw-r--r-- | drivers/input/joystick/xpad.c | 243 | 
1 files changed, 150 insertions, 93 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f9fb7fa10af..603fe0dd368 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -74,7 +74,6 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/stat.h>  #include <linux/module.h> @@ -98,15 +97,15 @@  #define XTYPE_XBOX360W    2  #define XTYPE_UNKNOWN     3 -static int dpad_to_buttons; +static bool dpad_to_buttons;  module_param(dpad_to_buttons, bool, S_IRUGO);  MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); -static int triggers_to_buttons; +static bool triggers_to_buttons;  module_param(triggers_to_buttons, bool, S_IRUGO);  MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); -static int sticks_to_null; +static bool sticks_to_null;  module_param(sticks_to_null, bool, S_IRUGO);  MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads"); @@ -118,12 +117,15 @@ static const struct xpad_device {  	u8 xtype;  } xpad_device[] = {  	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, -	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },  	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },  	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, +	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, +	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, +	{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },  	{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, -	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX },  	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, +	{ 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, +	{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },  	{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },  	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },  	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, @@ -136,31 +138,44 @@ static const struct xpad_device {  	{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },  	{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX },  	{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, +	{ 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },  	{ 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },  	{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, +	{ 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 },  	{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, +	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX },  	{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },  	{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },  	{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, +	{ 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },  	{ 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },  	{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },  	{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },  	{ 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX },  	{ 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, -	{ 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, +	{ 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },  	{ 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, +	{ 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },  	{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, +	{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, +	{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },  	{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },  	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },  	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, +	{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },  	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },  	{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },  	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },  	{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, -	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, +	{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, +	{ 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, +	{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },  	{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, -	{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, -	{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, +	{ 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, +	{ 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, +	{ 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, +	{ 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, +	{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },  	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },  	{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }  }; @@ -230,24 +245,29 @@ static const signed short xpad_abs_triggers[] = {  	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \  	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } -static struct usb_device_id xpad_table [] = { +static struct usb_device_id xpad_table[] = {  	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */  	XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */  	XPAD_XBOX360_VENDOR(0x046d),		/* Logitech X-Box 360 style controllers */  	XPAD_XBOX360_VENDOR(0x0738),		/* Mad Catz X-Box 360 controllers */ +	{ USB_DEVICE(0x0738, 0x4540) },		/* Mad Catz Beat Pad */  	XPAD_XBOX360_VENDOR(0x0e6f),		/* 0x0e6f X-Box 360 controllers */ +	XPAD_XBOX360_VENDOR(0x12ab),		/* X-Box 360 dance pads */  	XPAD_XBOX360_VENDOR(0x1430),		/* RedOctane X-Box 360 controllers */  	XPAD_XBOX360_VENDOR(0x146b),		/* BigBen Interactive Controllers */ -	XPAD_XBOX360_VENDOR(0x1bad),		/* Rock Band Drums */ -	XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */ +	XPAD_XBOX360_VENDOR(0x1bad),		/* Harminix Rock Band Guitar and Drums */ +	XPAD_XBOX360_VENDOR(0x0f0d),		/* Hori Controllers */ +	XPAD_XBOX360_VENDOR(0x1689),		/* Razer Onza */ +	XPAD_XBOX360_VENDOR(0x24c6),		/* PowerA Controllers */  	{ }  }; -MODULE_DEVICE_TABLE (usb, xpad_table); +MODULE_DEVICE_TABLE(usb, xpad_table);  struct usb_xpad {  	struct input_dev *dev;		/* input device interface */  	struct usb_device *udev;	/* usb device */ +	struct usb_interface *intf;	/* usb interface */  	int pad_present; @@ -453,6 +473,7 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha  static void xpad_irq_in(struct urb *urb)  {  	struct usb_xpad *xpad = urb->context; +	struct device *dev = &xpad->intf->dev;  	int retval, status;  	status = urb->status; @@ -465,11 +486,11 @@ static void xpad_irq_in(struct urb *urb)  	case -ENOENT:  	case -ESHUTDOWN:  		/* this urb is terminated, clean up */ -		dbg("%s - urb shutting down with status: %d", +		dev_dbg(dev, "%s - urb shutting down with status: %d\n",  			__func__, status);  		return;  	default: -		dbg("%s - nonzero urb status received: %d", +		dev_dbg(dev, "%s - nonzero urb status received: %d\n",  			__func__, status);  		goto exit;  	} @@ -488,12 +509,15 @@ static void xpad_irq_in(struct urb *urb)  exit:  	retval = usb_submit_urb(urb, GFP_ATOMIC);  	if (retval) -		err ("%s - usb_submit_urb failed with result %d", -		     __func__, retval); +		dev_err(dev, "%s - usb_submit_urb failed with result %d\n", +			__func__, retval);  }  static void xpad_bulk_out(struct urb *urb)  { +	struct usb_xpad *xpad = urb->context; +	struct device *dev = &xpad->intf->dev; +  	switch (urb->status) {  	case 0:  		/* success */ @@ -502,16 +526,20 @@ static void xpad_bulk_out(struct urb *urb)  	case -ENOENT:  	case -ESHUTDOWN:  		/* this urb is terminated, clean up */ -		dbg("%s - urb shutting down with status: %d", __func__, urb->status); +		dev_dbg(dev, "%s - urb shutting down with status: %d\n", +			__func__, urb->status);  		break;  	default: -		dbg("%s - nonzero urb status received: %d", __func__, urb->status); +		dev_dbg(dev, "%s - nonzero urb status received: %d\n", +			__func__, urb->status);  	}  }  #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)  static void xpad_irq_out(struct urb *urb)  { +	struct usb_xpad *xpad = urb->context; +	struct device *dev = &xpad->intf->dev;  	int retval, status;  	status = urb->status; @@ -525,39 +553,45 @@ static void xpad_irq_out(struct urb *urb)  	case -ENOENT:  	case -ESHUTDOWN:  		/* this urb is terminated, clean up */ -		dbg("%s - urb shutting down with status: %d", __func__, status); +		dev_dbg(dev, "%s - urb shutting down with status: %d\n", +			__func__, status);  		return;  	default: -		dbg("%s - nonzero urb status received: %d", __func__, status); +		dev_dbg(dev, "%s - nonzero urb status received: %d\n", +			__func__, status);  		goto exit;  	}  exit:  	retval = usb_submit_urb(urb, GFP_ATOMIC);  	if (retval) -		err("%s - usb_submit_urb failed with result %d", -		    __func__, retval); +		dev_err(dev, "%s - usb_submit_urb failed with result %d\n", +			__func__, retval);  }  static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)  {  	struct usb_endpoint_descriptor *ep_irq_out; -	int error = -ENOMEM; +	int error; -	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) +	if (xpad->xtype == XTYPE_UNKNOWN)  		return 0;  	xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,  					 GFP_KERNEL, &xpad->odata_dma); -	if (!xpad->odata) +	if (!xpad->odata) { +		error = -ENOMEM;  		goto fail1; +	}  	mutex_init(&xpad->odata_mutex);  	xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); -	if (!xpad->irq_out) +	if (!xpad->irq_out) { +		error = -ENOMEM;  		goto fail2; +	}  	ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;  	usb_fill_int_urb(xpad->irq_out, xpad->udev, @@ -575,13 +609,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)  static void xpad_stop_output(struct usb_xpad *xpad)  { -	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) +	if (xpad->xtype != XTYPE_UNKNOWN)  		usb_kill_urb(xpad->irq_out);  }  static void xpad_deinit_output(struct usb_xpad *xpad)  { -	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { +	if (xpad->xtype != XTYPE_UNKNOWN) {  		usb_free_urb(xpad->irq_out);  		usb_free_coherent(xpad->udev, XPAD_PKT_LEN,  				xpad->odata, xpad->odata_dma); @@ -628,8 +662,26 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect  			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); +		case XTYPE_XBOX360W: +			xpad->odata[0] = 0x00; +			xpad->odata[1] = 0x01; +			xpad->odata[2] = 0x0F; +			xpad->odata[3] = 0xC0; +			xpad->odata[4] = 0x00; +			xpad->odata[5] = strong / 256; +			xpad->odata[6] = weak / 256; +			xpad->odata[7] = 0x00; +			xpad->odata[8] = 0x00; +			xpad->odata[9] = 0x00; +			xpad->odata[10] = 0x00; +			xpad->odata[11] = 0x00; +			xpad->irq_out->transfer_buffer_length = 12; + +			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); +  		default: -			dbg("%s - rumble command sent to unsupported xpad type: %d", +			dev_dbg(&xpad->dev->dev, +				"%s - rumble command sent to unsupported xpad type: %d\n",  				__func__, xpad->xtype);  			return -1;  		} @@ -640,7 +692,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect  static int xpad_init_ff(struct usb_xpad *xpad)  { -	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) +	if (xpad->xtype == XTYPE_UNKNOWN)  		return 0;  	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); @@ -728,7 +780,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)  	if (xpad_led) {  		led_classdev_unregister(&xpad_led->led_cdev); -		kfree(xpad_led->name); +		kfree(xpad_led);  	}  }  #else @@ -742,7 +794,7 @@ static int xpad_open(struct input_dev *dev)  	struct usb_xpad *xpad = input_get_drvdata(dev);  	/* URB was submitted in probe */ -	if(xpad->xtype == XTYPE_XBOX360W) +	if (xpad->xtype == XTYPE_XBOX360W)  		return 0;  	xpad->irq_in->dev = xpad->udev; @@ -756,8 +808,9 @@ static void xpad_close(struct input_dev *dev)  {  	struct usb_xpad *xpad = input_get_drvdata(dev); -	if(xpad->xtype != XTYPE_XBOX360W) +	if (xpad->xtype != XTYPE_XBOX360W)  		usb_kill_urb(xpad->irq_in); +  	xpad_stop_output(xpad);  } @@ -789,8 +842,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id  	struct usb_xpad *xpad;  	struct input_dev *input_dev;  	struct usb_endpoint_descriptor *ep_irq_in; -	int i; -	int error = -ENOMEM; +	int i, error;  	for (i = 0; xpad_device[i].idVendor; i++) {  		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && @@ -800,19 +852,26 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id  	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);  	input_dev = input_allocate_device(); -	if (!xpad || !input_dev) +	if (!xpad || !input_dev) { +		error = -ENOMEM;  		goto fail1; +	}  	xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,  					 GFP_KERNEL, &xpad->idata_dma); -	if (!xpad->idata) +	if (!xpad->idata) { +		error = -ENOMEM;  		goto fail1; +	}  	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); -	if (!xpad->irq_in) +	if (!xpad->irq_in) { +		error = -ENOMEM;  		goto fail2; +	}  	xpad->udev = udev; +	xpad->intf = intf;  	xpad->mapping = xpad_device[i].mapping;  	xpad->xtype = xpad_device[i].xtype; @@ -887,15 +946,15 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id  	error = xpad_init_output(intf, xpad);  	if (error) -		goto fail2; +		goto fail3;  	error = xpad_init_ff(xpad);  	if (error) -		goto fail3; +		goto fail4;  	error = xpad_led_probe(xpad);  	if (error) -		goto fail3; +		goto fail5;  	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;  	usb_fill_int_urb(xpad->irq_in, udev, @@ -907,34 +966,26 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id  	error = input_register_device(xpad->dev);  	if (error) -		goto fail4; +		goto fail6;  	usb_set_intfdata(intf, xpad); -	/* -	 * Submit the int URB immediatly rather than waiting for open -	 * because we get status messages from the device whether -	 * or not any controllers are attached.  In fact, it's -	 * exactly the message that a controller has arrived that -	 * we're waiting for. -	 */  	if (xpad->xtype == XTYPE_XBOX360W) { -		xpad->irq_in->dev = xpad->udev; -		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); -		if (error) -			goto fail4; -  		/*  		 * Setup the message to set the LEDs on the  		 * controller when it shows up  		 */  		xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); -		if(!xpad->bulk_out) -			goto fail5; +		if (!xpad->bulk_out) { +			error = -ENOMEM; +			goto fail7; +		}  		xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); -		if(!xpad->bdata) -			goto fail6; +		if (!xpad->bdata) { +			error = -ENOMEM; +			goto fail8; +		}  		xpad->bdata[2] = 0x08;  		switch (intf->cur_altsetting->desc.bInterfaceNumber) { @@ -955,14 +1006,31 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id  		usb_fill_bulk_urb(xpad->bulk_out, udev,  				usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),  				xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); + +		/* +		 * Submit the int URB immediately rather than waiting for open +		 * because we get status messages from the device whether +		 * or not any controllers are attached.  In fact, it's +		 * exactly the message that a controller has arrived that +		 * we're waiting for. +		 */ +		xpad->irq_in->dev = xpad->udev; +		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); +		if (error) +			goto fail9;  	}  	return 0; - fail6:	usb_free_urb(xpad->bulk_out); - fail5:	usb_kill_urb(xpad->irq_in); - fail4:	usb_free_urb(xpad->irq_in); - fail3:	xpad_deinit_output(xpad); + fail9:	kfree(xpad->bdata); + fail8:	usb_free_urb(xpad->bulk_out); + fail7:	input_unregister_device(input_dev); +	input_dev = NULL; + fail6:	xpad_led_disconnect(xpad); + fail5:	if (input_dev) +		input_ff_destroy(input_dev); + fail4:	xpad_deinit_output(xpad); + fail3:	usb_free_urb(xpad->irq_in);   fail2:	usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);   fail1:	input_free_device(input_dev);  	kfree(xpad); @@ -974,21 +1042,24 @@ static void xpad_disconnect(struct usb_interface *intf)  {  	struct usb_xpad *xpad = usb_get_intfdata (intf); -	usb_set_intfdata(intf, NULL); -	if (xpad) { -		xpad_led_disconnect(xpad); -		input_unregister_device(xpad->dev); -		xpad_deinit_output(xpad); -		if (xpad->xtype == XTYPE_XBOX360W) { -			usb_kill_urb(xpad->bulk_out); -			usb_free_urb(xpad->bulk_out); -			usb_kill_urb(xpad->irq_in); -		} -		usb_free_urb(xpad->irq_in); -		usb_free_coherent(xpad->udev, XPAD_PKT_LEN, -				xpad->idata, xpad->idata_dma); -		kfree(xpad); +	xpad_led_disconnect(xpad); +	input_unregister_device(xpad->dev); +	xpad_deinit_output(xpad); + +	if (xpad->xtype == XTYPE_XBOX360W) { +		usb_kill_urb(xpad->bulk_out); +		usb_free_urb(xpad->bulk_out); +		usb_kill_urb(xpad->irq_in);  	} + +	usb_free_urb(xpad->irq_in); +	usb_free_coherent(xpad->udev, XPAD_PKT_LEN, +			xpad->idata, xpad->idata_dma); + +	kfree(xpad->bdata); +	kfree(xpad); + +	usb_set_intfdata(intf, NULL);  }  static struct usb_driver xpad_driver = { @@ -998,21 +1069,7 @@ static struct usb_driver xpad_driver = {  	.id_table	= xpad_table,  }; -static int __init usb_xpad_init(void) -{ -	int result = usb_register(&xpad_driver); -	if (result == 0) -		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); -	return result; -} - -static void __exit usb_xpad_exit(void) -{ -	usb_deregister(&xpad_driver); -} - -module_init(usb_xpad_init); -module_exit(usb_xpad_exit); +module_usb_driver(xpad_driver);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  | 
