| From foo@baz Fri Jan 24 11:15:28 PST 2014 |
| Date: Fri, 24 Jan 2014 11:15:28 -0800 |
| To: Greg KH <gregkh@linuxfoundation.org> |
| From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com> |
| Subject: [PATCH] Input: xpad: move the input device creation to a new function |
| |
| From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com> |
| |
| To allow us to later create / destroy the input device from the urb |
| callback, we need to initialize 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" <pgriffais@valvesoftware.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/input/joystick/xpad.c | 171 +++++++++++++++++++++++------------------- |
| 1 file changed, 97 insertions(+), 74 deletions(-) |
| |
| --- a/drivers/input/joystick/xpad.c |
| +++ b/drivers/input/joystick/xpad.c |
| @@ -293,6 +293,7 @@ struct usb_xpad { |
| |
| int mapping; /* map d-pad to buttons or to axes */ |
| int xtype; /* type of xbox device */ |
| + const char *name; /* name of the device */ |
| }; |
| |
| /* |
| @@ -858,70 +859,21 @@ static void xpad_set_up_abs(struct input |
| } |
| } |
| |
| -static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| +static int xpad_init_input(struct usb_xpad *xpad) |
| { |
| - 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 i, error; |
| |
| - for (i = 0; xpad_device[i].idVendor; i++) { |
| - if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
| - (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) |
| - break; |
| - } |
| - |
| - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); |
| input_dev = input_allocate_device(); |
| - 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) { |
| - error = -ENOMEM; |
| - goto fail1; |
| - } |
| - |
| - xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); |
| - 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; |
| - |
| - if (xpad->xtype == XTYPE_UNKNOWN) { |
| - if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { |
| - if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) |
| - xpad->xtype = XTYPE_XBOX360W; |
| - else |
| - xpad->xtype = XTYPE_XBOX360; |
| - } else |
| - xpad->xtype = XTYPE_XBOX; |
| - |
| - if (dpad_to_buttons) |
| - xpad->mapping |= MAP_DPAD_TO_BUTTONS; |
| - if (triggers_to_buttons) |
| - xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; |
| - if (sticks_to_null) |
| - xpad->mapping |= MAP_STICKS_TO_NULL; |
| - } |
| + if (!input_dev) |
| + return -ENOMEM; |
| |
| 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->name = xpad->name; |
| input_dev->phys = xpad->phys; |
| - usb_to_input_id(udev, &input_dev->id); |
| - input_dev->dev.parent = &intf->dev; |
| + usb_to_input_id(xpad->udev, &input_dev->id); |
| + input_dev->dev.parent = &xpad->intf->dev; |
| |
| input_set_drvdata(input_dev, xpad); |
| |
| @@ -966,17 +918,92 @@ static int xpad_probe(struct usb_interfa |
| 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; |
| + goto fail_init_ff; |
| |
| error = xpad_led_probe(xpad); |
| if (error) |
| - goto fail5; |
| + 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 usb_endpoint_descriptor *ep_irq_in; |
| + int i, error; |
| + |
| + for (i = 0; xpad_device[i].idVendor; i++) { |
| + if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
| + (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) |
| + break; |
| + } |
| + |
| + xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); |
| + 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) { |
| + error = -ENOMEM; |
| + goto fail1; |
| + } |
| + |
| + xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); |
| + 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; |
| + xpad->name = xpad_device[i].name; |
| + |
| + if (xpad->xtype == XTYPE_UNKNOWN) { |
| + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { |
| + if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) |
| + xpad->xtype = XTYPE_XBOX360W; |
| + else |
| + xpad->xtype = XTYPE_XBOX360; |
| + } else |
| + xpad->xtype = XTYPE_XBOX; |
| + |
| + if (dpad_to_buttons) |
| + xpad->mapping |= MAP_DPAD_TO_BUTTONS; |
| + if (triggers_to_buttons) |
| + xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; |
| + if (sticks_to_null) |
| + xpad->mapping |= MAP_STICKS_TO_NULL; |
| + } |
| + |
| + error = xpad_init_output(intf, xpad); |
| + if (error) |
| + goto fail3; |
| |
| ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
| usb_fill_int_urb(xpad->irq_in, udev, |
| @@ -986,10 +1013,6 @@ static int xpad_probe(struct usb_interfa |
| 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) { |
| @@ -1000,7 +1023,7 @@ static int xpad_probe(struct usb_interfa |
| xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); |
| if (!xpad->bulk_out) { |
| error = -ENOMEM; |
| - goto fail7; |
| + goto fail4; |
| } |
| |
| xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); |
| @@ -1048,24 +1071,24 @@ static int xpad_probe(struct usb_interfa |
| */ |
| xpad->irq_in->dev = xpad->udev; |
| error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); |
| - if (error) |
| + if (error) { |
| + usb_kill_urb(xpad->irq_in); |
| goto fail9; |
| + } |
| } |
| + xpad->pad_present = 1; |
| + error = xpad_init_input(xpad); |
| + if (error) |
| + goto fail9; |
| |
| 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); |
| - 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; |
| |
| } |