Re: [PATCH] xpad.c: Send necessary control transfer to certain Xbox controllers

From: Mike Salvatore
Date: Tue Apr 16 2019 - 19:32:01 EST


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@xxxxxxxxxxxxx>
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@xxxxxxxxxxxxx>
---
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@xxxxxxxxxxxxx>
> 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@xxxxxxxxxxxxx>
> ---
> 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: signature.asc
Description: OpenPGP digital signature