[PATCH v2 0/4] Input: xpad - improve support for new Xbox One S pad

STALE3593d

Revision v2 of 3 in this series.

6 messages, 1 author, 2016-10-04 · open the first message on its own page

[PATCH v2 0/4] Input: xpad - improve support for new Xbox One S pad

From: Cameron Gutman <hidden>
Date: 2016-08-16 04:10:18

This pad generally works well enough on the current xpad, but there are
a few usability issues that I'm fixing with this series.

The notable changes:

The protocol seems to have changed a bit with the new pad. For one, it
needs an ack for the mode report now, otherwise it just retransmits it
forever. This makes the mode button look stuck down to userspace after
the first time it is pressed.

It also seems to overflow some internal buffer, hang, then eventually
reset the pad if there is user input without the driver listening.
This causes a spurious disconnection that may cause userspace programs
to behave unexpectedly.

Changes in v2:
Fixed multi-line comment style in patch 2 and 3 to be consistent with
the existing code. I've also added a simple patch to address rumble
issues on all Xbox One pads, including Xbox One S.

Cameron Gutman (4):
  Input: xpad - add device ID for Xbox One S pad
  Input: xpad - fix One S pad disconnecting when not opened
  Input: xpad - fix stuck mode button on Xbox One S pad
  Input: xpad - fix Xbox One rumble stopping after 2.5 secs

 drivers/input/joystick/xpad.c | 60 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 6 deletions(-)

-- 
2.7.4

[PATCH v2 1/4] Input: xpad - add device ID for Xbox One S pad

From: Cameron Gutman <hidden>
Date: 2016-08-16 04:10:19

This is the new gamepad that ships with the Xbox One S which
includes Bluetooth functionality.

