Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[cascardo/linux.git] / drivers / input / joystick / xpad.c
index a529a45..83af17a 100644 (file)
@@ -115,6 +115,10 @@ static bool sticks_to_null;
 module_param(sticks_to_null, bool, S_IRUGO);
 MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
 
+static bool auto_poweroff = true;
+module_param(auto_poweroff, bool, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(auto_poweroff, "Power off wireless controllers on suspend");
+
 static const struct xpad_device {
        u16 idVendor;
        u16 idProduct;
@@ -1248,6 +1252,36 @@ static void xpad_stop_input(struct usb_xpad *xpad)
        usb_kill_urb(xpad->irq_in);
 }
 
+static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
+{
+       unsigned long flags;
+       struct xpad_output_packet *packet =
+                       &xpad->out_packets[XPAD_OUT_CMD_IDX];
+
+       spin_lock_irqsave(&xpad->odata_lock, flags);
+
+       packet->data[0] = 0x00;
+       packet->data[1] = 0x00;
+       packet->data[2] = 0x08;
+       packet->data[3] = 0xC0;
+       packet->data[4] = 0x00;
+       packet->data[5] = 0x00;
+       packet->data[6] = 0x00;
+       packet->data[7] = 0x00;
+       packet->data[8] = 0x00;
+       packet->data[9] = 0x00;
+       packet->data[10] = 0x00;
+       packet->data[11] = 0x00;
+       packet->len = 12;
+       packet->pending = true;
+
+       /* Reset the sequence so we send out poweroff now */
+       xpad->last_out_packet = -1;
+       xpad_try_sending_next_out_packet(xpad);
+
+       spin_unlock_irqrestore(&xpad->odata_lock, flags);
+}
+
 static int xpad360w_start_input(struct usb_xpad *xpad)
 {
        int error;
@@ -1590,6 +1624,15 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
                 * or goes away.
                 */
                xpad360w_stop_input(xpad);
+
+               /*
+                * The wireless adapter is going off now, so the
+                * gamepads are going to become disconnected.
+                * Unless explicitly disabled, power them down
+                * so they don't just sit there flashing.
+                */
+               if (auto_poweroff && xpad->pad_present)
+                       xpad360w_poweroff_controller(xpad);
        } else {
                mutex_lock(&input->mutex);
                if (input->users)