linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Correctly support some quirky Xbox One pads
@ 2017-02-05  0:29 Cameron Gutman
  2017-02-05  0:29 ` [PATCH 1/5] Input: xpad - use a packet array to start " Cameron Gutman
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:29 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

There are a bunch of quirky Xbox One pads that depend on weird
initialization things that the Microsoft pads don't. In this series,
I've incorporated quirk handling from Valve's Steam Link driver[0]
and the 360Controller project[1] for macOS.

Patches 1 - 3 are split that way in case 2 or 3 introduce regressions
that need to be bisected. The new packet in patch 2 has been in Pavel's
xpad repository[2] for a little over a month without complaints, and
patch 3 just sends a rumble packet on init, so I don't expect regressions.

Patch 2 was tested by a GitHub user with a Hori pad[3]. I've tested patch 3
on a previously non-working PowerA pad that I got my hands on.

I folded Patch 4 into this series as it was previously submitted alone.
It is unchanged from its original submission.

Patch 5 was a patch I had previously dropped from a previous series, but it
turns out to still be needed for Xbox One S pads on the latest firmware. It
has also been in Pavel's repository for months without complaints.

[0]: https://github.com/ValveSoftware/steamlink-sdk/blob/master/kernel/drivers/input/joystick/xpad.c
[1]: https://github.com/360Controller/360Controller
[2]: https://github.com/paroj/xpad
[3]: https://github.com/paroj/xpad/issues/59

Cameron Gutman (5):
  Input: xpad - use a packet array to start Xbox One pads
  Input: xpad - add init packet for Hori and Titanfall 2 pads
  Input: xpad - send rumble on Xbox One init to fix PowerA pads
  Input: xpad - restore LED state after device resume
  Input: xpad - fix stuck mode button on Xbox One S pad

 drivers/input/joystick/xpad.c | 102 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 88 insertions(+), 14 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] Input: xpad - use a packet array to start Xbox One pads
  2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
@ 2017-02-05  0:29 ` Cameron Gutman
  2017-02-05  0:29 ` [PATCH 2/5] Input: xpad - add init packet for Hori and Titanfall 2 pads Cameron Gutman
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:29 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

This is preparatory work for supporting some 3rd party
pads that need more initialization packets than just
one. No initialization behavior change expected.

Signed-off-by: Cameron Gutman <aicommander@gmail.com>
---
 drivers/input/joystick/xpad.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 247fd3a..6f07b5b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -343,6 +343,15 @@ struct xpad_output_packet {
 	bool pending;
 };
 
+/* Sequence numbers will be added before the packets are sent */
+static const struct xpad_output_packet xone_init_pkt[] = {
+	/*
+	 * This packet is required for all Xbox One pads with 2015
+	 * or later firmware installed (or present from the factory).
+	 */
+	{{0x05, 0x20, 0x00, 0x01, 0x00}, 5, true},
+};
+
 #define XPAD_OUT_CMD_IDX	0
 #define XPAD_OUT_FF_IDX		1
 #define XPAD_OUT_LED_IDX	(1 + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF))
@@ -373,6 +382,7 @@ struct usb_xpad {
 
 	struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS];
 	int last_out_packet;
+	int init_seq;
 
 #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
 	struct xpad_led *led;
@@ -742,8 +752,19 @@ static void xpad_irq_in(struct urb *urb)
 static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad)
 {
 	struct xpad_output_packet *pkt, *packet = NULL;
+	const struct xpad_output_packet *init_packet;
 	int i;
 
+	if (xpad->xtype == XTYPE_XBOXONE && xpad->init_seq < ARRAY_SIZE(xone_init_pkt)) {
+		init_packet = &xone_init_pkt[xpad->init_seq++];
+		memcpy(xpad->odata, init_packet->data, init_packet->len);
+		xpad->irq_out->transfer_buffer_length = init_packet->len;
+
+		/* Update packet with current sequence number */
+		xpad->odata[2] = xpad->odata_serial++;
+		return true;
+	}
+
 	for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) {
 		if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS)
 			xpad->last_out_packet = 0;
@@ -929,24 +950,17 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
 
 static int xpad_start_xbox_one(struct usb_xpad *xpad)
 {
-	struct xpad_output_packet *packet =
-			&xpad->out_packets[XPAD_OUT_CMD_IDX];
 	unsigned long flags;
 	int retval;
 
 	spin_lock_irqsave(&xpad->odata_lock, flags);
 
-	/* Xbox one controller needs to be initialized. */
-	packet->data[0] = 0x05;
-	packet->data[1] = 0x20;
-	packet->data[2] = xpad->odata_serial++; /* packet serial */
-	packet->data[3] = 0x01; /* rumble bit enable?  */
-	packet->data[4] = 0x00;
-	packet->len = 5;
-	packet->pending = true;
-
-	/* Reset the sequence so we send out start packet first */
-	xpad->last_out_packet = -1;
+	/*
+	 * Begin the init sequence by attempting to send a packet.
+	 * We will cycle through the init packet sequence before
+	 * sending any packets from the output ring.
+	 */
+	xpad->init_seq = 0;
 	retval = xpad_try_sending_next_out_packet(xpad);
 
 	spin_unlock_irqrestore(&xpad->odata_lock, flags);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] Input: xpad - add init packet for Hori and Titanfall 2 pads
  2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
  2017-02-05  0:29 ` [PATCH 1/5] Input: xpad - use a packet array to start " Cameron Gutman
@ 2017-02-05  0:29 ` Cameron Gutman
  2017-02-05  0:30 ` [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads Cameron Gutman
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:29 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

Without sending this packet, the Titanfall 2 pad (0x0e6f:0x0165)
continuously attempts to handshake with the PC and never sends
any input reports.

The Hori gamepad (0x0f0d:0x0067) analog sticks don't work if
this isn't sent, though other buttons do work without it.

Signed-off-by: Cameron Gutman <aicommander@gmail.com>
---
 drivers/input/joystick/xpad.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 6f07b5b..3f19f32b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -346,6 +346,14 @@ struct xpad_output_packet {
 /* Sequence numbers will be added before the packets are sent */
 static const struct xpad_output_packet xone_init_pkt[] = {
 	/*
+	 * This packet is required for the Titanfall 2 Xbox One pads
+	 * (0x0e6f:0x0165) to finish initialization and for Hori pads
+	 * (0x0f0d:0x0067) to make the analog sticks work.
+	 */
+	{{0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
+	  0x00, 0x00, 0x00, 0x80, 0x00}, 13, true},
+
+	/*
 	 * This packet is required for all Xbox One pads with 2015
 	 * or later firmware installed (or present from the factory).
 	 */
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads
  2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
  2017-02-05  0:29 ` [PATCH 1/5] Input: xpad - use a packet array to start " Cameron Gutman
  2017-02-05  0:29 ` [PATCH 2/5] Input: xpad - add init packet for Hori and Titanfall 2 pads Cameron Gutman
@ 2017-02-05  0:30 ` Cameron Gutman
  2017-02-06 22:13   ` Dmitry Torokhov
  2017-02-05  0:30 ` [PATCH 4/5] Input: xpad - restore LED state after device resume Cameron Gutman
  2017-02-05  0:30 ` [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad Cameron Gutman
  4 siblings, 1 reply; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:30 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

Some PowerA pads require a rumble packet to start sending
input reports.

Signed-off-by: Cameron Gutman <aicommander@gmail.com>
---
 drivers/input/joystick/xpad.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 3f19f32b..13f298d 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -358,6 +358,13 @@ static const struct xpad_output_packet xone_init_pkt[] = {
 	 * or later firmware installed (or present from the factory).
 	 */
 	{{0x05, 0x20, 0x00, 0x01, 0x00}, 5, true},
+
+	/*
+	 * A rumble packet is required for some PowerA pads to start
+	 * sending input reports. One of those pads is (0x24c6:0x543a).
+	 */
+	{{0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}, 13, true},
 };
 
 #define XPAD_OUT_CMD_IDX	0
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] Input: xpad - restore LED state after device resume
  2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
                   ` (2 preceding siblings ...)
  2017-02-05  0:30 ` [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads Cameron Gutman
@ 2017-02-05  0:30 ` Cameron Gutman
  2017-02-05  1:17   ` kbuild test robot
  2017-02-06 22:05   ` Dmitry Torokhov
  2017-02-05  0:30 ` [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad Cameron Gutman
  4 siblings, 2 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:30 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

The state of pad LEDs can be inconsistent when the system is
woken up after sleep. Rather than leaving the controllers blinking,
let's resend the last LED command to Xbox 360 pads on resume.

Since Xbox One pads stop flashing only when reinitialized, we'll
send them the initialization packet so they calm down too.

Signed-off-by: Cameron Gutman <aicommander@gmail.com>
---
 drivers/input/joystick/xpad.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 13f298d..1179266 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1683,11 +1683,23 @@ static int xpad_resume(struct usb_interface *intf)
 		retval = xpad360w_start_input(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input->users) {
 			retval = xpad_start_input(xpad);
+		} else if (xpad->xtype == XTYPE_XBOXONE) {
+			/*
+			 * Even if there are no users, we'll send Xbox One pads
+			 * the startup sequence so they don't sit there and
+			 * blink until somebody opens the input device again.
+			 */
+			retval = xpad_start_xbox_one(xpad);
+		}
 		mutex_unlock(&input->mutex);
 	}
 
+	/* LED state is lost across resume, so resend the last command */
+	if (xpad->led)
+		xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
+
 	return retval;
 }
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad
  2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
                   ` (3 preceding siblings ...)
  2017-02-05  0:30 ` [PATCH 4/5] Input: xpad - restore LED state after device resume Cameron Gutman
@ 2017-02-05  0:30 ` Cameron Gutman
  2017-02-06 22:03   ` Dmitry Torokhov
  4 siblings, 1 reply; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  0:30 UTC (permalink / raw)
  To: dmitry.torokhov, rojtberg; +Cc: linux-input, linux-kernel, Cameron Gutman

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: Cameron Gutman <aicommander@gmail.com>
---
 drivers/input/joystick/xpad.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 1179266..eb01c54 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -414,6 +414,7 @@ struct usb_xpad {
 
 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);
 
 /*
  *	xpad_process_packet
@@ -647,6 +648,14 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
 
 	/* the xbox button has its own special report */
 	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_sync(dev);
 		return;
@@ -983,6 +992,30 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad)
 	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
 static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/5] Input: xpad - restore LED state after device resume
  2017-02-05  0:30 ` [PATCH 4/5] Input: xpad - restore LED state after device resume Cameron Gutman
@ 2017-02-05  1:17   ` kbuild test robot
  2017-02-05  1:47     ` Cameron Gutman
  2017-02-06 22:05   ` Dmitry Torokhov
  1 sibling, 1 reply; 12+ messages in thread
From: kbuild test robot @ 2017-02-05  1:17 UTC (permalink / raw)
  To: Cameron Gutman
  Cc: kbuild-all, dmitry.torokhov, rojtberg, linux-input, linux-kernel,
	Cameron Gutman

[-- Attachment #1: Type: text/plain, Size: 1843 bytes --]

Hi Cameron,

[auto build test ERROR on input/next]
[also build test ERROR on v4.10-rc6 next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Cameron-Gutman/Correctly-support-some-quirky-Xbox-One-pads/20170205-083659
base:   https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
config: x86_64-randconfig-x016-201706 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/input/joystick/xpad.c: In function 'xpad_resume':
>> drivers/input/joystick/xpad.c:1700:10: error: 'struct usb_xpad' has no member named 'led'
     if (xpad->led)
             ^~
>> drivers/input/joystick/xpad.c:1701:3: error: implicit declaration of function 'xpad_send_led_command' [-Werror=implicit-function-declaration]
      xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
      ^~~~~~~~~~~~~~~~~~~~~
   drivers/input/joystick/xpad.c:1701:35: error: 'struct usb_xpad' has no member named 'led'
      xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
                                      ^~
   cc1: some warnings being treated as errors

vim +1700 drivers/input/joystick/xpad.c

  1694				retval = xpad_start_xbox_one(xpad);
  1695			}
  1696			mutex_unlock(&input->mutex);
  1697		}
  1698	
  1699		/* LED state is lost across resume, so resend the last command */
> 1700		if (xpad->led)
> 1701			xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
  1702	
  1703		return retval;
  1704	}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27535 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/5] Input: xpad - restore LED state after device resume
  2017-02-05  1:17   ` kbuild test robot
@ 2017-02-05  1:47     ` Cameron Gutman
  0 siblings, 0 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-05  1:47 UTC (permalink / raw)
  To: dmitry.torokhov; +Cc: rojtberg, linux-input, linux-kernel


On 02/04/2017 05:17 PM, kbuild test robot wrote:
> Hi Cameron,
> 
> [auto build test ERROR on input/next]
> [also build test ERROR on v4.10-rc6 next-20170203]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Cameron-Gutman/Correctly-support-some-quirky-Xbox-One-pads/20170205-083659
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
> config: x86_64-randconfig-x016-201706 (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64 
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/input/joystick/xpad.c: In function 'xpad_resume':
>>> drivers/input/joystick/xpad.c:1700:10: error: 'struct usb_xpad' has no member named 'led'
>      if (xpad->led)
>              ^~
>>> drivers/input/joystick/xpad.c:1701:3: error: implicit declaration of function 'xpad_send_led_command' [-Werror=implicit-function-declaration]
>       xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
>       ^~~~~~~~~~~~~~~~~~~~~
>    drivers/input/joystick/xpad.c:1701:35: error: 'struct usb_xpad' has no member named 'led'
>       xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
>                                       ^~
>    cc1: some warnings being treated as errors

Whoops, missed a CONFIG_JOYSTICK_XPAD_LEDS guard around that.

I'll send a v2 in the next day or two, incorporating this fix plus any review
comments made in the meantime.

> 
> vim +1700 drivers/input/joystick/xpad.c
> 
>   1694				retval = xpad_start_xbox_one(xpad);
>   1695			}
>   1696			mutex_unlock(&input->mutex);
>   1697		}
>   1698	
>   1699		/* LED state is lost across resume, so resend the last command */
>> 1700		if (xpad->led)
>> 1701			xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
>   1702	
>   1703		return retval;
>   1704	}
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> 

