[PATCH v3] Input: xpad - add support for Azeron devices
From: Roberts Kursitis
Date: Fri Jun 19 2026 - 10:23:09 EST
Add USB Vendor and Product IDs for the Azeron devices (Cyro, Cyborg,
Classic/Compact, Cyro Lefty, Cyborg II and Keyzen). These devices share
a firmware XInput implementation and expose the standard Xbox 360
interface signature.
Note that 0x16d0 is a shared vendor block (MCS Electronics / pid.codes
allocations), but binding here is safe as the XPAD_XBOX360_VENDOR macro
only binds interfaces presenting the strict Xbox 360 signature.
These devices reject Xbox 360 LED and rumble magic packets with a
stall (-EPIPE). Add FLAG_NO_LED and FLAG_NO_RUMBLE device flags,
set on all Azeron entries, so xpad_led_probe() and xpad_init_ff()
skip LED and force-feedback initialization for them.
Signed-off-by: Roberts Kursitis <roberts.kursitis@xxxxxxxxx>
---
v2 -> v3:
- Move 0x16d0 entries after 0x1689 to keep both tables sorted by
vendor ID
- Move quirks from the mapping field to the flags field; mapping is
u8 and the new bits overflowed it
- Add FLAG_NO_RUMBLE; these devices stall on rumble packets too
drivers/input/joystick/xpad.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index feb8f368f..405fcd5e9 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -72,6 +72,9 @@
#define PKT_XBE2_FW_5_11 4
#define FLAG_DELAY_INIT BIT(0)
+#define FLAG_NO_LED BIT(1)
+#define FLAG_NO_RUMBLE BIT(2)
+#define FLAG_NO_LED_RUMBLE (FLAG_NO_LED | FLAG_NO_RUMBLE)
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -292,6 +295,12 @@ static const struct xpad_device {
{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 },
{ 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 },
{ 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+ { 0x16d0, 0x1103, "Azeron Cyro", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
+ { 0x16d0, 0x113c, "Azeron Cyborg", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
+ { 0x16d0, 0x1192, "Azeron Classic/Compact", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
+ { 0x16d0, 0x1212, "Azeron Cyro Lefty", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
+ { 0x16d0, 0x12f7, "Azeron Cyborg II", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
+ { 0x16d0, 0x13ea, "Azeron Keyzen", 0, XTYPE_XBOX360, FLAG_NO_LED_RUMBLE },
{ 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 },
{ 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 },
{ 0x1a86, 0xe310, "Legion Go S", 0, XTYPE_XBOX360 },
@@ -533,6 +542,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */
XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */
XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
+ XPAD_XBOX360_VENDOR(0x16d0), /* Azeron controllers */
XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */
XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */
XPAD_XBOX360_VENDOR(0x1a86), /* Nanjing Qinheng Microelectronics (WCH) */
@@ -776,6 +786,8 @@ struct usb_xpad {
const char *name; /* name of the device */
struct work_struct work; /* init/remove device from callback */
time64_t mode_btn_down_ts;
+ bool no_led; /* device stalls on LED packets */
+ bool no_rumble; /* device stalls on rumble packets */
bool delay_init; /* init packets should be delayed */
bool delayed_init_done;
};
@@ -1615,6 +1627,9 @@ static int xpad_init_ff(struct usb_xpad *xpad)
if (xpad->xtype == XTYPE_UNKNOWN)
return 0;
+ if (xpad->no_rumble)
+ return 0;
+
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
@@ -1719,6 +1734,9 @@ static int xpad_led_probe(struct usb_xpad *xpad)
struct led_classdev *led_cdev;
int error;
+ if (xpad->no_led)
+ return 0;
+
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W)
return 0;
@@ -2082,6 +2100,10 @@ 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_NO_LED)
+ xpad->no_led = true;
+ if (xpad_device[i].flags & FLAG_NO_RUMBLE)
+ xpad->no_rumble = true;
xpad->packet_type = PKT_XB;
INIT_WORK(&xpad->work, xpad_presence_work);
--
2.43.0