All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.