From: "Pierre-Loup A. Griffais" <pgriff...@valvesoftware.com>

To allow us to later create / destroy the input device from the urb
callback, we need to initialize/ deinitialize the input device from a
separate function.  So pull that logic out now to make later patches
more "obvious" as to what they do.

Signed-off-by: "Pierre-Loup A. Griffais" <pgriff...@valvesoftware.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Pavel Rojtberg <rojtb...@gmail.com>
---
 drivers/input/joystick/xpad.c | 199 
+++++++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 113 insertions(+), 86 deletions(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 15da2a3..43490ea 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -343,6 +343,7 @@ struct usb_xpad {
        int mapping;                    /* map d-pad to buttons or to axes */
        int xtype;                      /* type of xbox device */
        unsigned long pad_nr;           /* the order x360 pads were attached */
+       const char *name;               /* name of the device */
 };
 
 /*
@@ -1044,11 +1045,101 @@ static void xpad_set_up_abs(struct input_dev 
*input_dev, signed short abs)
        }
 }
 
+static int xpad_init_input(struct usb_xpad *xpad)
+{
+       struct input_dev *input_dev;
+       int i, error;
+
+       input_dev = input_allocate_device();
+       if (!input_dev)
+               return -ENOMEM;
+
+       xpad->dev = input_dev;
+       input_dev->name = xpad->name;
+       input_dev->phys = xpad->phys;
+       usb_to_input_id(xpad->udev, &input_dev->id);
+       input_dev->dev.parent = &xpad->intf->dev;
+
+       input_set_drvdata(input_dev, xpad);
+
+       input_dev->open = xpad_open;
+       input_dev->close = xpad_close;
+
+       input_dev->evbit[0] = BIT_MASK(EV_KEY);
+
+       if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
+               input_dev->evbit[0] |= BIT_MASK(EV_ABS);
+               /* set up axes */
+               for (i = 0; xpad_abs[i] >= 0; i++)
+                       xpad_set_up_abs(input_dev, xpad_abs[i]);
+       }
+
+       /* set up standard buttons */
+       for (i = 0; xpad_common_btn[i] >= 0; i++)
+               __set_bit(xpad_common_btn[i], input_dev->keybit);
+
+       /* set up model-specific ones */
+       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
+           xpad->xtype == XTYPE_XBOXONE) {
+               for (i = 0; xpad360_btn[i] >= 0; i++)
+                       __set_bit(xpad360_btn[i], input_dev->keybit);
+       } else {
+               for (i = 0; xpad_btn[i] >= 0; i++)
+                       __set_bit(xpad_btn[i], input_dev->keybit);
+       }
+
+       if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
+               for (i = 0; xpad_btn_pad[i] >= 0; i++)
+                       __set_bit(xpad_btn_pad[i], input_dev->keybit);
+       }
+       /* this should be a simple else block. However historically xbox360w
+        * has mapped DPAD to buttons while xbox360 did not.
+        * This made no sense, but now we can not just switch back and have to
+        * support both behaviors.
+        */
+       if(!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
+                       xpad->xtype == XTYPE_XBOX360W) {
+               for (i = 0; xpad_abs_pad[i] >= 0; i++)
+                       xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+       }
+
+       if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
+               for (i = 0; xpad_btn_triggers[i] >= 0; i++)
+                       __set_bit(xpad_btn_triggers[i], input_dev->keybit);
+       } else {
+               for (i = 0; xpad_abs_triggers[i] >= 0; i++)
+                       xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
+       }
+
+       error = xpad_init_ff(xpad);
+       if (error)
+               goto fail_init_ff;
+
+       error = xpad_led_probe(xpad);
+       if (error)
+               goto fail_init_led;
+
+       error = input_register_device(xpad->dev);
+       if (error)
+               goto fail_input_register;
+
+       return 0;
+
+fail_input_register:
+       xpad_led_disconnect(xpad);
+
+fail_init_led:
+       input_ff_destroy(input_dev);
+
+fail_init_ff:
+       input_free_device(input_dev);
+       return error;
+}
+
 static int xpad_probe(struct usb_interface *intf, const struct usb_device_id 
*id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_xpad *xpad;
-       struct input_dev *input_dev;
        struct usb_endpoint_descriptor *ep_irq_in;
        int ep_irq_in_idx;
        int i, error;
@@ -1070,12 +1161,14 @@ 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) {
                error = -ENOMEM;
                goto fail1;
        }
 
+       usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+       strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
+
        xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
                                         GFP_KERNEL, &xpad->idata_dma);
        if (!xpad->idata) {
@@ -1093,6 +1186,7 @@ static int xpad_probe(struct usb_interface *intf, const 
struct usb_device_id *id
        xpad->intf = intf;
        xpad->mapping = xpad_device[i].mapping;
        xpad->xtype = xpad_device[i].xtype;
+       xpad->name = xpad_device[i].name;
 
        if (xpad->xtype == XTYPE_UNKNOWN) {
                if (intf->cur_altsetting->desc.bInterfaceClass == 
USB_CLASS_VENDOR_SPEC) {
@@ -1111,78 +1205,10 @@ static int xpad_probe(struct usb_interface *intf, const 
struct usb_device_id *id
                        xpad->mapping |= MAP_STICKS_TO_NULL;
        }
 
-       xpad->dev = input_dev;
-       usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
-       strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
-
-       input_dev->name = xpad_device[i].name;
-       input_dev->phys = xpad->phys;
-       usb_to_input_id(udev, &input_dev->id);
-       input_dev->dev.parent = &intf->dev;
-
-       input_set_drvdata(input_dev, xpad);
-
-       input_dev->open = xpad_open;
-       input_dev->close = xpad_close;
-
-       input_dev->evbit[0] = BIT_MASK(EV_KEY);
-
-       if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
-               input_dev->evbit[0] |= BIT_MASK(EV_ABS);
-               /* set up axes */
-               for (i = 0; xpad_abs[i] >= 0; i++)
-                       xpad_set_up_abs(input_dev, xpad_abs[i]);
-       }
-
-       /* set up standard buttons */
-       for (i = 0; xpad_common_btn[i] >= 0; i++)
-               __set_bit(xpad_common_btn[i], input_dev->keybit);
-
-       /* set up model-specific ones */
-       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
-           xpad->xtype == XTYPE_XBOXONE) {
-               for (i = 0; xpad360_btn[i] >= 0; i++)
-                       __set_bit(xpad360_btn[i], input_dev->keybit);
-       } else {
-               for (i = 0; xpad_btn[i] >= 0; i++)
-                       __set_bit(xpad_btn[i], input_dev->keybit);
-       }
-
-       if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
-               for (i = 0; xpad_btn_pad[i] >= 0; i++)
-                       __set_bit(xpad_btn_pad[i], input_dev->keybit);
-       }
-       /* this should be a simple else block. However historically xbox360w
-        * has mapped DPAD to buttons while xbox360 did not.
-        * This made no sense, but now we can not just switch back and have to
-        * support both behaviors.
-        */
-       if(!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
-                       xpad->xtype == XTYPE_XBOX360W) {
-               for (i = 0; xpad_abs_pad[i] >= 0; i++)
-                       xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
-       }
-
-       if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
-               for (i = 0; xpad_btn_triggers[i] >= 0; i++)
-                       __set_bit(xpad_btn_triggers[i], input_dev->keybit);
-       } else {
-               for (i = 0; xpad_abs_triggers[i] >= 0; i++)
-                       xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
-       }
-
        error = xpad_init_output(intf, xpad);
        if (error)
                goto fail3;
 
-       error = xpad_init_ff(xpad);
-       if (error)
-               goto fail4;
-
-       error = xpad_led_probe(xpad);
-       if (error)
-               goto fail5;
-
        /* Xbox One controller has in/out endpoints swapped. */
        ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
        ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;
@@ -1194,10 +1220,6 @@ static int xpad_probe(struct usb_interface *intf, const 
struct usb_device_id *id
        xpad->irq_in->transfer_dma = xpad->idata_dma;
        xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       error = input_register_device(xpad->dev);
-       if (error)
-               goto fail6;
-
        usb_set_intfdata(intf, xpad);
 
        if (xpad->xtype == XTYPE_XBOX360W) {
@@ -1210,32 +1232,37 @@ 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 fail7;
+               if (error) {
+                       usb_kill_urb(xpad->irq_in);
+                       goto fail4;
+               }
        }
+       xpad->pad_present = 1;
+       error = xpad_init_input(xpad);
+       if (error)
+               goto fail4;
 
        return 0;
 
- 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);
+ fail1:        kfree(xpad);
        return error;
 
 }
 
+static void xpad_deinit_input(struct usb_xpad *xpad)
+{
+       xpad_led_disconnect(xpad);
+       input_unregister_device(xpad->dev);
+}
+
 static void xpad_disconnect(struct usb_interface *intf)
 {
        struct usb_xpad *xpad = usb_get_intfdata (intf);
 
-       xpad_led_disconnect(xpad);
-       input_unregister_device(xpad->dev);
+       xpad_deinit_input(xpad);
        xpad_deinit_output(xpad);
 
        if (xpad->xtype == XTYPE_XBOX360W) {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to