--- Begin Message ---
On Sun, Jun 12, 2011 at 05:49:49PM -0700, Chris Moeller wrote:
> This patch removes the non-functional bulk output URB method for setting
> XBox360 Wireless Controller player number indicators on controller
> activation, and replaces it with a functional IRQ output URB method. It
> also implements the LED command control for these devices.
>
> Signed-off-by: Chris Moeller <kode54@xxxxxxxxx>
>
> ---
>
> I chose to duplicate the LED command setting function in the
> xpad360w_process_packet function, as the other LED setting function is
> designed to require mutex locking, which I found to deadlock the driver
> when used in that manner. I will consider adding a lock, as testing with
> a rumble flooding application collided with the LED control and
> prevented it from setting the player number on connect. I'm not even
> sure how the mutex could be deadlocking in the input packet handler, or
> even what good it would do in that case, since the rumble setting
> functions don't lock it. In fact, only the LED setting function locks
> it.
If 2 functions share the same URB then we need to arbitrate access to
URB data buffers, etc, etc. I believe the patch below could be used as a
starting point.
Thanks.
--
Dmitry
Input: xpad - wireless LED setting
From: Chris Moeller <kode54@xxxxxxxxx>
This patch removes the non-functional bulk output URB method for setting
XBox360 Wireless Controller player number indicators on controller
activation, and replaces it with a functional IRQ output URB method. It
also implements the LED command control for these devices.
Signed-off-by: Chris Moeller <kode54@xxxxxxxxx>
Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
---
drivers/input/joystick/xpad.c | 699 ++++++++++++++++++++++-------------------
1 files changed, 379 insertions(+), 320 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index d728875..e2dbe54 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -253,23 +253,28 @@ struct usb_xpad {
struct input_dev *dev; /* input device interface */
struct usb_device *udev; /* usb device */
- int pad_present;
+ int interface_number;
struct urb *irq_in; /* urb for interrupt in report */
unsigned char *idata; /* input data */
dma_addr_t idata_dma;
- struct urb *bulk_out;
- unsigned char *bdata;
-
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct urb *irq_out; /* urb for interrupt out report */
unsigned char *odata; /* output data */
dma_addr_t odata_dma;
- struct mutex odata_mutex;
+ spinlock_t odata_lock;
+ bool irq_out_pending;
+
+ bool led_pending;
+ int led_command;
+
+ bool ff_pending;
+ u16 rumble_strong;
+ u16 rumble_weak;
#endif
-#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
+#ifdef CONFIG_JOYSTICK_XPAD_LEDS
struct xpad_led *led;
#endif
@@ -279,6 +284,369 @@ struct usb_xpad {
int xtype; /* type of xbox device */
};
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static bool xpad_format_rumble(struct usb_xpad *xpad, u16 strong, u16 weak)
+{
+ switch (xpad->xtype) {
+
+ case XTYPE_XBOX:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x06;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator */
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = weak / 256; /* right actuator */
+ xpad->irq_out->transfer_buffer_length = 6;
+
+ return true;
+
+ case XTYPE_XBOX360:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator? */
+ xpad->odata[4] = weak / 256; /* right actuator? */
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 8;
+
+ return true;
+
+ 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 true;
+
+ default:
+ dbg("%s - rumble command sent to unsupported xpad type: %d",
+ __func__, xpad->xtype);
+ return false;
+ }
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
+{
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
+ if (effect->type == FF_RUMBLE) {
+ u16 strong = effect->u.rumble.strong_magnitude;
+ u16 weak = effect->u.rumble.weak_magnitude;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xpad->odata_lock, flags);
+
+ if (xpad->irq_out_pending) {
+ xpad->rumble_strong = strong;
+ xpad->rumble_weak = weak;
+ xpad->ff_pending = true;
+ } else if (xpad_format_rumble(xpad, strong, weak)) {
+ xpad->irq_out_pending = true;
+ usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+ }
+
+ spin_unlock_irqrestore(&xpad->odata_lock, flags);
+ }
+
+ return 0;
+}
+
+static int xpad_init_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_UNKNOWN)
+ return 0;
+
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+ return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+}
+
+#else
+
+static int xpad_init_ff(struct usb_xpad *xpad)
+{
+ return 0;
+}
+
+#ifdef CONFIG_JOYSTICK_XPAD_LEDS
+static bool xpad_format_rumble(struct usb_xpad *xpad, u16 strong, u16 weak)
+{
+ return false;
+}
+#endif
+
+#endif
+
+#ifdef CONFIG_JOYSTICK_XPAD_LEDS
+#include <linux/leds.h>
+
+struct xpad_led {
+ char name[16];
+ struct led_classdev led_cdev;
+ struct usb_xpad *xpad;
+};
+
+static bool xpad_format_led_command(struct usb_xpad *xpad, int command)
+{
+ switch (xpad->xtype) {
+ case XTYPE_XBOX:
+ case XTYPE_XBOX360:
+ if (command >= 0 && command < 14) {
+ xpad->odata[0] = 0x01;
+ xpad->odata[1] = 0x03;
+ xpad->odata[2] = command;
+ xpad->irq_out->transfer_buffer_length = 3;
+ return true;
+ }
+ break;
+
+ case XTYPE_XBOX360W:
+ if (command >= 0 && command <= 16) {
+ if (command == 16)
+ command = 2 + (xpad->interface_number & 6) / 2;
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x00;
+ xpad->odata[2] = 0x08;
+ xpad->odata[3] = 0x40 + command;
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ 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 true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+static void xpad_send_led_command(struct usb_xpad *xpad, int command)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&xpad->odata_lock, flags);
+
+ if (xpad->irq_out_pending) {
+ xpad->led_command = command;
+ xpad->led_pending = true;
+ } else if (xpad_format_led_command(xpad, command)) {
+ xpad->irq_out_pending = true;
+ usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+ }
+
+ spin_unlock_irqrestore(&xpad->odata_lock, flags);
+}
+
+static void xpad_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct xpad_led *xpad_led = container_of(led_cdev,
+ struct xpad_led, led_cdev);
+
+ xpad_send_led_command(xpad_led->xpad, value);
+}
+
+static int xpad_led_probe(struct usb_xpad *xpad)
+{
+ static atomic_t led_seq = ATOMIC_INIT(0);
+ long led_no;
+ struct xpad_led *led;
+ struct led_classdev *led_cdev;
+ int error;
+
+ if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W)
+ return 0;
+
+ xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ led_no = (long)atomic_inc_return(&led_seq) - 1;
+
+ snprintf(led->name, sizeof(led->name), "xpad%ld", led_no);
+ led->xpad = xpad;
+
+ led_cdev = &led->led_cdev;
+ led_cdev->name = led->name;
+ led_cdev->brightness_set = xpad_led_set;
+
+ error = led_classdev_register(&xpad->udev->dev, led_cdev);
+ if (error) {
+ kfree(led);
+ xpad->led = NULL;
+ return error;
+ }
+
+ /*
+ * Light up the segment corresponding to controller number
+ */
+ if (xpad->xtype == XTYPE_XBOX360)
+ xpad_send_led_command(xpad, (led_no % 4) + 2);
+
+ return 0;
+}
+
+static void xpad_led_disconnect(struct usb_xpad *xpad)
+{
+ struct xpad_led *xpad_led = xpad->led;
+
+ if (xpad_led) {
+ led_classdev_unregister(&xpad_led->led_cdev);
+ kfree(xpad_led);
+ }
+}
+
+#else
+
+static int xpad_led_probe(struct usb_xpad *xpad)
+{
+ return 0;
+}
+
+static void xpad_led_disconnect(struct usb_xpad *xpad)
+{
+}
+
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static bool xpad_format_led_command(struct usb_xpad *xpad, int command)
+{
+ return false;
+}
+#endif
+
+static void xpad_send_led_command(struct usb_xpad *xpad, int command)
+{
+}
+
+#endif
+
+#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;
+ int status = urb->status;
+ int retval;
+ unsigned long flags;
+
+ switch (status) {
+ case 0:
+ /* success */
+ spin_lock_irqsave(&xpad->odata_lock, flags);
+ xpad->irq_out_pending = false;
+
+ if (xpad->ff_pending) {
+ xpad->ff_pending = false;
+ if (xpad_format_rumble(xpad,
+ xpad->rumble_strong,
+ xpad->rumble_weak)) {
+ xpad->irq_out_pending = true;
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+ } else if (xpad->led_pending) {
+ xpad->led_pending = false;
+ if (xpad_format_led_command(xpad,
+ xpad->led_command)) {
+ xpad->irq_out_pending = true;
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+ }
+
+ spin_unlock_irqrestore(&xpad->odata_lock, flags);
+ return;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, status);
+ return;
+
+ default:
+ dbg("%s - nonzero urb status received: %d", __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);
+}
+
+static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+ struct usb_endpoint_descriptor *ep_irq_out;
+ int error;
+
+ if (xpad->xtype == XTYPE_UNKNOWN)
+ return 0;
+
+ spin_lock_init(&xpad->odata_lock);
+
+ xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
+ GFP_KERNEL, &xpad->odata_dma);
+ if (!xpad->odata) {
+ error = -ENOMEM;
+ goto fail1;
+ }
+
+ xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+ 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,
+ usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+ xpad->odata, XPAD_PKT_LEN,
+ xpad_irq_out, xpad, ep_irq_out->bInterval);
+ xpad->irq_out->transfer_dma = xpad->odata_dma;
+ xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ return 0;
+
+ fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1: return error;
+}
+
+static void xpad_stop_output(struct usb_xpad *xpad)
+{
+ if (xpad->xtype != XTYPE_UNKNOWN)
+ usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_output(struct usb_xpad *xpad)
+{
+ if (xpad->xtype != XTYPE_UNKNOWN) {
+ usb_free_urb(xpad->irq_out);
+ usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
+ xpad->odata, xpad->odata_dma);
+ }
+}
+#else
+static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_deinit_output(struct usb_xpad *xpad) { }
+static void xpad_stop_output(struct usb_xpad *xpad) { }
+#endif
+
/*
* xpad_process_packet
*
@@ -439,13 +807,8 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
{
/* Presence change */
- if (data[0] & 0x08) {
- if (data[1] & 0x80) {
- xpad->pad_present = 1;
- usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
- } else
- xpad->pad_present = 0;
- }
+ if ((data[0] & 0x08) && (data[1] & 0x80))
+ xpad_send_led_command(xpad, 16);
/* Valid pad data */
if (!(data[1] & 0x1))
@@ -496,271 +859,6 @@ exit:
__func__, retval);
}
-static void xpad_bulk_out(struct urb *urb)
-{
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
- break;
- default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
- }
-}
-
-#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
-static void xpad_irq_out(struct urb *urb)
-{
- int retval, status;
-
- status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- return;
-
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, status);
- return;
-
- default:
- dbg("%s - nonzero urb status received: %d", __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);
-}
-
-static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
-{
- struct usb_endpoint_descriptor *ep_irq_out;
- int error;
-
- 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) {
- error = -ENOMEM;
- goto fail1;
- }
-
- mutex_init(&xpad->odata_mutex);
-
- xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
- 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,
- usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
- xpad->odata, XPAD_PKT_LEN,
- xpad_irq_out, xpad, ep_irq_out->bInterval);
- xpad->irq_out->transfer_dma = xpad->odata_dma;
- xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
- return 0;
-
- fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
- fail1: return error;
-}
-
-static void xpad_stop_output(struct usb_xpad *xpad)
-{
- if (xpad->xtype != XTYPE_UNKNOWN)
- usb_kill_urb(xpad->irq_out);
-}
-
-static void xpad_deinit_output(struct usb_xpad *xpad)
-{
- if (xpad->xtype != XTYPE_UNKNOWN) {
- usb_free_urb(xpad->irq_out);
- usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
- xpad->odata, xpad->odata_dma);
- }
-}
-#else
-static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
-static void xpad_deinit_output(struct usb_xpad *xpad) {}
-static void xpad_stop_output(struct usb_xpad *xpad) {}
-#endif
-
-#ifdef CONFIG_JOYSTICK_XPAD_FF
-static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
-{
- struct usb_xpad *xpad = input_get_drvdata(dev);
-
- if (effect->type == FF_RUMBLE) {
- __u16 strong = effect->u.rumble.strong_magnitude;
- __u16 weak = effect->u.rumble.weak_magnitude;
-
- switch (xpad->xtype) {
-
- case XTYPE_XBOX:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x06;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator */
- xpad->odata[4] = 0x00;
- xpad->odata[5] = weak / 256; /* right actuator */
- xpad->irq_out->transfer_buffer_length = 6;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOX360:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x08;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator? */
- xpad->odata[4] = weak / 256; /* right actuator? */
- xpad->odata[5] = 0x00;
- xpad->odata[6] = 0x00;
- xpad->odata[7] = 0x00;
- xpad->irq_out->transfer_buffer_length = 8;
-
- 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",
- __func__, xpad->xtype);
- return -1;
- }
- }
-
- return 0;
-}
-
-static int xpad_init_ff(struct usb_xpad *xpad)
-{
- if (xpad->xtype == XTYPE_UNKNOWN)
- return 0;
-
- input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
-
- return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
-}
-
-#else
-static int xpad_init_ff(struct usb_xpad *xpad) { return 0; }
-#endif
-
-#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
-#include <linux/leds.h>
-
-struct xpad_led {
- char name[16];
- struct led_classdev led_cdev;
- struct usb_xpad *xpad;
-};
-
-static void xpad_send_led_command(struct usb_xpad *xpad, int command)
-{
- if (command >= 0 && command < 14) {
- mutex_lock(&xpad->odata_mutex);
- xpad->odata[0] = 0x01;
- xpad->odata[1] = 0x03;
- xpad->odata[2] = command;
- xpad->irq_out->transfer_buffer_length = 3;
- usb_submit_urb(xpad->irq_out, GFP_KERNEL);
- mutex_unlock(&xpad->odata_mutex);
- }
-}
-
-static void xpad_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct xpad_led *xpad_led = container_of(led_cdev,
- struct xpad_led, led_cdev);
-
- xpad_send_led_command(xpad_led->xpad, value);
-}
-
-static int xpad_led_probe(struct usb_xpad *xpad)
-{
- static atomic_t led_seq = ATOMIC_INIT(0);
- long led_no;
- struct xpad_led *led;
- struct led_classdev *led_cdev;
- int error;
-
- if (xpad->xtype != XTYPE_XBOX360)
- return 0;
-
- xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL);
- if (!led)
- return -ENOMEM;
-
- led_no = (long)atomic_inc_return(&led_seq) - 1;
-
- snprintf(led->name, sizeof(led->name), "xpad%ld", led_no);
- led->xpad = xpad;
-
- led_cdev = &led->led_cdev;
- led_cdev->name = led->name;
- led_cdev->brightness_set = xpad_led_set;
-
- error = led_classdev_register(&xpad->udev->dev, led_cdev);
- if (error) {
- kfree(led);
- xpad->led = NULL;
- return error;
- }
-
- /*
- * Light up the segment corresponding to controller number
- */
- xpad_send_led_command(xpad, (led_no % 4) + 2);
-
- return 0;
-}
-
-static void xpad_led_disconnect(struct usb_xpad *xpad)
-{
- struct xpad_led *xpad_led = xpad->led;
-
- if (xpad_led) {
- led_classdev_unregister(&xpad_led->led_cdev);
- kfree(xpad_led);
- }
-}
-#else
-static int xpad_led_probe(struct usb_xpad *xpad) { return 0; }
-static void xpad_led_disconnect(struct usb_xpad *xpad) { }
-#endif
-
static int xpad_open(struct input_dev *dev)
{
@@ -942,43 +1040,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
usb_set_intfdata(intf, xpad);
- if (xpad->xtype == XTYPE_XBOX360W) {
- /*
- * 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) {
- error = -ENOMEM;
- goto fail7;
- }
-
- xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
- if (!xpad->bdata) {
- error = -ENOMEM;
- goto fail8;
- }
-
- xpad->bdata[2] = 0x08;
- switch (intf->cur_altsetting->desc.bInterfaceNumber) {
- case 0:
- xpad->bdata[3] = 0x42;
- break;
- case 2:
- xpad->bdata[3] = 0x43;
- break;
- case 4:
- xpad->bdata[3] = 0x44;
- break;
- case 6:
- xpad->bdata[3] = 0x45;
- }
-
- ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
- usb_fill_bulk_urb(xpad->bulk_out, udev,
- usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
- xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+ xpad->interface_number = intf->cur_altsetting->desc.bInterfaceNumber;
+ if (xpad->xtype == XTYPE_XBOX360W) {
/*
* Submit the int URB immediately rather than waiting for open
* because we get status messages from the device whether
@@ -989,13 +1053,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->irq_in->dev = xpad->udev;
error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
if (error)
- goto fail9;
+ goto fail7;
}
return 0;
- 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);
@@ -1019,8 +1081,6 @@ static void xpad_disconnect(struct usb_interface *intf)
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);
}
@@ -1028,7 +1088,6 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
- kfree(xpad->bdata);
kfree(xpad);
usb_set_intfdata(intf, NULL);
--- End Message ---