Commit 57b8443d authored by Cameron Gutman's avatar Cameron Gutman Committed by Dmitry Torokhov

Input: xpad - fix stuck mode button on Xbox One S pad

The Xbox One S requires an ack to its mode button report, otherwise it
continuously retransmits the report. This makes the mode button appear to
be stuck down after it is pressed for the first time.
Signed-off-by: default avatarCameron Gutman <aicommander@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 5ec69524
...@@ -389,6 +389,7 @@ struct usb_xpad { ...@@ -389,6 +389,7 @@ struct usb_xpad {
static int xpad_init_input(struct usb_xpad *xpad); static int xpad_init_input(struct usb_xpad *xpad);
static void xpad_deinit_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);
/* /*
* xpad_process_packet * xpad_process_packet
...@@ -622,6 +623,14 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char ...@@ -622,6 +623,14 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
/* the xbox button has its own special report */ /* the xbox button has its own special report */
if (data[0] == 0X07) { if (data[0] == 0X07) {
/*
* The Xbox One S controller requires these reports to be
* acked otherwise it continues sending them forever and
* won't report further mode button events.
*/
if (data[1] == 0x30)
xpadone_ack_mode_report(xpad, data[2]);
input_report_key(dev, BTN_MODE, data[4] & 0x01); input_report_key(dev, BTN_MODE, data[4] & 0x01);
input_sync(dev); input_sync(dev);
return; return;
...@@ -954,6 +963,30 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad) ...@@ -954,6 +963,30 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad)
return retval; return retval;
} }
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
{
unsigned long flags;
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
static const u8 mode_report_ack[] = {
0x01, 0x20, 0x00, 0x09, 0x00, 0x07, 0x20, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00
};
spin_lock_irqsave(&xpad->odata_lock, flags);
packet->len = sizeof(mode_report_ack);
memcpy(packet->data, mode_report_ack, packet->len);
packet->data[2] = seq_num;
packet->pending = true;
/* Reset the sequence so we send out the ack now */
xpad->last_out_packet = -1;
xpad_try_sending_next_out_packet(xpad);
spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
#ifdef CONFIG_JOYSTICK_XPAD_FF #ifdef CONFIG_JOYSTICK_XPAD_FF
static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment