Skip to content

Commit 036ec44

Browse files
endriftdtor
authored andcommitted
Input: xpad - allow delaying init packets
Some Xbox One controllers will only start processing the init packets after sending the GIP announce packet. While most controllers send this packet immediately, others will delay for some time, e.g. if a dongle needs to connect to an actual controller first. In those cases, we want to delay until we receive the announce packet before sending the init sequence. Signed-off-by: Vicki Pfau <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent d51b9d8 commit 036ec44

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

drivers/input/joystick/xpad.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
#define PKT_XBE2_FW_5_EARLY 3
106106
#define PKT_XBE2_FW_5_11 4
107107

108+
#define FLAG_DELAY_INIT BIT(0)
109+
108110
static bool dpad_to_buttons;
109111
module_param(dpad_to_buttons, bool, S_IRUGO);
110112
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -127,6 +129,7 @@ static const struct xpad_device {
127129
char *name;
128130
u8 mapping;
129131
u8 xtype;
132+
u8 flags;
130133
} xpad_device[] = {
131134
/* Please keep this list sorted by vendor and product ID. */
132135
{ 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
@@ -596,6 +599,7 @@ struct xboxone_init_packet {
596599
* - https://github.com/medusalix/xone/blob/master/bus/protocol.c
597600
*/
598601
#define GIP_CMD_ACK 0x01
602+
#define GIP_CMD_ANNOUNCE 0x02
599603
#define GIP_CMD_IDENTIFY 0x04
600604
#define GIP_CMD_POWER 0x05
601605
#define GIP_CMD_AUTHENTICATE 0x06
@@ -785,10 +789,13 @@ struct usb_xpad {
785789
const char *name; /* name of the device */
786790
struct work_struct work; /* init/remove device from callback */
787791
time64_t mode_btn_down_ts;
792+
bool delay_init; /* init packets should be delayed */
793+
bool delayed_init_done;
788794
};
789795

790796
static int xpad_init_input(struct usb_xpad *xpad);
791797
static void xpad_deinit_input(struct usb_xpad *xpad);
798+
static int xpad_start_input(struct usb_xpad *xpad);
792799
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
793800
static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
794801

@@ -1073,6 +1080,17 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
10731080

10741081
do_sync = true;
10751082
}
1083+
} else if (data[0] == GIP_CMD_ANNOUNCE) {
1084+
int error;
1085+
1086+
if (xpad->delay_init && !xpad->delayed_init_done) {
1087+
xpad->delayed_init_done = true;
1088+
error = xpad_start_input(xpad);
1089+
if (error)
1090+
dev_warn(&xpad->dev->dev,
1091+
"unable to start delayed input: %d\n",
1092+
error);
1093+
}
10761094
} else if (data[0] == GIP_CMD_INPUT) { /* The main valid packet type for inputs */
10771095
/* menu/view buttons */
10781096
input_report_key(dev, BTN_START, data[4] & BIT(2));
@@ -1251,6 +1269,14 @@ static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad)
12511269
if (xpad->xtype != XTYPE_XBOXONE)
12521270
return false;
12531271

1272+
/*
1273+
* Some dongles will discard init packets if they're sent before the
1274+
* controller connects. In these cases, we need to wait until we get
1275+
* an announce packet from them to send the init packet sequence.
1276+
*/
1277+
if (xpad->delay_init && !xpad->delayed_init_done)
1278+
return false;
1279+
12541280
/* Perform initialization sequence for Xbox One pads that require it */
12551281
while (xpad->init_seq < ARRAY_SIZE(xboxone_init_packets)) {
12561282
init_packet = &xboxone_init_packets[xpad->init_seq++];
@@ -2066,6 +2092,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
20662092
xpad->mapping = xpad_device[i].mapping;
20672093
xpad->xtype = xpad_device[i].xtype;
20682094
xpad->name = xpad_device[i].name;
2095+
if (xpad_device[i].flags & FLAG_DELAY_INIT)
2096+
xpad->delay_init = true;
2097+
20692098
xpad->packet_type = PKT_XB;
20702099
INIT_WORK(&xpad->work, xpad_presence_work);
20712100

@@ -2265,6 +2294,7 @@ static int xpad_resume(struct usb_interface *intf)
22652294
struct usb_xpad *xpad = usb_get_intfdata(intf);
22662295
struct input_dev *input = xpad->dev;
22672296

2297+
xpad->delayed_init_done = false;
22682298
if (xpad->xtype == XTYPE_XBOX360W)
22692299
return xpad360w_start_input(xpad);
22702300

0 commit comments

Comments
 (0)