Skip to content

Commit

Permalink
Input: xpad - Poweroff XBOX360W on mode button long press
Browse files Browse the repository at this point in the history
Newer gamepads turn themselves off when the mode button is held down.
For XBOX360W gamepads we must do this in the driver.

Do not use BIT() macro for consistency within the file.

Signed-off-by: Santosh De Massari <[email protected]>
Signed-off-by: Pavel Rojtberg <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
  • Loading branch information
Santosh De Massari authored and dtor committed Sep 6, 2022
1 parent a17b984 commit da7e212
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions drivers/input/joystick/xpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
#define XTYPE_XBOXONE 3
#define XTYPE_UNKNOWN 4

/* Send power-off packet to xpad360w after holding the mode button for this many
* seconds
*/
#define XPAD360W_POWEROFF_TIMEOUT 5

static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
Expand Down Expand Up @@ -630,11 +635,13 @@ struct usb_xpad {
int pad_nr; /* the order x360 pads were attached */
const char *name; /* name of the device */
struct work_struct work; /* init/remove device from callback */
time64_t mode_btn_down_ts;
};

static int xpad_init_input(struct usb_xpad *xpad);
static void xpad_deinit_input(struct usb_xpad *xpad);
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
static void xpad360w_poweroff_controller(struct usb_xpad *xpad);

/*
* xpad_process_packet
Expand Down Expand Up @@ -786,6 +793,23 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
}

input_sync(dev);

/* XBOX360W controllers can't be turned off without driver assistance */
if (xpad->xtype == XTYPE_XBOX360W) {
if (xpad->mode_btn_down_ts > 0 && xpad->pad_present &&
((ktime_get_seconds() - xpad->mode_btn_down_ts) >=
XPAD360W_POWEROFF_TIMEOUT)) {
xpad360w_poweroff_controller(xpad);
xpad->mode_btn_down_ts = 0;
return;
}

/* mode button down/up */
if (data[3] & 0x04)
xpad->mode_btn_down_ts = ktime_get_seconds();
else
xpad->mode_btn_down_ts = 0;
}
}

static void xpad_presence_work(struct work_struct *work)
Expand Down

0 comments on commit da7e212

Please sign in to comment.