diff --git a/packages/linux/patches/4.1.3/linux-063-xpad-fix_xbox360_wireless.patch b/packages/linux/patches/4.1.3/linux-063-xpad-fix_xbox360_wireless.patch new file mode 100644 index 0000000000..969bc574e8 --- /dev/null +++ b/packages/linux/patches/4.1.3/linux-063-xpad-fix_xbox360_wireless.patch @@ -0,0 +1,887 @@ +From 0f578b91219bd354a170eb53359336f67bbfda57 Mon Sep 17 00:00:00 2001 +From: Matt DeVillier +Date: Tue, 28 Jul 2015 11:19:40 -0500 +Subject: [PATCH 1/1] linux/drivers/input/joystick/xpad: fixes for xbox360/one controllers + +merged from https://github.com/paroj/xpad + +- fixed blinking LED on Xbox 360 Wireless Controllers +- only expose actually connected Xbox 360 Wireless Controllers +- fixed kernel warnings due to submitting active URB requests +- updated Xbox One controller force feedback +- controller still works after suspend/ resume +- Xbox 360 Wireless button mappings are now compatible with Xbox 360 (non-wireless) mappings + +Signed-off-by: Matt DeVillier +--- + drivers/input/joystick/xpad.c | 599 ++++++++++++++++++++++++------------------ + 1 file changed, 337 insertions(+), 262 deletions(-) + +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index f8850f9..77ccd2b 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -74,7 +74,7 @@ + * + * Later changes can be tracked in SCM. + */ +- ++#define DEBUG + #include + #include + #include +@@ -328,10 +328,8 @@ struct usb_xpad { + unsigned char *idata; /* input data */ + dma_addr_t idata_dma; + +- struct urb *bulk_out; +- unsigned char *bdata; +- + struct urb *irq_out; /* urb for interrupt out report */ ++ int irq_out_active; /* we must not use an active URB */ + unsigned char *odata; /* output data */ + dma_addr_t odata_dma; + struct mutex odata_mutex; +@@ -344,9 +342,17 @@ struct usb_xpad { + + int mapping; /* map d-pad to buttons or to axes */ + int xtype; /* type of xbox device */ +- unsigned long led_no; /* led to lit on xbox360 controllers */ ++ unsigned long pad_nr; /* the order x360 pads were attached */ ++ const char *name; /* name of the device */ ++ struct work_struct work; /* init/remove device from callback */ ++ unsigned char odata_serial; /* serial number for xbox one protocol */ + }; + ++static unsigned long xpad_pad_seq; ++ ++static int xpad_init_input(struct usb_xpad *xpad); ++static void xpad_deinit_input(struct usb_xpad *xpad); ++ + /* + * xpad_process_packet + * +@@ -356,7 +362,6 @@ struct usb_xpad { + * The used report descriptor was taken from ITO Takayukis website: + * http://euc.jp/periphs/xbox-controller.ja.html + */ +- + static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) + { + struct input_dev *dev = xpad->dev; +@@ -439,7 +444,14 @@ static void xpad360_process_packet(struct usb_xpad *xpad, + input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); + input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); + input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); +- } else { ++ } ++ /* 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) { + input_report_abs(dev, ABS_HAT0X, + !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, +@@ -491,6 +503,22 @@ static void xpad360_process_packet(struct usb_xpad *xpad, + + static void xpad_identify_controller(struct usb_xpad *xpad); + ++static void presence_work_function(struct work_struct *work) ++{ ++ struct usb_xpad *xpad = container_of(work, struct usb_xpad, work); ++ int error; ++ ++ if (xpad->pad_present) { ++ error = xpad_init_input(xpad); ++ if (error) { ++ /* complain only, not much else we can do here */ ++ dev_err(&xpad->dev->dev, "unable to init device\n"); ++ } ++ } else { ++ xpad_deinit_input(xpad); ++ } ++} ++ + /* + * xpad360w_process_packet + * +@@ -505,21 +533,18 @@ static void xpad_identify_controller(struct usb_xpad *xpad); + * 01.1 - Pad state (Bytes 4+) valid + * + */ +- + static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) + { ++ int presence; ++ + /* Presence change */ + if (data[0] & 0x08) { +- if (data[1] & 0x80) { +- xpad->pad_present = 1; +- usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); +- /* +- * Light up the segment corresponding to +- * controller number. +- */ +- xpad_identify_controller(xpad); +- } else +- xpad->pad_present = 0; ++ presence = (data[1] & 0x80) != 0; ++ ++ if (xpad->pad_present != presence) { ++ xpad->pad_present = presence; ++ schedule_work(&xpad->work); ++ } + } + + /* Valid pad data */ +@@ -674,28 +699,6 @@ exit: + __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 */ +- break; +- case -ECONNRESET: +- case -ENOENT: +- case -ESHUTDOWN: +- /* this urb is terminated, clean up */ +- dev_dbg(dev, "%s - urb shutting down with status: %d\n", +- __func__, urb->status); +- break; +- default: +- dev_dbg(dev, "%s - nonzero urb status received: %d\n", +- __func__, urb->status); +- } +-} +- + static void xpad_irq_out(struct urb *urb) + { + struct usb_xpad *xpad = urb->context; +@@ -707,6 +710,7 @@ static void xpad_irq_out(struct urb *urb) + switch (status) { + case 0: + /* success */ ++ xpad->irq_out_active = 0; + return; + + case -ECONNRESET: +@@ -715,6 +719,7 @@ static void xpad_irq_out(struct urb *urb) + /* this urb is terminated, clean up */ + dev_dbg(dev, "%s - urb shutting down with status: %d\n", + __func__, status); ++ xpad->irq_out_active = 0; + return; + + default: +@@ -734,7 +739,6 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) + { + struct usb_endpoint_descriptor *ep_irq_out; + int ep_irq_out_idx; +- int error; + + if (xpad->xtype == XTYPE_UNKNOWN) + return 0; +@@ -742,16 +746,15 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) + xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->odata_dma); + if (!xpad->odata) { +- error = -ENOMEM; +- goto fail1; ++ return -ENOMEM; + } + + mutex_init(&xpad->odata_mutex); + + xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); + if (!xpad->irq_out) { +- error = -ENOMEM; +- goto fail2; ++ usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); ++ return -ENOMEM; + } + + /* Xbox One controller has in/out endpoints swapped. */ +@@ -766,9 +769,6 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) + 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) +@@ -790,80 +790,94 @@ static void xpad_deinit_output(struct usb_xpad *xpad) + static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) + { + struct usb_xpad *xpad = input_get_drvdata(dev); ++ __u16 strong; ++ __u16 weak; ++ int retval; + +- 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); +- +- case XTYPE_XBOXONE: +- xpad->odata[0] = 0x09; /* activate rumble */ +- xpad->odata[1] = 0x08; +- xpad->odata[2] = 0x00; +- xpad->odata[3] = 0x08; /* continuous effect */ +- xpad->odata[4] = 0x00; /* simple rumble mode */ +- xpad->odata[5] = 0x03; /* L and R actuator only */ +- xpad->odata[6] = 0x00; /* TODO: LT actuator */ +- xpad->odata[7] = 0x00; /* TODO: RT actuator */ +- xpad->odata[8] = strong / 256; /* left actuator */ +- xpad->odata[9] = weak / 256; /* right actuator */ +- xpad->odata[10] = 0x80; /* length of pulse */ +- xpad->odata[11] = 0x00; /* stop period of pulse */ +- xpad->irq_out->transfer_buffer_length = 12; +- +- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); +- +- default: +- dev_dbg(&xpad->dev->dev, +- "%s - rumble command sent to unsupported xpad type: %d\n", +- __func__, xpad->xtype); +- return -1; +- } ++ if (effect->type != FF_RUMBLE) ++ return 0; ++ ++ strong = effect->u.rumble.strong_magnitude; ++ weak = effect->u.rumble.weak_magnitude; ++ ++ mutex_lock(&xpad->odata_mutex); ++ ++ 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; ++ break; ++ ++ 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; ++ break; ++ ++ 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; ++ break; ++ ++ case XTYPE_XBOXONE: ++ xpad->odata[0] = 0x09; /* activate rumble */ ++ xpad->odata[1] = 0x08; ++ xpad->odata[2] = xpad->odata_serial++; ++ xpad->odata[3] = 0x08; /* continuous effect */ ++ xpad->odata[4] = 0x00; /* simple rumble mode */ ++ xpad->odata[5] = 0x03; /* L and R actuator only */ ++ xpad->odata[6] = 0x00; /* TODO: LT actuator */ ++ xpad->odata[7] = 0x00; /* TODO: RT actuator */ ++ xpad->odata[8] = strong / 512; /* left actuator */ ++ xpad->odata[9] = weak / 512; /* right actuator */ ++ xpad->odata[10] = 0x80; /* length of pulse */ ++ xpad->odata[11] = 0x00; /* stop period of pulse */ ++ xpad->odata[12] = 0x00; ++ xpad->irq_out->transfer_buffer_length = 13; ++ break; ++ ++ default: ++ mutex_unlock(&xpad->odata_mutex); ++ dev_dbg(&xpad->dev->dev, ++ "%s - rumble command sent to unsupported xpad type: %d\n", ++ __func__, xpad->xtype); ++ return -EINVAL; + } + +- return 0; ++ if (!xpad->irq_out_active) { ++ retval = usb_submit_urb(xpad->irq_out, GFP_ATOMIC); ++ xpad->irq_out_active = 1; ++ } else { ++ retval = -EIO; ++ dev_dbg(&xpad->dev->dev, "%s - dropped, irq_out is active\n", ++ __func__); ++ } ++ ++ mutex_unlock(&xpad->odata_mutex); ++ ++ return retval; + } + + static int xpad_init_ff(struct usb_xpad *xpad) +@@ -890,6 +904,7 @@ struct xpad_led { + }; + + /** ++ * set the LEDs on Xbox360 / Wireless Controllers + * @param command + * 0: off + * 1: all blink, then previous setting +@@ -938,14 +953,28 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command) + break; + } + +- usb_submit_urb(xpad->irq_out, GFP_KERNEL); ++ if (!xpad->irq_out_active) { ++ usb_submit_urb(xpad->irq_out, GFP_KERNEL); ++ xpad->irq_out_active = 1; ++ } else ++ dev_dbg(&xpad->dev->dev, "%s - dropped, irq_out is active\n", ++ __func__); ++ + mutex_unlock(&xpad->odata_mutex); + } + ++/* ++ * Light up the segment corresponding to the pad number on Xbox 360 Controllers ++ */ + static void xpad_identify_controller(struct usb_xpad *xpad) + { +- /* Light up the segment corresponding to controller number */ +- xpad_send_led_command(xpad, (xpad->led_no % 4) + 2); ++ if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) ++ return; ++ ++ xpad->pad_nr = find_first_zero_bit(&xpad_pad_seq, 32); ++ set_bit(xpad->pad_nr, &xpad_pad_seq); ++ ++ xpad_send_led_command(xpad, (xpad->pad_nr % 4) + 2); + } + + static void xpad_led_set(struct led_classdev *led_cdev, +@@ -959,7 +988,6 @@ static void xpad_led_set(struct led_classdev *led_cdev, + + static int xpad_led_probe(struct usb_xpad *xpad) + { +- static atomic_t led_seq = ATOMIC_INIT(-1); + struct xpad_led *led; + struct led_classdev *led_cdev; + int error; +@@ -971,9 +999,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) + if (!led) + return -ENOMEM; + +- xpad->led_no = atomic_inc_return(&led_seq); +- +- snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->led_no); ++ snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->pad_nr); + led->xpad = xpad; + + led_cdev = &led->led_cdev; +@@ -987,9 +1013,6 @@ static int xpad_led_probe(struct usb_xpad *xpad) + return error; + } + +- /* Light up the segment corresponding to controller number */ +- xpad_identify_controller(xpad); +- + return 0; + } + +@@ -1012,6 +1035,7 @@ static void xpad_identify_controller(struct usb_xpad *xpad) { } + static int xpad_open(struct input_dev *dev) + { + struct usb_xpad *xpad = input_get_drvdata(dev); ++ int retval; + + /* URB was submitted in probe */ + if (xpad->xtype == XTYPE_XBOX360W) +@@ -1022,11 +1046,17 @@ static int xpad_open(struct input_dev *dev) + return -EIO; + + if (xpad->xtype == XTYPE_XBOXONE) { ++ mutex_lock(&xpad->odata_mutex); + /* Xbox one controller needs to be initialized. */ + xpad->odata[0] = 0x05; + xpad->odata[1] = 0x20; +- xpad->irq_out->transfer_buffer_length = 2; +- return usb_submit_urb(xpad->irq_out, GFP_KERNEL); ++ xpad->odata[2] = xpad->odata_serial++; /* packet serial */ ++ xpad->odata[3] = 0x01; /* rumble bit enable? */ ++ xpad->odata[4] = 0x00; ++ xpad->irq_out->transfer_buffer_length = 5; ++ retval = usb_submit_urb(xpad->irq_out, GFP_KERNEL); ++ mutex_unlock(&xpad->odata_mutex); ++ return retval; + } + + return 0; +@@ -1068,11 +1098,103 @@ 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]); ++ } ++ ++ xpad_identify_controller(xpad); ++ ++ 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; +@@ -1094,12 +1216,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) { +@@ -1117,6 +1241,8 @@ 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; ++ INIT_WORK(&xpad->work, presence_work_function); + + if (xpad->xtype == XTYPE_UNKNOWN) { + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { +@@ -1135,71 +1261,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); +- } else { +- 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; +@@ -1211,60 +1276,10 @@ 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) { + /* +- * 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; +- if (usb_endpoint_is_bulk_out(ep_irq_in)) { +- usb_fill_bulk_urb(xpad->bulk_out, udev, +- usb_sndbulkpipe(udev, +- ep_irq_in->bEndpointAddress), +- xpad->bdata, XPAD_PKT_LEN, +- xpad_bulk_out, xpad); +- } else { +- usb_fill_int_urb(xpad->bulk_out, udev, +- usb_sndintpipe(udev, +- ep_irq_in->bEndpointAddress), +- xpad->bdata, XPAD_PKT_LEN, +- xpad_bulk_out, xpad, 0); +- } +- +- /* + * 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 +@@ -1273,56 +1288,116 @@ 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) { ++ usb_kill_urb(xpad->irq_in); ++ goto fail4; ++ } ++ ++ /* ++ * send presence packet ++ * This will force the controller to resend connection packets. ++ * This is useful in the case we activate the module after the ++ * adapter has been plugged in, as it won't automatically ++ * send us info about the controllers. ++ */ ++ mutex_lock(&xpad->odata_mutex); ++ xpad->odata[0] = 0x08; ++ xpad->odata[1] = 0x00; ++ xpad->odata[2] = 0x0F; ++ xpad->odata[3] = 0xC0; ++ 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; ++ ++ if (!xpad->irq_out_active) { ++ usb_submit_urb(xpad->irq_out, GFP_KERNEL); ++ xpad->irq_out_active = 1; ++ } else ++ dev_dbg(&xpad->dev->dev, ++ "%s - dropped, irq_out is active\n", __func__); ++ ++ mutex_unlock(&xpad->odata_mutex); ++ } else { ++ xpad->pad_present = 1; ++ error = xpad_init_input(xpad); + if (error) +- goto fail9; ++ goto fail4; + } + + 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; + + } + +-static void xpad_disconnect(struct usb_interface *intf) ++static void xpad_deinit_input(struct usb_xpad *xpad) + { +- struct usb_xpad *xpad = usb_get_intfdata (intf); +- + xpad_led_disconnect(xpad); + input_unregister_device(xpad->dev); +- xpad_deinit_output(xpad); ++ ++ if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) ++ return; ++ ++ clear_bit(xpad->pad_nr, &xpad_pad_seq); ++} ++ ++static void xpad_stop_communication(struct usb_xpad *xpad) { ++ xpad_stop_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); + } + ++ cancel_work_sync(&xpad->work); ++} ++ ++static void xpad_disconnect(struct usb_interface *intf) ++{ ++ struct usb_xpad *xpad = usb_get_intfdata (intf); ++ ++ if (xpad->pad_present) ++ xpad_deinit_input(xpad); ++ ++ xpad_stop_communication(xpad); ++ ++ xpad_deinit_output(xpad); ++ + 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 int xpad_suspend(struct usb_interface *intf, pm_message_t message) { ++ struct usb_xpad *xpad = usb_get_intfdata (intf); ++ xpad_stop_communication(xpad); ++ return 0; ++} ++ ++static int xpad_resume(struct usb_interface *intf) { ++ usb_queue_reset_device(intf); ++ return 0; ++} ++ + static struct usb_driver xpad_driver = { + .name = "xpad", + .probe = xpad_probe, + .disconnect = xpad_disconnect, ++ .suspend = xpad_suspend, ++ .resume = xpad_resume, + .id_table = xpad_table, + }; + +-- +1.9.1 +