Regards,
Cameron

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad
  2017-02-05  0:30 ` [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad Cameron Gutman
@ 2017-02-06 22:03   ` Dmitry Torokhov
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Torokhov @ 2017-02-06 22:03 UTC (permalink / raw)
  To: Cameron Gutman; +Cc: rojtberg, linux-input, linux-kernel

On Sat, Feb 04, 2017 at 04:30:02PM -0800, Cameron Gutman wrote:
> 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: Cameron Gutman <aicommander@gmail.com>

Applied, thank you.

> ---
>  drivers/input/joystick/xpad.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
> index 1179266..eb01c54 100644
> --- a/drivers/input/joystick/xpad.c
> +++ b/drivers/input/joystick/xpad.c
> @@ -414,6 +414,7 @@ struct usb_xpad {
>  
>  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);
>  
>  /*
>   *	xpad_process_packet
> @@ -647,6 +648,14 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
>  
>  	/* the xbox button has its own special report */
>  	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_sync(dev);
>  		return;
> @@ -983,6 +992,30 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad)
>  	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
>  static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
>  {
> -- 
> 2.9.3
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/5] Input: xpad - restore LED state after device resume
  2017-02-05  0:30 ` [PATCH 4/5] Input: xpad - restore LED state after device resume Cameron Gutman
  2017-02-05  1:17   ` kbuild test robot