Signed-off-by: Cameron Gutman <redacted>
---
 drivers/input/joystick/xpad.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 83af17a..19886db 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -134,6 +134,7 @@ static const struct xpad_device {
 	{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
+	{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
 	{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
 	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
-- 
2.7.4

[PATCH v2 2/4] Input: xpad - fix One S pad disconnecting when not opened

From: Cameron Gutman <hidden>
Date: 2016-08-16 04:10:20

The Xbox One S controller will hang after ~2 seconds of input
if it isn't being read by the OS. After another ~5 seconds the
controller will reset itself and reconnect to the host.

To avoid this, we'll just read Xbox One controllers all the time,
like we do for Xbox 360 wireless adapters.

Signed-off-by: Cameron Gutman <redacted>
---
 drivers/input/joystick/xpad.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 19886db..3577253 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1381,7 +1381,7 @@ static int xpad_init_input(struct usb_xpad *xpad)
 
 	input_set_drvdata(input_dev, xpad);
 
-	if (xpad->xtype != XTYPE_XBOX360W) {
+	if (xpad->xtype != XTYPE_XBOX360W && xpad->xtype != XTYPE_XBOXONE) {
 		input_dev->open = xpad_open;
 		input_dev->close = xpad_close;
 	}
@@ -1573,9 +1573,21 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
 		error = xpad_init_input(xpad);
 		if (error)
 			goto err_deinit_output;
+
+		/*
+		 * Newer Xbox One controllers will hang and disconnect if
+		 * not initialized and read from when receiving user input.
+		 */
+		if (xpad->xtype == XTYPE_XBOXONE) {
+			error = xpad_start_input(xpad);
+			if (error)
+				goto err_deinit_input;
+		}
 	}
 	return 0;
 
+err_deinit_input:
+	xpad_deinit_input(xpad);
 err_deinit_output:
 	xpad_deinit_output(xpad);
 err_free_in_urb:
@@ -1593,6 +1605,8 @@ static void xpad_disconnect(struct usb_interface *intf)
 
 	if (xpad->xtype == XTYPE_XBOX360W)
 		xpad360w_stop_input(xpad);
+	else if (xpad->xtype == XTYPE_XBOXONE)
+		xpad_stop_input(xpad);
 
 	xpad_deinit_input(xpad);
 
@@ -1636,7 +1650,7 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
 			xpad360w_poweroff_controller(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input->users || xpad->xtype == XTYPE_XBOXONE)
 			xpad_stop_input(xpad);
 		mutex_unlock(&input->mutex);
 	}
@@ -1656,7 +1670,7 @@ static int xpad_resume(struct usb_interface *intf)
 		retval = xpad360w_start_input(xpad);
 	} else {
 		mutex_lock(&input->mutex);
-		if (input->users)
+		if (input->users || xpad->xtype == XTYPE_XBOXONE)
 			retval = xpad_start_input(xpad);
 		mutex_unlock(&input->mutex);
 	}
-- 
2.7.4

[PATCH v2 3/4] Input: xpad - fix stuck mode button on Xbox One S pad

From: Cameron Gutman <hidden>
Date: 2016-08-16 04:10:21

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 <redacted>
---
 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 3577253..42723ba 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -389,6 +389,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
@@ -699,6 +700,14 @@ static void xpadone_process_packet(struct usb_xpad *xpad,
 		break;
 
 	case 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]);
+
 		/* the xbox button has its own special report */
 		input_report_key(dev, BTN_MODE, data[4] & 0x01);
 		input_sync(dev);
@@ -974,6 +983,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.7.4

[PATCH v2 4/4] Input: xpad - fix Xbox One rumble stopping after 2.5 secs

From: Cameron Gutman <hidden>
Date: 2016-08-16 04:10:22

Unlike previous Xbox pads, the Xbox One pad doesn't have
"sticky" rumble packets. The duration is encoded into
the command and expiration is handled by the pad firmware.

ff-memless needs pseudo-sticky behavior for rumble effects
to behave properly for long duration effects. We already
specify the maximum rumble on duration in the command
packets, but it's still only good for about 2.5 seconds
of rumble. This is easily reproducable running fftest's
sine vibration test.

It turns out there's a repeat count encoded in the rumble
command. We can abuse that to get the pseudo-sticky behavior
needed for rumble to behave as expected for effects with long
duration.

By my math, this change should allow a single ff_effect to
rumble for 10 minutes straight, which should be more than
enough for most needs.

Signed-off-by: Cameron Gutman <redacted>
---
 drivers/input/joystick/xpad.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 42723ba..8954643 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1078,9 +1078,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 		packet->data[7] = 0x00;
 		packet->data[8] = strong / 512;	/* left actuator */
 		packet->data[9] = weak / 512;	/* right actuator */
-		packet->data[10] = 0xFF;
-		packet->data[11] = 0x00;
-		packet->data[12] = 0x00;
+		packet->data[10] = 0xFF; /* on period */
+		packet->data[11] = 0x00; /* off period */
+		packet->data[12] = 0xFF; /* repeat count */
 		packet->len = 13;
 		packet->pending = true;
 		break;
-- 
2.7.4

Re: [PATCH v2 0/4] Input: xpad - improve support for new Xbox One S pad

From: Cameron Gutman <hidden>
Date: 2016-10-04 19:29:43

On 08/15/2016 09:10 PM, Cameron Gutman wrote:
This pad generally works well enough on the current xpad, but there are
a few usability issues that I'm fixing with this series.

The notable changes:

The protocol seems to have changed a bit with the new pad. For one, it
needs an ack for the mode report now, otherwise it just retransmits it
forever. This makes the mode button look stuck down to userspace after
the first time it is pressed.

It also seems to overflow some internal buffer, hang, then eventually
reset the pad if there is user input without the driver listening.
This causes a spurious disconnection that may cause userspace programs
to behave unexpectedly.

Changes in v2:
Fixed multi-line comment style in patch 2 and 3 to be consistent with
the existing code. I've also added a simple patch to address rumble
issues on all Xbox One pads, including Xbox One S.

Cameron Gutman (4):
  Input: xpad - add device ID for Xbox One S pad
  Input: xpad - fix One S pad disconnecting when not opened
  Input: xpad - fix stuck mode button on Xbox One S pad
  Input: xpad - fix Xbox One rumble stopping after 2.5 secs

 drivers/input/joystick/xpad.c | 60 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 6 deletions(-)
Hi Dmitry,

I'm just following up on these patches. Do you want any changes or are they
fine as is?

Pavel has already applied the patches to his out-of-tree xpad driver [0].

[0] https://github.com/paroj/xpad

Thanks,
Cameron
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help