* [PATCH v2] Input: xpad - add support for Beitong KP series controllers
@ 2026-07-26 8:21 VegetablCat
2026-08-15 10:29 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: VegetablCat @ 2026-07-26 8:21 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, vegetablecat
From: vegetablecat <vegetablecat@foxmail.com>
Beitong KP series controllers (0x20bc:*) enumerate as standard
Xbox 360 devices but require a Microsoft OS Extended Compat ID
descriptor read (XUSB10) to lock into XInput mode. Without this
request the controller re-enumerates as a Nintendo Switch device
(057e:2069) after approximately 1.9 seconds and stops reporting
valid input.
Add FLAG_READ_XUSB10 and device table entries for KP20A/D,
KP40A/B/D/F, KP50B/C/D/E, and KP70A. Devices with this flag
trigger a usb_control_msg_recv() during probe to read the XUSB10
descriptor, which is the sole condition required to keep the
controllers in XInput mode.
The flag follows the same pattern as FLAG_DELAY_INIT used for
the ByoWave Proteus Controller.
Additionally, add an optional HID receiver driver for the KP40D
receiver dongle (0x20dd:0x515c) that binds to its HID interface
to prevent hid-generic from interfering. The receiver dongle is
a separate USB device with its own vendor ID (0x20dd), distinct
from the controller (0x20bc). The HID code is guarded with
IS_ENABLED(CONFIG_HID) to avoid build failures when HID is
disabled or built as a module.
Tested on 20bc:5126 (KP20A) and 20bc:515b (KP40D).
Signed-off-by: vegetablecat <vegetablecat@foxmail.com>
---
drivers/input/joystick/xpad.c | 119 +++++++++++++++++++++++++++++++++-
1 file changed, 118 insertions(+), 1 deletion(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index feb8f36..13b6168 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -28,6 +28,7 @@
*/
#include <linux/bits.h>
+#include <linux/hid.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/rcupdate.h>
@@ -72,6 +73,7 @@
#define PKT_XBE2_FW_5_11 4
#define FLAG_DELAY_INIT BIT(0)
+#define FLAG_READ_XUSB10 BIT(1)
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -332,6 +334,32 @@ static const struct xpad_device {
{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
{ 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 },
+ { 0x20bc, 0x5125, "BETOP BTP-KP20A/BTP-KP40A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5126, "BETOP BTP-KP20A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5127, "BETOP BTP-KP20A/BTP-KP40A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5128, "BETOP BTP-KP20A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x512f, "BETOP BTP-KP70A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5130, "BETOP BTP-KP70A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5133, "BETOP BTP-KP50B Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5145, "BETOP BTP-KP40A/BTP-KP40B Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5146, "BETOP BTP-KP40A/BTP-KP40B Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5149, "BETOP BTP-KP50C Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5150, "BETOP BTP-KP50D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5151, "BETOP BTP-KP50D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5152, "BETOP BTP-KP50E Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5153, "BETOP BTP-KP50E Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5154, "BETOP BTP-KP40D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5155, "BETOP BTP-KP40D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5158, "BETOP BTP-KP20D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5159, "BETOP BTP-KP20D Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x515b, "BETOP BTP-KP40D Controller (White)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x515c, "BETOP BTP-KP40D Controller (White)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x515d, "BETOP BTP-KP40F Controller (White)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x515e, "BETOP BTP-KP40F Controller (White)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x515f, "BETOP BTP-KP70A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5160, "BETOP BTP-KP70A Controller", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x5169, "BETOP BTP-KP40F Controller (Black)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
+ { 0x20bc, 0x516a, "BETOP BTP-KP40F Controller (Black)", 0, XTYPE_XBOX360, FLAG_READ_XUSB10 },
{ 0x20bc, 0x5134, "BETOP BTP-KP50B Xinput Dongle", 0, XTYPE_XBOX360 },
{ 0x20bc, 0x514a, "BETOP BTP-KP50C Xinput Dongle", 0, XTYPE_XBOX360 },
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
@@ -778,6 +806,7 @@ struct usb_xpad {
time64_t mode_btn_down_ts;
bool delay_init; /* init packets should be delayed */
bool delayed_init_done;
+ bool read_xusb10; /* read XUSB10 descriptor during probe */
};
static int xpad_init_input(struct usb_xpad *xpad);
@@ -2044,6 +2073,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_xpad *xpad;
struct usb_endpoint_descriptor *ep_irq_in, *ep_irq_out;
+ u8 ms_feature_descriptor[40];
int i, error;
if (intf->cur_altsetting->desc.bNumEndpoints != 2)
@@ -2082,6 +2112,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_READ_XUSB10)
+ xpad->read_xusb10 = true;
xpad->packet_type = PKT_XB;
INIT_WORK(&xpad->work, xpad_presence_work);
@@ -2148,6 +2180,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_set_intfdata(intf, xpad);
+ if (xpad->read_xusb10) {
+ error = usb_control_msg_recv(udev, 0, 0xee,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_DEVICE,
+ 0x0000, 0x0004,
+ ms_feature_descriptor,
+ sizeof(ms_feature_descriptor), 25,
+ GFP_KERNEL);
+ if (error)
+ dev_warn(&intf->dev,
+ "unable to read Microsoft feature descriptor: %d\n",
+ error);
+ }
/* Packet type detection */
if (le16_to_cpu(udev->descriptor.idVendor) == 0x045e) { /* Microsoft controllers */
@@ -2312,7 +2357,79 @@ static struct usb_driver xpad_driver = {
.id_table = xpad_table,
};
-module_usb_driver(xpad_driver);
+#if IS_ENABLED(CONFIG_HID)
+static int xpad_receiver_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int error;
+
+ error = hid_parse(hdev);
+ if (error)
+ return error;
+
+ error = hid_hw_start(hdev, 0);
+ if (error)
+ return error;
+
+ error = hid_hw_open(hdev);
+ if (error) {
+ hid_hw_stop(hdev);
+ return error;
+ }
+
+ return 0;
+}
+
+static void xpad_receiver_remove(struct hid_device *hdev)
+{
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id xpad_receiver_devices[] = {
+ { HID_USB_DEVICE(0x20dd, 0x515c) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, xpad_receiver_devices);
+
+static struct hid_driver xpad_receiver_driver = {
+ .name = "xpad-kp40d-receiver",
+ .id_table = xpad_receiver_devices,
+ .probe = xpad_receiver_probe,
+ .remove = xpad_receiver_remove,
+};
+#endif
+
+static int __init xpad_init(void)
+{
+ int error;
+
+#if IS_ENABLED(CONFIG_HID)
+ error = hid_register_driver(&xpad_receiver_driver);
+ if (error)
+ return error;
+#endif
+
+ error = usb_register(&xpad_driver);
+ if (error) {
+#if IS_ENABLED(CONFIG_HID)
+ hid_unregister_driver(&xpad_receiver_driver);
+#endif
+ return error;
+ }
+
+ return 0;
+}
+
+static void __exit xpad_exit(void)
+{
+ usb_deregister(&xpad_driver);
+#if IS_ENABLED(CONFIG_HID)
+ hid_unregister_driver(&xpad_receiver_driver);
+#endif
+}
+
+module_init(xpad_init);
+module_exit(xpad_exit);
MODULE_AUTHOR("Marko Friedemann <mfr@bmx-chemnitz.de>");
MODULE_DESCRIPTION("Xbox pad driver");
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] Input: xpad - add support for Beitong KP series controllers
2026-07-26 8:21 [PATCH v2] Input: xpad - add support for Beitong KP series controllers VegetablCat
@ 2026-08-15 10:29 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-08-15 10:29 UTC (permalink / raw)
To: VegetablCat, Dmitry Torokhov
Cc: oe-kbuild-all, linux-input, linux-kernel, vegetablecat
Hi VegetablCat,
kernel test robot noticed the following build errors:
[auto build test ERROR on dtor-input/next]
[also build test ERROR on dtor-input/for-linus hid/for-next linus/master v7.2-rc7 next-20260813]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/VegetablCat/Input-xpad-add-support-for-Beitong-KP-series-controllers/20260814-093918
base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
patch link: https://lore.kernel.org/r/tencent_CD9DBF098D1B3BB565A1DD5761C1D34F4805%40qq.com
patch subject: [PATCH v2] Input: xpad - add support for Beitong KP series controllers
config: m68k-randconfig-r071-20260815 (https://download.01.org/0day-ci/archive/20260815/202608151844.kqZOpOOS-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 16.1.0
smatch: v0.5.0-9187-g5189e3fb
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260815/202608151844.kqZOpOOS-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608151844.kqZOpOOS-lkp@intel.com/
All errors (new ones prefixed by >>):
m68k-linux-ld: drivers/input/joystick/xpad.o: in function `xpad_receiver_remove':
>> xpad.c:(.text+0xa): undefined reference to `hid_hw_close'
>> m68k-linux-ld: xpad.c:(.text+0x18): undefined reference to `hid_hw_stop'
m68k-linux-ld: drivers/input/joystick/xpad.o: in function `xpad_receiver_probe':
>> xpad.c:(.text+0x288): undefined reference to `hid_open_report'
>> m68k-linux-ld: xpad.c:(.text+0x29e): undefined reference to `hid_hw_start'
>> m68k-linux-ld: xpad.c:(.text+0x2ae): undefined reference to `hid_hw_open'
m68k-linux-ld: xpad.c:(.text+0x2c2): undefined reference to `hid_hw_stop'
m68k-linux-ld: drivers/input/joystick/xpad.o: in function `xpad_init':
>> xpad.c:(.init.text+0x12): undefined reference to `__hid_register_driver'
>> m68k-linux-ld: xpad.c:(.init.text+0x46): undefined reference to `hid_unregister_driver'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-15 10:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-26 8:21 [PATCH v2] Input: xpad - add support for Beitong KP series controllers VegetablCat
2026-08-15 10:29 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox