aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-24 16:42:19 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-24 16:42:19 -0800
commit72145f96a0bb72231891d63309bbd1b586a8704b (patch)
tree43eb43c1ec04a417b9cdc689c25b2db380bce453
parent798d88bf9ea205e79d015893b1f616d1de6ab039 (diff)
downloadpatches-72145f96a0bb72231891d63309bbd1b586a8704b.tar.gz
xpad patches
-rw-r--r--defer-input-nodes-and-led-support417
-rw-r--r--input-xpad-disconnect-all-wireless-controllers-at-init.patch73
-rw-r--r--input-xpad-handle-present-and-gone-correctly.patch87
-rw-r--r--input-xpad-move-the-input-device-creation-to-a-new-function.patch252
-rw-r--r--input-xpad-set-the-correct-led-number.patch78
-rw-r--r--input-xpad-set-the-leds-properly-on-xbox-wireless-controllers.patch71
-rw-r--r--series7
7 files changed, 985 insertions, 0 deletions
diff --git a/defer-input-nodes-and-led-support b/defer-input-nodes-and-led-support
new file mode 100644
index 00000000000000..f17bbfc6eab65f
--- /dev/null
+++ b/defer-input-nodes-and-led-support
@@ -0,0 +1,417 @@
+
+
+---
+ drivers/input/joystick/xpad.c | 273 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 188 insertions(+), 85 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -281,17 +281,21 @@ struct usb_xpad {
+ 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;
+ #endif
+
+ #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;
+ };
+
+ /*
+@@ -435,6 +439,109 @@ static void xpad360_process_packet(struc
+
+ 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;
++
++ 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) {
++ 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]);
++ }
++
++ input_register_device(xpad->dev);
++
++ {
++ 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);
++ }
++ }
++
++ xpad_init_ff(xpad);
++ } else {
++ input_unregister_device(xpad->dev);
++ }
++
++ kfree( (void *)work );
++
++ return;
++}
+
+ /*
+ * xpad360w_process_packet
+@@ -456,12 +563,32 @@ static void xpad360w_process_packet(stru
+ /* 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_ATOMIC);
++ 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_ATOMIC);
++ 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))
+ return;
+@@ -584,8 +711,6 @@ static int xpad_init_output(struct usb_i
+ goto fail1;
+ }
+
+- mutex_init(&xpad->odata_mutex);
+-
+ xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!xpad->irq_out) {
+ error = -ENOMEM;
+@@ -717,7 +842,7 @@ static void xpad_send_led_command(struct
+ if (command > 15)
+ return;
+
+- mutex_lock(&xpad->odata_mutex);
++ spin_lock(&xpad->odata_lock);
+
+ switch (xpad->xtype) {
+ case XTYPE_XBOX360:
+@@ -744,7 +869,7 @@ static void xpad_send_led_command(struct
+ }
+
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+- mutex_unlock(&xpad->odata_mutex);
++ spin_unlock(&xpad->odata_lock);
+ }
+
+ static void xpad_led_set(struct led_classdev *led_cdev,
+@@ -787,11 +912,6 @@ static int xpad_led_probe(struct usb_xpa
+ return error;
+ }
+
+- /*
+- * Light up the segment corresponding to controller number
+- */
+- xpad_send_led_command(xpad, (led_no % 4) + 2);
+-
+ return 0;
+ }
+
+@@ -813,6 +933,7 @@ static void xpad_led_disconnect(struct u
+ static int xpad_open(struct input_dev *dev)
+ {
+ 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)
+@@ -861,9 +982,13 @@ static int xpad_probe(struct usb_interfa
+ {
+ 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;
++// struct input_dev *input_dev;
++
++ 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) &&
+@@ -872,11 +997,8 @@ static int xpad_probe(struct usb_interfa
+ }
+
+ 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);
+@@ -913,65 +1035,12 @@ static int xpad_probe(struct usb_interfa
+ 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) {
+- 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)
+@@ -985,10 +1054,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) {
+@@ -996,6 +1061,7 @@ static int xpad_probe(struct usb_interfa
+ * Setup the message to set the LEDs on the
+ * controller when it shows up
+ */
++ spin_lock(&xpad->odata_lock);
+ xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!xpad->bulk_out) {
+ error = -ENOMEM;
+@@ -1037,23 +1103,55 @@ static int xpad_probe(struct usb_interfa
+ */
+ xpad->irq_in->dev = xpad->udev;
+ error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
++
++ spin_unlock(&xpad->odata_lock);
+ 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(&xpad->odata_lock);
++ xpad->odata[0] = 0x00;
++ xpad->odata[1] = 0x00;
++ xpad->odata[2] = 0x08;
++ 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;
++ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
++ spin_unlock(&xpad->odata_lock);
++ } 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;
++ fail7: //input_unregister_device(input_dev);
++ //input_dev = NULL;
+ fail6: xpad_led_disconnect(xpad);
+- fail5: if (input_dev)
+- input_ff_destroy(input_dev);
++ 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;
+
+@@ -1063,8 +1161,13 @@ static void xpad_disconnect(struct usb_i
+ {
+ 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) {
diff --git a/input-xpad-disconnect-all-wireless-controllers-at-init.patch b/input-xpad-disconnect-all-wireless-controllers-at-init.patch
new file mode 100644
index 00000000000000..36cc4ae77aba77
--- /dev/null
+++ b/input-xpad-disconnect-all-wireless-controllers-at-init.patch
@@ -0,0 +1,73 @@
+From foo@baz Fri Jan 24 11:58:18 PST 2014
+Date: Fri, 24 Jan 2014 11:58:18 -0800
+To: Greg KH <gregkh@linuxfoundation.org>
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+Subject: [PATCH] Input: xpad: disconnect all Wireless controllers at init
+
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+
+We initializing the driver/device, we really don't know how many
+controllers are connected. So send a "disconnect all" command to the
+base-station, and let the user pair the controllers in the order in
+which they want them assigned.
+
+Note, this means we now do not "preallocate" all 4 devices when a single
+wireless base station is seen, but require the device to be properly
+connected to the base station before that can happen. The allocation of
+the device happens in the next patch, not here, so in a way, this patch
+breaks all wireless devices...
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/joystick/xpad.c | 38 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -1074,11 +1074,41 @@ static int xpad_probe(struct usb_interfa
+ usb_kill_urb(xpad->irq_in);
+ goto fail9;
+ }
++
++ /*
++ * We don't know how to check the controller state at driver
++ * load, so just disconnect them all, requiring the user to
++ * repair the device in the order they want them used. Good
++ * point is that we don't connect devices in "random" order,
++ * but the extra step seems a bit harsh as other operating
++ * systems don't require this at the moment.
++ *
++ * Power-off packet information came from an OS-X
++ * reverse-engineered driver located at:
++ * http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver#toc1
++ */
++ mutex_lock(&xpad->odata_mutex);
++ xpad->odata[0] = 0x00;
++ xpad->odata[1] = 0x00;
++ xpad->odata[2] = 0x08;
++ 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;
++ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
++ mutex_unlock(&xpad->odata_mutex);
++ } else {
++ xpad->pad_present = 1;
++ error = xpad_init_input(xpad);
++ if (error)
++ goto fail9;
+ }
+- xpad->pad_present = 1;
+- error = xpad_init_input(xpad);
+- if (error)
+- goto fail9;
+
+ return 0;
+
diff --git a/input-xpad-handle-present-and-gone-correctly.patch b/input-xpad-handle-present-and-gone-correctly.patch
new file mode 100644
index 00000000000000..e093ec98de782b
--- /dev/null
+++ b/input-xpad-handle-present-and-gone-correctly.patch
@@ -0,0 +1,87 @@
+From foo@baz Fri Jan 24 11:59:45 PST 2014
+Date: Fri, 24 Jan 2014 11:59:45 -0800
+To: Greg KH <gregkh@linuxfoundation.org>
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+Subject: [PATCH] Input: xpad: handle "present" and "gone" correctly
+
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+
+Handle the "a new device is present" message properly by dynamically
+creating the input device at this point in time. This requires a
+workqueue as we are in interrupt context when we learn about this.
+
+Also properly disconnect any devices that we are told are removed.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/joystick/xpad.c | 37 ++++++++++++++++++++++++++++++++-----
+ 1 file changed, 32 insertions(+), 5 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -294,8 +294,11 @@ struct usb_xpad {
+ int xtype; /* type of xbox device */
+ int joydev_id; /* the minor of the device */
+ const char *name; /* name of the device */
++ struct work_struct work; /* to init/remove device from callback */
+ };
+
++static int xpad_init_input(struct usb_xpad *xpad);
++
+ /*
+ * xpad_process_packet
+ *
+@@ -438,6 +441,22 @@ static void xpad360_process_packet(struc
+ input_sync(dev);
+ }
+
++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 {
++ input_unregister_device(xpad->dev);
++ }
++}
++
+ /*
+ * xpad360w_process_packet
+ *
+@@ -452,16 +471,24 @@ static void xpad360_process_packet(struc
+ * 01.1 - Pad state (Bytes 4+) valid
+ *
+ */
+-
+ 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 (!xpad_present) {
++ xpad->pad_present = 1;
++ usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
++ INIT_WORK(&xpad->work, presence_work_function);
++ schedule_work(&xpad->work);
++ }
++ } else {
++ if (xpad->present) {
++ xpad->pad_present = 0;
++ INIT_WORK(&xpad->work, presence_work_function);
++ schedule_work(&xpad->work);
++ }
++ }
+ }
+
+ /* Valid pad data */
diff --git a/input-xpad-move-the-input-device-creation-to-a-new-function.patch b/input-xpad-move-the-input-device-creation-to-a-new-function.patch
new file mode 100644
index 00000000000000..62664704be9f46
--- /dev/null
+++ b/input-xpad-move-the-input-device-creation-to-a-new-function.patch
@@ -0,0 +1,252 @@
+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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/joystick/xpad.c | 163 +++++++++++++++++++++++-------------------
+ 1 file changed, 91 insertions(+), 72 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -292,6 +292,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 */
+ };
+
+ /*
+@@ -857,70 +858,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);
+
+@@ -965,17 +917,87 @@ static int xpad_probe(struct usb_interfa
+ xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
+ }
+
+- error = xpad_init_output(intf, xpad);
++ error = xpad_init_ff(xpad);
+ if (error)
+- goto fail3;
++ goto fail_init_ff;
+
+- error = xpad_init_ff(xpad);
++ error = input_register_device(xpad->dev);
+ if (error)
+- goto fail4;
++ goto fail_input_register;
++
++fail_init_ff:
++ input_ff_destroy(input_dev);
++
++fail_input_register:
++ 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;
+
+ error = xpad_led_probe(xpad);
+ if (error)
+- goto fail5;
++ goto fail4;
+
+ ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
+ usb_fill_int_urb(xpad->irq_in, udev,
+@@ -985,10 +1007,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) {
+@@ -999,7 +1017,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 fail6;
+ }
+
+ xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
+@@ -1037,24 +1055,25 @@ 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;
+
+ }
diff --git a/input-xpad-set-the-correct-led-number.patch b/input-xpad-set-the-correct-led-number.patch
new file mode 100644
index 00000000000000..6c4b9a01685b38
--- /dev/null
+++ b/input-xpad-set-the-correct-led-number.patch
@@ -0,0 +1,78 @@
+From foo@baz Fri Jan 24 11:26:09 PST 2014
+Date: Fri, 24 Jan 2014 11:26:09 -0800
+To: Greg KH <gregkh@linuxfoundation.org>
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+Subject: [PATCH] Input: xpad: Set the correct LED number
+
+The LED number should not just be incremented every time, that doesn't
+work, set the number based on the number it actually is.
+
+Note, the joydev subsystem doesn't allow us to easily find out the minor
+number, so we have to walk all devices in order to find a joystick
+device by looking at the name of the device. Odds are, this isn't the
+best way to do it, but I don't know of any other way at the moment.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/joystick/xpad.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -292,6 +292,7 @@ struct usb_xpad {
+
+ int mapping; /* map d-pad to buttons or to axes */
+ int xtype; /* type of xbox device */
++ int joydev_id; /* the minor of the device */
+ const char *name; /* name of the device */
+ };
+
+@@ -788,11 +789,6 @@ static int xpad_led_probe(struct usb_xpa
+ return error;
+ }
+
+- /*
+- * Light up the segment corresponding to controller number
+- */
+- xpad_send_led_command(xpad, (led_no % 4) + 2);
+-
+ return 0;
+ }
+
+@@ -858,9 +854,17 @@ static void xpad_set_up_abs(struct input
+ }
+ }
+
++static int xpad_find_joydev(struct device *dev, void *data)
++{
++ if (strstr(dev_name(dev), "js"))
++ return 1;
++ return 0;
++}
++
+ static int xpad_init_input(struct usb_xpad *xpad)
+ {
+ struct input_dev *input_dev;
++ struct device *joydev_dev;
+ int i, error;
+
+ input_dev = input_allocate_device();
+@@ -925,6 +929,17 @@ static int xpad_init_input(struct usb_xp
+ if (error)
+ goto fail_input_register;
+
++ joydev_dev = device_find_child(&xpad->dev->dev, NULL,
++ xpad_find_joydev);
++ if (joydev_dev) {
++ dev_dbg(&xpad->dev->dev, "Found xpad with minor %i\n",
++ MINOR(joydev_dev->devt));
++ xpad->joydev_id = MINOR(joydev_dev->devt);
++
++ /* Light up the segment corresponding to controller number */
++ xpad_send_led_command(xpad, (xpad->joydev_id % 4) + 2);
++ }
++
+ fail_init_ff:
+ input_ff_destroy(input_dev);
+
diff --git a/input-xpad-set-the-leds-properly-on-xbox-wireless-controllers.patch b/input-xpad-set-the-leds-properly-on-xbox-wireless-controllers.patch
new file mode 100644
index 00000000000000..b746a0f1fce0af
--- /dev/null
+++ b/input-xpad-set-the-leds-properly-on-xbox-wireless-controllers.patch
@@ -0,0 +1,71 @@
+From foo@baz Fri Jan 24 09:30:08 PST 2014
+Date: Fri, 24 Jan 2014 09:30:08 -0800
+To: Greg KH <gregkh@linuxfoundation.org>
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+Subject: [PATCH] Input: xpad: set the LEDs properly on XBox Wireless controllers
+
+From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com>
+
+Add the logic to set the LEDs on XBox Wireless controllers. Command
+sequence found by sniffing the Windows data stream when plugging the
+device in.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/joystick/xpad.c | 32 +++++++++++++++++++++++++++-----
+ 1 file changed, 27 insertions(+), 5 deletions(-)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -714,15 +714,37 @@ struct xpad_led {
+
+ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
+ {
+- if (command >= 0 && command < 14) {
+- mutex_lock(&xpad->odata_mutex);
++ if (command > 15)
++ return;
++
++ mutex_lock(&xpad->odata_mutex);
++
++ switch (xpad->xtype) {
++ case XTYPE_XBOX360:
+ 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);
++ break;
++ case XTYPE_XBOX360W:
++ xpad->odata[0] = 0x00;
++ xpad->odata[1] = 0x00;
++ xpad->odata[2] = 0x08;
++ xpad->odata[3] = 0x40 + (command % 0x0e);
++ 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;
++ break;
+ }
++
++ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
++ mutex_unlock(&xpad->odata_mutex);
+ }
+
+ static void xpad_led_set(struct led_classdev *led_cdev,
+@@ -742,7 +764,7 @@ static int xpad_led_probe(struct usb_xpa
+ struct led_classdev *led_cdev;
+ int error;
+
+- 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);
diff --git a/series b/series
index bea1cf1cdc0822..5ccec0561a6c27 100644
--- a/series
+++ b/series
@@ -1,3 +1,10 @@
+input-xpad-set-the-leds-properly-on-xbox-wireless-controllers.patch
+input-xpad-move-the-input-device-creation-to-a-new-function.patch
+input-xpad-set-the-correct-led-number.patch
+input-xpad-disconnect-all-wireless-controllers-at-init.patch
+input-xpad-handle-present-and-gone-correctly.patch
+#defer-input-nodes-and-led-support
+
staging-rtl8812ae-add-realtek-8821-pci-wifi-driver.patch
staging-rtl8821ae-rc.c-fix-up-function-prototypes.patch
staging-rtl8821ae-removed-unused-functions-and-variables.patch