@ 2017-02-06 22:05   ` Dmitry Torokhov
  2017-02-06 22:57     ` Cameron Gutman
  1 sibling, 1 reply; 12+ messages in thread
From: Dmitry Torokhov @ 2017-02-06 22:05 UTC (permalink / raw)
  To: Cameron Gutman; +Cc: rojtberg, linux-input, linux-kernel

On Sat, Feb 04, 2017 at 04:30:01PM -0800, Cameron Gutman wrote:
> The state of pad LEDs can be inconsistent when the system is
> woken up after sleep. Rather than leaving the controllers blinking,
> let's resend the last LED command to Xbox 360 pads on resume.
> 
> Since Xbox One pads stop flashing only when reinitialized, we'll
> send them the initialization packet so they calm down too.
> 
> Signed-off-by: Cameron Gutman <aicommander@gmail.com>
> ---
>  drivers/input/joystick/xpad.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
> index 13f298d..1179266 100644
> --- a/drivers/input/joystick/xpad.c
> +++ b/drivers/input/joystick/xpad.c
> @@ -1683,11 +1683,23 @@ static int xpad_resume(struct usb_interface *intf)
>  		retval = xpad360w_start_input(xpad);
>  	} else {
>  		mutex_lock(&input->mutex);
> -		if (input->users)
> +		if (input->users) {
>  			retval = xpad_start_input(xpad);
> +		} else if (xpad->xtype == XTYPE_XBOXONE) {
> +			/*
> +			 * Even if there are no users, we'll send Xbox One pads
> +			 * the startup sequence so they don't sit there and
> +			 * blink until somebody opens the input device again.
> +			 */
> +			retval = xpad_start_xbox_one(xpad);
> +		}
>  		mutex_unlock(&input->mutex);
>  	}
>  
> +	/* LED state is lost across resume, so resend the last command */
> +	if (xpad->led)
> +		xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);

I can see that we might need to send the "start" command, but I am not
sure that explicitly calling xpad_send_led_command() is needed: LED core
should restore LED state upon resume, and this should happen after its
parent (i.e. xbox device) is resumed.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads
  2017-02-05  0:30 ` [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads Cameron Gutman
@ 2017-02-06 22:13   ` Dmitry Torokhov
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Torokhov @ 2017-02-06 22:13 UTC (permalink / raw)
  To: Cameron Gutman; +Cc: rojtberg, linux-input, linux-kernel

On Sat, Feb 04, 2017 at 04:30:00PM -0800, Cameron Gutman wrote:
> Some PowerA pads require a rumble packet to start sending
> input reports.
> 
> Signed-off-by: Cameron Gutman <aicommander@gmail.com>
> ---
>  drivers/input/joystick/xpad.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
> index 3f19f32b..13f298d 100644
> --- a/drivers/input/joystick/xpad.c
> +++ b/drivers/input/joystick/xpad.c
> @@ -358,6 +358,13 @@ static const struct xpad_output_packet xone_init_pkt[] = {
>  	 * or later firmware installed (or present from the factory).
>  	 */
>  	{{0x05, 0x20, 0x00, 0x01, 0x00}, 5, true},
> +
> +	/*
> +	 * A rumble packet is required for some PowerA pads to start
> +	 * sending input reports. One of those pads is (0x24c6:0x543a).
> +	 */
> +	{{0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
> +	  0x00, 0x00, 0x00, 0x00, 0x00}, 13, true},

I am uncomfortable with us just blasting random commands to random
controllers. Can we make it device-dependent. I.e:

struct xboxone_init_packet = {
	u16 idVendor;
	u16 idProduct;
	const u8 *data;
	size_t len;
};

static const u8 xboxone_powera_init[] = {
	0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00
};

#define XBOXONE_INIT_PKT(_vid, _pid, _data)		\
	{						\
		.idVendor	= (_vid),		\
		.idProduct	= (_pid),		\
		.data		= (_data),		\
		.len		= ARRAY_SIZE(data),	\
	}
...

static const struct xboxone_init_packet xboxone_init_packets[] = {
	...
	XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_powera_init),
	...

With 0/0 VID/PID being "catch all" entry.

BTW, why do we set "pending" on these ones? I do not think it is needed.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/5] Input: xpad - restore LED state after device resume
  2017-02-06 22:05   ` Dmitry Torokhov
@ 2017-02-06 22:57     ` Cameron Gutman
  0 siblings, 0 replies; 12+ messages in thread
