linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] xpad.c: Send necessary control transfer to certain Xbox controllers
@ 2019-03-23 16:46 Mike Salvatore
  2019-04-16 23:31 ` Mike Salvatore
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Salvatore @ 2019-03-23 16:46 UTC (permalink / raw)
  To: dmitry.torokhov, linux-input
  Cc: ramzeto, marcus.folkesson, flibitijibibo, aicommander,
	leosperling97, gottox, frtherien, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 4235 bytes --]

Hi,

I recently purchased an Xbox controller with USB ID 045e:028e. When I plugged
the device in, it was recognized as a joystick but button presses were not
recognized. Using evtest, I confirmed that the device was not sending any
information to the host when I pressed its buttons.

After doing some research, I found that this particular device requires that the
host send a control transfer before the device will begin sending any data to
the host. Below is a patch that introduces a mechanism into xpad.c for sending
control transfers to specific Xbox controllers at initialization.

After applying this patch to the xpad module, the Xbox controller is properly
initialized when plugged in and functions as expected. Other Xbox controllers
may also require control transfers at initialization, but I don't know which (if
any).

Regards,
Mike Salvatore


From 3051524e62d68b920019bcb50a713e736fcf4234 Mon Sep 17 00:00:00 2001
From: Mike Salvatore <mike.salvatore@canonical.com>
Date: Wed, 13 Mar 2019 22:11:37 -0400
Subject: [PATCH] Input: xpad - send control init message to certain Xbox
 controllers

The Xbox controller with idVendor == 0x045e and idProduct == 0x028e
requires that a specific control transfer be sent from the host to the
device before the device will send data to the host.

This patch introduces an xboxone_control_packet struct and a mechanism
for sending control packets to devices that require them at
initialization.

Signed-off-by: Mike Salvatore <mike.salvatore@canonical.com>
---
 drivers/input/joystick/xpad.c | 56 +++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index cfc8b94527b9..f45522b9ff1f 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -460,6 +460,25 @@ struct xboxone_init_packet {
 		.len		= ARRAY_SIZE(_data),	\
 	}
 
+struct xboxone_control_packet {
+	u16 idVendor;
+	u16 idProduct;
+	struct usb_ctrlrequest ctrlrequest;
+};
+
+#define XBOXONE_CONTROL_PKT(_vid, _pid, _reqtype, _req, _value, _index, _len)  \
+	{						\
+		.idVendor	= (_vid),		\
+		.idProduct	= (_pid),		\
+		.ctrlrequest    = {			\
+			.bRequestType	= (_reqtype),	\
+			.bRequest	= (_req),	\
+			.wValue		= (_value),	\
+			.wIndex		= (_index),	\
+			.wLength	= (_len),	\
+		},					\
+	}
+
 
 /*
  * This packet is required for all Xbox One pads with 2015
@@ -537,6 +556,13 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
 	XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init),
 };
 
+static const struct xboxone_control_packet xboxone_control_packets[] = {
+	XBOXONE_CONTROL_PKT(0x045e, 0x028e,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			USB_REQ_CLEAR_FEATURE,
+			USB_DEVICE_REMOTE_WAKEUP, 0, 0),
+};
+
 struct xpad_output_packet {
 	u8 data[XPAD_PKT_LEN];
 	u8 len;
@@ -1119,6 +1145,31 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
 	return error;
 }
 
+static int xpad_init_control_msg(struct usb_xpad *xpad)
+{
+	struct usb_device *udev = xpad->udev;
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(xboxone_control_packets); i++) {
+		u16 idVendor = xboxone_control_packets[i].idVendor;
+		u16 idProduct = xboxone_control_packets[i].idProduct;
+
+		if (le16_to_cpu(udev->descriptor.idVendor) == idVendor
+		    && le16_to_cpu(udev->descriptor.idProduct) == idProduct) {
+			const struct usb_ctrlrequest *ctrlrequest =
+				&(xboxone_control_packets[i].ctrlrequest);
+
+			return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				ctrlrequest->bRequest,
+				ctrlrequest->bRequestType, ctrlrequest->wValue,
+				ctrlrequest->wIndex, NULL, ctrlrequest->wLength,
+				2 * HZ);
+		}
+	}
+
+	return 0;
+}
+
 static void xpad_stop_output(struct usb_xpad *xpad)
 {
 	if (xpad->xtype != XTYPE_UNKNOWN) {
@@ -1839,6 +1890,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
 		if (error)
 			goto err_deinit_output;
 	}
+
+	error = xpad_init_control_msg(xpad);
+	if (error)
+		goto err_deinit_output;
+
 	return 0;
 
 err_deinit_output:
-- 
2.17.1



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH] xpad.c: Send necessary control transfer to certain Xbox controllers
  2019-03-23 16:46 [PATCH] xpad.c: Send necessary control transfer to certain Xbox controllers Mike Salvatore
@ 2019-04-16 23:31 ` Mike Salvatore
  0 siblings, 0 replies; 2+ messages in thread
From: Mike Salvatore @ 2019-04-16 23:31 UTC (permalink / raw)
  To: dmitry.torokhov, linux-input
  Cc: ramzeto, marcus.folkesson, flibitijibibo, aicommander,
	leosperling97, gottox, frtherien, linux-kernel, Mike Salvatore,
	mike.s.salvatore


[-- Attachment #1.1: Type: text/plain, Size: 7344 bytes --]

All,

I took another look at this patch and realized it was missing a #include.
I've added the appropriate #include to a new version of the patch.

Thanks,
Mike Salvatore



From 6fbf80fa3d5bc39fa054350a663080e1380046f8 Mon Sep 17 00:00:00 2001
From: Mike Salvatore <mike.salvatore@canonical.com>
Date: Wed, 13 Mar 2019 22:11:37 -0400
Subject: [PATCH] Input: xpad - send control init message to certain Xbox
 controllers

The Xbox controller with idVendor == 0x045e and idProduct == 0x028e
requires that a specific control transfer be sent from the host to the
device before the device will send data to the host.

This patch introduces an xboxone_control_packet struct and a mechanism
for sending control packets to devices that require them at
initialization.

Signed-off-by: Mike Salvatore <mike.salvatore@canonical.com>
---
 drivers/input/joystick/xpad.c | 57 +++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index cfc8b94527b9..756df325bfa6 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -81,6 +81,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/module.h>
+#include <linux/usb/ch9.h>
 #include <linux/usb/input.h>
 #include <linux/usb/quirks.h>
 
@@ -460,6 +461,25 @@ struct xboxone_init_packet {
 		.len		= ARRAY_SIZE(_data),	\
 	}
 
+struct xboxone_control_packet {
+	u16 idVendor;
+	u16 idProduct;
+	struct usb_ctrlrequest ctrlrequest;
+};
+
+#define XBOXONE_CONTROL_PKT(_vid, _pid, _reqtype, _req, _value, _index, _len)  \
+	{						\
+		.idVendor	= (_vid),		\
+		.idProduct	= (_pid),		\
+		.ctrlrequest    = {			\
+			.bRequestType	= (_reqtype),	\
+			.bRequest	= (_req),	\
+			.wValue		= (_value),	\
+			.wIndex		= (_index),	\
+			.wLength	= (_len),	\
+		},					\
+	}
+
 
 /*
  * This packet is required for all Xbox One pads with 2015
@@ -537,6 +557,13 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
 	XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init),
 };
 
+static const struct xboxone_control_packet xboxone_control_packets[] = {
+	XBOXONE_CONTROL_PKT(0x045e, 0x028e,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			USB_REQ_CLEAR_FEATURE,
+			USB_DEVICE_REMOTE_WAKEUP, 0, 0),
+};
+
 struct xpad_output_packet {
 	u8 data[XPAD_PKT_LEN];
 	u8 len;
@@ -1119,6 +1146,31 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
 	return error;
 }
 
+static int xpad_init_control_msg(struct usb_xpad *xpad)
+{
+	struct usb_device *udev = xpad->udev;
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(xboxone_control_packets); i++) {
+		u16 idVendor = xboxone_control_packets[i].idVendor;
+		u16 idProduct = xboxone_control_packets[i].idProduct;
+
+		if (le16_to_cpu(udev->descriptor.idVendor) == idVendor
+		    && le16_to_cpu(udev->descriptor.idProduct) == idProduct) {
+			const struct usb_ctrlrequest *ctrlrequest =
+				&(xboxone_control_packets[i].ctrlrequest);
+
+			return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				ctrlrequest->bRequest,
+				ctrlrequest->bRequestType, ctrlrequest->wValue,
+				ctrlrequest->wIndex, NULL, ctrlrequest->wLength,
+				2 * HZ);
+		}
+	}
+
+	return 0;
+}
+
 static void xpad_stop_output(struct usb_xpad *xpad)
 {
 	if (xpad->xtype != XTYPE_UNKNOWN) {
@@ -1839,6 +1891,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
 		if (error)
 			goto err_deinit_output;
 	}
+
+	error = xpad_init_control_msg(xpad);
+	if (error)
+		goto err_deinit_output;
+
 	return 0;
 
 err_deinit_output:
-- 
2.17.1



On 3/23/19 12:46 PM, Mike Salvatore wrote:
> From 3051524e62d68b920019bcb50a713e736fcf4234 Mon Sep 17 00:00:00 2001
> From: Mike Salvatore <mike.salvatore@canonical.com>
> Date: Wed, 13 Mar 2019 22:11:37 -0400
> Subject: [PATCH] Input: xpad - send control init message to certain Xbox
>  controllers
> 
> The Xbox controller with idVendor == 0x045e and idProduct == 0x028e
> requires that a specific control transfer be sent from the host to the
> device before the device will send data to the host.
> 
> This patch introduces an xboxone_control_packet struct and a mechanism
> for sending control packets to devices that require them at
> initialization.
> 
> Signed-off-by: Mike Salvatore <mike.salvatore@canonical.com>
> ---
>  drivers/input/joystick/xpad.c | 56 +++++++++++++++++++++++++++++++++++
>  1 file changed, 56 insertions(+)
> 
> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
> index cfc8b94527b9..f45522b9ff1f 100644
> --- a/drivers/input/joystick/xpad.c
> +++ b/drivers/input/joystick/xpad.c
> @@ -460,6 +460,25 @@ struct xboxone_init_packet {
>  		.len		= ARRAY_SIZE(_data),	\
>  	}
>  
> +struct xboxone_control_packet {
> +	u16 idVendor;
> +	u16 idProduct;
> +	struct usb_ctrlrequest ctrlrequest;
> +};
> +
> +#define XBOXONE_CONTROL_PKT(_vid, _pid, _reqtype, _req, _value, _index, _len)  \
> +	{						\
> +		.idVendor	= (_vid),		\
> +		.idProduct	= (_pid),		\
> +		.ctrlrequest    = {			\
> +			.bRequestType	= (_reqtype),	\
> +			.bRequest	= (_req),	\
> +			.wValue		= (_value),	\
> +			.wIndex		= (_index),	\
> +			.wLength	= (_len),	\
> +		},					\
> +	}
> +
>  
>  /*
>   * This packet is required for all Xbox One pads with 2015
> @@ -537,6 +556,13 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
>  	XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init),
>  };
>  
> +static const struct xboxone_control_packet xboxone_control_packets[] = {
> +	XBOXONE_CONTROL_PKT(0x045e, 0x028e,
> +			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
> +			USB_REQ_CLEAR_FEATURE,
> +			USB_DEVICE_REMOTE_WAKEUP, 0, 0),
> +};
> +
>  struct xpad_output_packet {
>  	u8 data[XPAD_PKT_LEN];
>  	u8 len;
> @@ -1119,6 +1145,31 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
>  	return error;
>  }
>  
> +static int xpad_init_control_msg(struct usb_xpad *xpad)
> +{
> +	struct usb_device *udev = xpad->udev;
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(xboxone_control_packets); i++) {
> +		u16 idVendor = xboxone_control_packets[i].idVendor;
> +		u16 idProduct = xboxone_control_packets[i].idProduct;
> +
> +		if (le16_to_cpu(udev->descriptor.idVendor) == idVendor
> +		    && le16_to_cpu(udev->descriptor.idProduct) == idProduct) {
> +			const struct usb_ctrlrequest *ctrlrequest =
> +				&(xboxone_control_packets[i].ctrlrequest);
> +
> +			return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
> +				ctrlrequest->bRequest,
> +				ctrlrequest->bRequestType, ctrlrequest->wValue,
> +				ctrlrequest->wIndex, NULL, ctrlrequest->wLength,
> +				2 * HZ);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static void xpad_stop_output(struct usb_xpad *xpad)
>  {
>  	if (xpad->xtype != XTYPE_UNKNOWN) {
> @@ -1839,6 +1890,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
>  		if (error)
>  			goto err_deinit_output;
>  	}
> +
> +	error = xpad_init_control_msg(xpad);
> +	if (error)
> +		goto err_deinit_output;
> +
>  	return 0;
>  
>  err_deinit_output:
> -- 2.17.1


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2019-04-16 23:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-23 16:46 [PATCH] xpad.c: Send necessary control transfer to certain Xbox controllers Mike Salvatore
2019-04-16 23:31 ` Mike Salvatore

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).