From ef03acf6023fd49a760ea91986f870d019ff0ba4 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 23 Mar 2015 16:16:06 +0200 Subject: [PATCH] Revert "Merge pull request #4033 from zzattack/xpad-steamos" This reverts commit 3e5f7f3c018885e0b95978cc817b8894b4dcd8dd as requested. I am tired of all this xpad bull****. dont touch it until mainlined --- .../3.19.2/linux-061-xpad_steamos.patch | 941 ------------------ 1 file changed, 941 deletions(-) delete mode 100644 packages/linux/patches/3.19.2/linux-061-xpad_steamos.patch diff --git a/packages/linux/patches/3.19.2/linux-061-xpad_steamos.patch b/packages/linux/patches/3.19.2/linux-061-xpad_steamos.patch deleted file mode 100644 index a4207d6b49..0000000000 --- a/packages/linux/patches/3.19.2/linux-061-xpad_steamos.patch +++ /dev/null @@ -1,941 +0,0 @@ ---- linux-3.19.2.orig/drivers/input/joystick/xpad.c 2015-03-22 15:23:17.000000000 +0100 -+++ linux-3.19.2/drivers/input/joystick/xpad.c 2015-03-22 15:18:03.000000000 +0100 -@@ -74,6 +74,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -315,6 +316,12 @@ - - MODULE_DEVICE_TABLE(usb, xpad_table); - -+struct irq_out_data { -+ struct list_head list; -+ unsigned char odata[XPAD_PKT_LEN]; -+ u32 odata_length; -+}; -+ - struct usb_xpad { - struct input_dev *dev; /* input device interface */ - struct usb_device *udev; /* usb device */ -@@ -330,20 +337,30 @@ - unsigned char *bdata; - - struct urb *irq_out; /* urb for interrupt out report */ -+ int irq_out_busy; /* is urb submitted, odata_lock must be held */ - unsigned char *odata; /* output data */ - dma_addr_t odata_dma; -- struct mutex odata_mutex; -+ spinlock_t odata_lock; -+ struct list_head odata_list; /* odata_lock must be held */ -+ -+ unsigned char odata_serial; /* serial number for xbox one protocol */ - - #if defined(CONFIG_JOYSTICK_XPAD_LEDS) - struct xpad_led *led; - #endif -+ -+ int joydev_id; - - char phys[64]; /* physical device path */ - - int mapping; /* map d-pad to buttons or to axes */ - int xtype; /* type of xbox device */ -+ -+ const char *name; - }; - -+static int xpad_send_ff(struct usb_xpad *xpad, int strong, int weak); -+ - /* - * xpad_process_packet - * -@@ -485,6 +502,116 @@ - - input_sync(dev); - } -+static void xpad_send_led_command(struct usb_xpad *xpad, int command); -+static int xpad_open(struct input_dev *dev); -+static void xpad_close(struct input_dev *dev); -+static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs); -+static int xpad_init_ff(struct usb_xpad *xpad); -+static int xpad_find_joydev(struct device *dev, void *data) -+{ -+ if (strstr(dev_name(dev), "js")) -+ return 1; -+ -+ return 0; -+} -+ -+static struct workqueue_struct *my_wq; -+ -+typedef struct { -+ struct work_struct my_work; -+ struct usb_xpad *xpad; -+} my_work_t; -+ -+static void my_wq_function( struct work_struct *work) -+{ -+ my_work_t *my_work = (my_work_t *)work; -+ int ret; -+ -+ struct usb_xpad *xpad = my_work->xpad; -+ -+ if (xpad->pad_present) { -+ -+ struct input_dev *input_dev; -+ int i; -+ -+ input_dev = input_allocate_device(); -+ -+ 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); -+ } 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]); -+ } -+ -+ ret = input_register_device(xpad->dev); -+ -+ if (ret == 0) -+ { -+ struct device* joydev_dev = device_find_child(&xpad->dev->dev, NULL, xpad_find_joydev); -+ -+ if (joydev_dev) { -+// printk("found joydev child with minor %i\n", MINOR(joydev_dev->devt)); -+ xpad->joydev_id = MINOR(joydev_dev->devt); -+ xpad_send_led_command(xpad, (xpad->joydev_id % 4) + 2); -+ } -+ } -+ else -+ { -+ printk("xpad: Unable to register input device: %d\n", ret); -+ } -+ -+ xpad_init_ff(xpad); -+ } else { -+ input_unregister_device(xpad->dev); -+ } -+ -+ kfree( (void *)work ); -+ -+ return; -+} - - /* - * xpad360w_process_packet -@@ -506,11 +633,35 @@ - /* 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 (!xpad->pad_present) -+ { -+ my_work_t * work; -+ xpad->pad_present = 1; -+ usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); -+ -+ work = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL); -+ INIT_WORK( (struct work_struct *)work, my_wq_function ); -+ work->xpad = xpad; -+ queue_work( my_wq, (struct work_struct *)work ); -+ } -+ -+ } else { -+ if (xpad->pad_present) -+ { -+ my_work_t * work; -+ xpad->pad_present = 0; -+ -+ work = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL); -+ INIT_WORK( (struct work_struct *)work, my_wq_function ); -+ work->xpad = xpad; -+ queue_work( my_wq, (struct work_struct *)work ); -+ } -+// printk("got kill packet for id %i\n", xpad->joydev_id); -+ } - } -+ -+// printk("xpad packet %hhX %hhX %hhX %hhX %hhX %hhX\n", data[0], data[1], data[2], data[3], data[4], data[5]); - - /* Valid pad data */ - if (!(data[1] & 0x1)) -@@ -625,6 +776,8 @@ - int retval, status; - - status = urb->status; -+ -+// printk("xpad_irq_in %i\n", status); - - switch (status) { - case 0: -@@ -686,18 +839,45 @@ - } - } - -+/* odata_lock must be held */ -+static void xpad_clear_odata_list(struct usb_xpad *xpad) -+{ -+ struct list_head *n, *p; -+ -+ list_for_each_safe(p, n, &xpad->odata_list) { -+ struct irq_out_data *out = list_entry(p, struct irq_out_data, list); -+ list_del(&out->list); -+ kfree(out); -+ } -+} -+ - static void xpad_irq_out(struct urb *urb) - { - struct usb_xpad *xpad = urb->context; - struct device *dev = &xpad->intf->dev; - int retval, status; -+ unsigned long flags; -+ struct irq_out_data *out; -+ -+ spin_lock_irqsave(&xpad->odata_lock, flags); - - status = urb->status; - - switch (status) { - case 0: -- /* success */ -- return; -+ /* success, submit next packet from queue, if not empty */ -+ if (!list_empty(&xpad->odata_list)) { -+ out = list_first_entry(&xpad->odata_list, -+ struct irq_out_data, -+ list); -+ list_del(&out->list); -+ memcpy(xpad->odata, out->odata, out->odata_length); -+ urb->transfer_buffer_length = out->odata_length; -+ kfree(out); -+ goto resubmit; -+ } -+ xpad->irq_out_busy = 0; -+ goto exit; - - case -ECONNRESET: - case -ENOENT: -@@ -705,19 +885,24 @@ - /* this urb is terminated, clean up */ - dev_dbg(dev, "%s - urb shutting down with status: %d\n", - __func__, status); -- return; -+ xpad_clear_odata_list(xpad); -+ xpad->irq_out_busy = 0; -+ // TODO: Clean odata_list ? -+ goto exit; - - default: - dev_dbg(dev, "%s - nonzero urb status received: %d\n", - __func__, status); -- goto exit; -+ goto resubmit; - } - --exit: -+resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s - usb_submit_urb failed with result %d\n", - __func__, retval); -+exit: -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); - } - - static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) -@@ -736,14 +921,15 @@ - goto fail1; - } - -- mutex_init(&xpad->odata_mutex); -- - xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->irq_out) { - error = -ENOMEM; - goto fail2; - } - -+ INIT_LIST_HEAD(&xpad->odata_list); -+ spin_lock_init(&xpad->odata_lock); -+ - /* Xbox One controller has in/out endpoints swapped. */ - ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1; - ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc; -@@ -763,8 +949,22 @@ - - static void xpad_stop_output(struct usb_xpad *xpad) - { -- if (xpad->xtype != XTYPE_UNKNOWN) -+ unsigned long flags; -+ -+ if (xpad->xtype != XTYPE_UNKNOWN) { - usb_kill_urb(xpad->irq_out); -+ -+ spin_lock_irqsave(&xpad->odata_lock, flags); -+ -+ /* Empty odata_list, in case URB was not pending */ -+ xpad_clear_odata_list(xpad); -+ xpad->irq_out_busy = 0; -+ -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ -+ /* Stop rumble */ -+ xpad_send_ff(xpad, 0, 0); -+ } - } - - static void xpad_deinit_output(struct usb_xpad *xpad) -@@ -776,64 +976,157 @@ - } - } - -+/* xpad->odata_lock must be held */ -+static unsigned char* xpad_get_irq_out_buffer(struct usb_xpad *xpad) -+{ -+ struct irq_out_data *out; -+ -+ if (xpad->irq_out_busy) { -+ /* Allocate list item and add to the end of odata_list */ -+ out = kzalloc(sizeof(*out), GFP_ATOMIC); -+ if (!out) -+ return NULL; -+ INIT_LIST_HEAD(&out->list); -+ list_add_tail(&out->list, &xpad->odata_list); -+ return out->odata; -+ } else { -+ return xpad->odata; -+ } -+} -+ -+/* xpad->odata_lock must be held */ -+static int xpad_submit_irq_out_buffer(struct usb_xpad *xpad, unsigned char* buf, u32 length) -+{ -+ struct irq_out_data *out; -+ -+ if (xpad->irq_out_busy) { -+ /* Get the last entry of the list */ -+ out = list_entry(xpad->odata_list.prev, struct irq_out_data, list); -+ if (buf == out->odata) { -+ out->odata_length = length; -+ } else { -+ dev_err(&xpad->intf->dev, "%s - bad odata_list item! %p %p\n", -+ __func__, out, buf); -+ return -EINVAL; -+ } -+ } else { -+ if (buf == xpad->irq_out->transfer_buffer) { -+ xpad->irq_out_busy = 1; -+ xpad->irq_out->transfer_buffer_length = length; -+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); -+ } else { -+ dev_err(&xpad->intf->dev, "%s - bad irq_out odata! %p %p\n", -+ __func__, xpad->irq_out->transfer_buffer, buf); -+ return -EINVAL; -+ } -+ } -+ return 0; -+} -+ - #ifdef CONFIG_JOYSTICK_XPAD_FF --static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) -+static int xpad_send_ff(struct usb_xpad *xpad, int strong, int weak) - { -- struct usb_xpad *xpad = input_get_drvdata(dev); -+ unsigned char *odata; -+ u32 transfer_length = 0; -+ unsigned long flags; -+ int error = 0; - -- if (effect->type == FF_RUMBLE) { -- __u16 strong = effect->u.rumble.strong_magnitude; -- __u16 weak = effect->u.rumble.weak_magnitude; -+ /* Check type, fall fast for unsupported types */ -+ switch (xpad->xtype) { -+ case XTYPE_XBOX: -+ case XTYPE_XBOX360: -+ case XTYPE_XBOX360W: -+ case XTYPE_XBOXONE: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&xpad->odata_lock, flags); - -- switch (xpad->xtype) { -+ odata = xpad_get_irq_out_buffer(xpad); -+ if (!odata) { -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ return -ENOMEM; -+ } -+ -+ 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; -+ odata[0] = 0x00; -+ odata[1] = 0x06; -+ odata[2] = 0x00; -+ odata[3] = strong / 256; /* left actuator */ -+ odata[4] = 0x00; -+ odata[5] = weak / 256; /* right actuator */ - -- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); -+ transfer_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; -+ odata[0] = 0x00; -+ odata[1] = 0x08; -+ odata[2] = 0x00; -+ odata[3] = strong / 256; /* left actuator? */ -+ odata[4] = weak / 256; /* right actuator? */ -+ odata[5] = 0x00; -+ odata[6] = 0x00; -+ odata[7] = 0x00; - -- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); -+ transfer_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; -+ odata[0] = 0x00; -+ odata[1] = 0x01; -+ odata[2] = 0x0F; -+ odata[3] = 0xC0; -+ odata[4] = 0x00; -+ odata[5] = strong / 256; -+ odata[6] = weak / 256; -+ odata[7] = 0x00; -+ odata[8] = 0x00; -+ odata[9] = 0x00; -+ odata[10] = 0x00; -+ odata[11] = 0x00; - -- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); -+ transfer_length = 12; -+ break; - -- default: -- dev_dbg(&xpad->dev->dev, -- "%s - rumble command sent to unsupported xpad type: %d\n", -- __func__, xpad->xtype); -- return -1; -- } -+ case XTYPE_XBOXONE: -+ odata[0] = 0x09; -+ odata[1] = 0x00; -+ odata[2] = xpad->odata_serial++; -+ odata[3] = 0x09; -+ odata[4] = 0x00; -+ odata[5] = 0x0F; -+ odata[6] = 0x00; -+ odata[7] = 0x00; -+ odata[8] = strong / 512; -+ odata[9] = weak / 512; -+ odata[10] = 0xFF; -+ odata[11] = 0x00; -+ odata[12] = 0x00; -+ -+ transfer_length = 13; -+ break; -+ } -+ -+ error = xpad_submit_irq_out_buffer(xpad, odata, transfer_length); -+ -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ return error; -+} -+ -+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; -+ -+ return xpad_send_ff(xpad, strong, weak); - } - - return 0; -@@ -841,7 +1134,7 @@ - - static int xpad_init_ff(struct usb_xpad *xpad) - { -- if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE) -+ if (xpad->xtype == XTYPE_UNKNOWN) - return 0; - - input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); -@@ -851,6 +1144,7 @@ - - #else - static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } -+static int xpad_send_ff(struct usb_xpad *xpad, int strong, int weak) { return 0; } - #endif - - #if defined(CONFIG_JOYSTICK_XPAD_LEDS) -@@ -864,15 +1158,52 @@ - - 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); -+ unsigned char *odata; -+ u32 transfer_length = 0; -+ unsigned long flags; -+ int error = 0; -+ -+ if ((unsigned)command > 15) -+ return; -+ -+ spin_lock_irqsave(&xpad->odata_lock, flags); -+ -+ odata = xpad_get_irq_out_buffer(xpad); -+ if (!odata) { -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ return; -+ } -+ -+ switch (xpad->xtype) { -+ -+ case XTYPE_XBOX360: -+ odata[0] = 0x01; -+ odata[1] = 0x03; -+ odata[2] = command; -+ transfer_length = 3; -+ break; -+ -+ case XTYPE_XBOX360W: -+ odata[0] = 0x00; -+ odata[1] = 0x00; -+ odata[2] = 0x08; -+ odata[3] = 0x40 + (command % 0x0e); -+ odata[4] = 0x00; -+ odata[5] = 0x00; -+ odata[6] = 0x00; -+ odata[7] = 0x00; -+ odata[8] = 0x00; -+ odata[9] = 0x00; -+ odata[10] = 0x00; -+ odata[11] = 0x00; -+ transfer_length = 12; -+ break; -+ } -+ -+ if (transfer_length) { -+ error = xpad_submit_irq_out_buffer(xpad, odata, transfer_length); - } -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); - } - - static void xpad_led_set(struct led_classdev *led_cdev, -@@ -886,22 +1217,24 @@ - - static int xpad_led_probe(struct usb_xpad *xpad) - { -- static atomic_t led_seq = ATOMIC_INIT(-1); -- unsigned long led_no; -+ static atomic_t led_seq = ATOMIC_INIT(0); -+ long led_no; - struct xpad_led *led; - struct led_classdev *led_cdev; - int error; -+ -+// printk("xpad_led_probe\n"); - -- if (xpad->xtype != XTYPE_XBOX360) -+ 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 = atomic_inc_return(&led_seq); -+ led_no = (long)atomic_inc_return(&led_seq) - 1; - -- snprintf(led->name, sizeof(led->name), "xpad%lu", led_no); -+ snprintf(led->name, sizeof(led->name), "xpad%ld", led_no); - led->xpad = xpad; - - led_cdev = &led->led_cdev; -@@ -915,11 +1248,6 @@ - return error; - } - -- /* -- * Light up the segment corresponding to controller number -- */ -- xpad_send_led_command(xpad, (led_no % 4) + 2); -- - return 0; - } - -@@ -940,7 +1268,11 @@ - - static int xpad_open(struct input_dev *dev) - { -+ unsigned long flags; -+ int ret; -+ unsigned char *odata; - struct usb_xpad *xpad = input_get_drvdata(dev); -+// printk("xpad open driver data %x\n", (unsigned int)xpad); - - /* URB was submitted in probe */ - if (xpad->xtype == XTYPE_XBOX360W) -@@ -951,11 +1283,25 @@ - return -EIO; - - if (xpad->xtype == XTYPE_XBOXONE) { -+ spin_lock_irqsave(&xpad->odata_lock, flags); -+ -+ odata = xpad_get_irq_out_buffer(xpad); -+ if (!odata) { -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ return -ENOMEM; -+ } -+ -+ xpad->odata_serial = 0; - /* 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); -+ odata[0] = 0x05; -+ odata[1] = 0x20; -+ odata[2] = xpad->odata_serial++; /* packet serial */ -+ odata[3] = 0x01; /* rumble bit enable? */ -+ odata[4] = 0x00; -+ ret = xpad_submit_irq_out_buffer(xpad, odata, 5); -+ -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ return ret; - } - - return 0; -@@ -1001,19 +1347,24 @@ - { - 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; -+ unsigned long flags; -+ unsigned char *odata; -+ -+ if (!my_wq) { -+ my_wq = create_workqueue("xpad_queue"); -+ } - - 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; - } -- -+ - if (xpad_device[i].xtype == XTYPE_XBOXONE && -- intf->cur_altsetting->desc.bInterfaceNumber != 0) { -+ intf->cur_altsetting->desc.bInterfaceNumber != 0) { - /* - * The Xbox One controller lists three interfaces all with the - * same interface class, subclass and protocol. Differentiate by -@@ -1023,12 +1374,9 @@ - } - - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); -- input_dev = input_allocate_device(); -- if (!xpad || !input_dev) { -- error = -ENOMEM; -- goto fail1; -- } - -+ xpad->name = xpad_device[i].name; -+ - xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->idata_dma); - if (!xpad->idata) { -@@ -1064,66 +1412,12 @@ - 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; -+ usb_make_path(xpad->udev, xpad->phys, sizeof(xpad->phys)); -+ strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - - error = xpad_led_probe(xpad); - if (error) -@@ -1140,10 +1434,6 @@ - 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) { -@@ -1151,6 +1441,7 @@ - * Setup the message to set the LEDs on the - * controller when it shows up - */ -+ spin_lock_irqsave(&xpad->odata_lock, flags); - xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->bulk_out) { - error = -ENOMEM; -@@ -1179,19 +1470,9 @@ - } - - 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); -- } -+ 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 -@@ -1202,23 +1483,60 @@ - */ - xpad->irq_in->dev = xpad->udev; - error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); -+ -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); - if (error) - goto fail9; -+ -+ // I don't know how to check controller state on driver load so just slam them -+ // off so that people have to turn them on, triggering a state update -+ -+ // got the power off packet from an OSX reverse-engineered driver: -+ // http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver#toc1 -+ spin_lock_irqsave(&xpad->odata_lock, flags); -+ -+ odata = xpad_get_irq_out_buffer(xpad); -+ if (odata) { -+ odata[0] = 0x00; -+ odata[1] = 0x00; -+ odata[2] = 0x08; -+ odata[3] = 0xC0; -+ odata[4] = 0x00; -+ odata[5] = 0x00; -+ odata[6] = 0x00; -+ odata[7] = 0x00; -+ odata[8] = 0x00; -+ odata[9] = 0x00; -+ odata[10] = 0x00; -+ odata[11] = 0x00; -+ xpad_submit_irq_out_buffer(xpad, odata, 12); -+ } -+ spin_unlock_irqrestore(&xpad->odata_lock, flags); -+ } else { -+ my_work_t *work; -+ xpad->pad_present = 1; -+ -+ work = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL); -+ INIT_WORK( (struct work_struct *)work, my_wq_function ); -+ work->xpad = xpad; -+ queue_work( my_wq, (struct work_struct *)work ); - } - - 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); -+ 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); -+ fail1: //input_free_device(input_dev); - kfree(xpad); - return error; - -@@ -1228,8 +1546,14 @@ - { - struct usb_xpad *xpad = usb_get_intfdata (intf); - -+// printk("xpad_disconnect\n"); - xpad_led_disconnect(xpad); -- input_unregister_device(xpad->dev); -+ -+ if (xpad->pad_present) -+ { -+ xpad->pad_present = 0; -+ input_unregister_device(xpad->dev); -+ } - xpad_deinit_output(xpad); - - if (xpad->xtype == XTYPE_XBOX360W) {