From: Cameron Gutman @ 2017-02-06 22:57 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: rojtberg, linux-input, linux-kernel

On 02/06/2017 02:05 PM, Dmitry Torokhov wrote:
> On Sat, Feb 04, 2017 at 04:30:01PM -0800, Cameron Gutman wrote:
>> The state of pad LEDs can be inconsistent when the system is
>> woken up after sleep. Rather than leaving the controllers blinking,
>> let's resend the last LED command to Xbox 360 pads on resume.
>>
>> Since Xbox One pads stop flashing only when reinitialized, we'll
>> send them the initialization packet so they calm down too.
>>
>> Signed-off-by: Cameron Gutman <aicommander@gmail.com>
>> ---
>>  drivers/input/joystick/xpad.c | 14 +++++++++++++-
>>  1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
>> index 13f298d..1179266 100644
>> --- a/drivers/input/joystick/xpad.c
>> +++ b/drivers/input/joystick/xpad.c
>> @@ -1683,11 +1683,23 @@ static int xpad_resume(struct usb_interface *intf)
>>  		retval = xpad360w_start_input(xpad);
>>  	} else {
>>  		mutex_lock(&input->mutex);
>> -		if (input->users)
>> +		if (input->users) {
>>  			retval = xpad_start_input(xpad);
>> +		} else if (xpad->xtype == XTYPE_XBOXONE) {
>> +			/*
>> +			 * Even if there are no users, we'll send Xbox One pads
>> +			 * the startup sequence so they don't sit there and
>> +			 * blink until somebody opens the input device again.
>> +			 */
>> +			retval = xpad_start_xbox_one(xpad);
>> +		}
>>  		mutex_unlock(&input->mutex);
>>  	}
>>  
>> +	/* LED state is lost across resume, so resend the last command */
>> +	if (xpad->led)
>> +		xpad_send_led_command(xpad, xpad->led->led_cdev.brightness);
> 
> I can see that we might need to send the "start" command, but I am not
> sure that explicitly calling xpad_send_led_command() is needed: LED core
> should restore LED state upon resume, and this should happen after its
> parent (i.e. xbox device) is resumed.
> 
> Thanks.
> 

Ah, so it seems we're missing the LED_CORE_SUSPENDRESUME flag on our LED
device required for that to happen automatically. I'll just use that
instead of manually setting brightness on resume.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-02-06 22:57 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-05  0:29 [PATCH 0/5] Correctly support some quirky Xbox One pads Cameron Gutman
2017-02-05  0:29 ` [PATCH 1/5] Input: xpad - use a packet array to start " Cameron Gutman
2017-02-05  0:29 ` [PATCH 2/5] Input: xpad - add init packet for Hori and Titanfall 2 pads Cameron Gutman
2017-02-05  0:30 ` [PATCH 3/5] Input: xpad - send rumble on Xbox One init to fix PowerA pads Cameron Gutman
2017-02-06 22:13   ` Dmitry Torokhov
2017-02-05  0:30 ` [PATCH 4/5] Input: xpad - restore LED state after device resume Cameron Gutman
2017-02-05  1:17   ` kbuild test robot
2017-02-05  1:47     ` Cameron Gutman
2017-02-06 22:05   ` Dmitry Torokhov
2017-02-06 22:57     ` Cameron Gutman
2017-02-05  0:30 ` [PATCH 5/5] Input: xpad - fix stuck mode button on Xbox One S pad Cameron Gutman
2017-02-06 22:03   ` Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).