From: Aaron Ma <mapengyu@gmail.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
linux-input@vger.kernel.org (open list:INPUT (KEYBOARD, MOUSE,
JOYSTICK, TOUCHSCREEN)...),
linux-kernel@vger.kernel.org
Cc: Sanjay Govind <sanjay.govind9@gmail.com>,
Vicki Pfau <vi@endrift.com>, Shengyu Qu <wiagn233@outlook.com>,
Aaron Ma <mapengyu@gmail.com>, Qbeliw Tanaka <q.tanaka@gmx.com>,
Elliot Tester <elliotctester@gmail.com>,
Kees Cook <kees@kernel.org>, Dmitriy Zharov <contact@zharov.dev>
Subject: [PATCH 2/2] Input: xpad - add wired Beitong BTP-KP20D support
Date: Sat, 25 Jul 2026 15:28:13 +0800 [thread overview]
Message-ID: <20260725072813.339112-2-mapengyu@gmail.com> (raw)
In-Reply-To: <20260725072813.339112-1-mapengyu@gmail.com>
The wired BTP-KP20D resets itself when its interrupt-IN pipe is idle
for a few seconds, causing periodic re-enumeration whenever no
userspace client holds the input device open. Add a FLAG_KEEPALIVE
quirk that keeps the input URB running from probe to disconnect,
mirroring the XTYPE_XBOX360W URB lifecycle.
The device also needs the MS OS descriptor query to stay in Xbox 360
mode.
Signed-off-by: Aaron Ma <mapengyu@gmail.com>
---
drivers/input/joystick/xpad.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 1616047e65f5e..5369b880c6a08 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -73,6 +73,7 @@
#define FLAG_DELAY_INIT BIT(0)
#define FLAG_MS_OS_DESC BIT(1)
+#define FLAG_KEEPALIVE BIT(2)
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -335,6 +336,7 @@ static const struct xpad_device {
{ 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 },
{ 0x20bc, 0x5134, "BETOP BTP-KP50B Xinput Dongle", 0, XTYPE_XBOX360 },
{ 0x20bc, 0x514a, "BETOP BTP-KP50C Xinput Dongle", 0, XTYPE_XBOX360 },
+ { 0x20bc, 0x5158, "Beitong BTP-KP20D Controller", 0, XTYPE_XBOX360, FLAG_MS_OS_DESC | FLAG_KEEPALIVE },
{ 0x20bc, 0x5159, "Beitong BTP-KP20D Controller", 0, XTYPE_XBOX360, FLAG_MS_OS_DESC },
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
@@ -780,6 +782,7 @@ struct usb_xpad {
time64_t mode_btn_down_ts;
bool delay_init; /* init packets should be delayed */
bool delayed_init_done;
+ bool keepalive; /* int URB must run from probe to disconnect */
};
static int xpad_init_input(struct usb_xpad *xpad);
@@ -1971,7 +1974,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->keepalive) {
input_dev->open = xpad_open;
input_dev->close = xpad_close;
}
@@ -2105,6 +2108,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->name = xpad_device[i].name;
if (xpad_device[i].flags & FLAG_DELAY_INIT)
xpad->delay_init = true;
+ if (xpad_device[i].flags & FLAG_KEEPALIVE)
+ xpad->keepalive = true;
xpad->packet_type = PKT_XB;
INIT_WORK(&xpad->work, xpad_presence_work);
@@ -2227,9 +2232,22 @@ 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;
+
+ if (xpad->keepalive) {
+ /*
+ * The device resets itself when the interrupt-IN pipe
+ * is idle for a few seconds, so keep the URB running
+ * from probe until disconnect.
+ */
+ 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:
@@ -2247,6 +2265,8 @@ static void xpad_disconnect(struct usb_interface *intf)
if (xpad->xtype == XTYPE_XBOX360W)
xpad360w_stop_input(xpad);
+ else if (xpad->keepalive)
+ xpad_stop_input(xpad);
xpad_deinit_input(xpad);
@@ -2288,6 +2308,8 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
*/
if (auto_poweroff && xpad->pad_present)
xpad360w_poweroff_controller(xpad);
+ } else if (xpad->keepalive) {
+ xpad_stop_input(xpad);
} else {
guard(mutex)(&input->mutex);
@@ -2309,6 +2331,9 @@ static int xpad_resume(struct usb_interface *intf)
if (xpad->xtype == XTYPE_XBOX360W)
return xpad360w_start_input(xpad);
+ if (xpad->keepalive)
+ return xpad_start_input(xpad);
+
guard(mutex)(&input->mutex);
if (input_device_enabled(input))
--
2.53.0
next prev parent reply other threads:[~2026-07-25 7:32 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-25 7:28 [PATCH 1/2] Input: xpad - query MS OS descriptor for BTP-KP20D Aaron Ma
2026-07-25 7:28 ` Aaron Ma [this message]
2026-07-25 7:48 ` [PATCH 2/2] Input: xpad - add wired Beitong BTP-KP20D support sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260725072813.339112-2-mapengyu@gmail.com \
--to=mapengyu@gmail.com \
--cc=contact@zharov.dev \
--cc=dmitry.torokhov@gmail.com \
--cc=elliotctester@gmail.com \
--cc=kees@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=q.tanaka@gmx.com \
--cc=sanjay.govind9@gmail.com \
--cc=vi@endrift.com \
--cc=wiagn233@outlook.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox