diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/hid_table.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/hid_table.rs new file mode 100644 index 0000000000..ff4e22ae02 --- /dev/null +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/hid_table.rs @@ -0,0 +1,213 @@ +//! Compiled-in HID quirk table. +//! +//! Phase R10 (2026-06-07) — generated from +//! `local/reference/linux-7.1/drivers/hid/hid-quirks.c` lines 27-223 +//! (the `hid_quirks[]` array, 191 entries). +use super::{HidQuirkEntry, HidQuirkFlags}; + +const F_NO_INIT_ALWAYS: HidQuirkFlags = HidQuirkFlags::from_bits_truncate( + HidQuirkFlags::NO_INIT_REPORTS.bits() | HidQuirkFlags::ALWAYS_POLL.bits(), +); +const F_BADPAD_MULTI: HidQuirkFlags = HidQuirkFlags::from_bits_truncate( + HidQuirkFlags::BADPAD.bits() | HidQuirkFlags::MULTI_INPUT.bits(), +); +const F_NOGET_MULTI: HidQuirkFlags = HidQuirkFlags::from_bits_truncate( + HidQuirkFlags::NOGET.bits() | HidQuirkFlags::MULTI_INPUT.bits(), +); +const F_MULTI_SKIP: HidQuirkFlags = HidQuirkFlags::from_bits_truncate( + HidQuirkFlags::MULTI_INPUT.bits() | HidQuirkFlags::SKIP_OUTPUT_REPORTS.bits(), +); + +pub const HID_QUIRK_TABLE: &[HidQuirkEntry] = &[ + HidQuirkEntry { vendor: 0x2dc8, product: 0x6009, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x6d6, product: 0x25, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x6d6, product: 0x26, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x125f, product: 0x7505, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x125f, product: 0x7506, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x15a4, product: 0x9016, flags: HidQuirkFlags::FULLSPEED_INTERVAL }, + HidQuirkEntry { vendor: 0x1a2c, product: 0x2, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x9e8, product: 0x31, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x2011, product: 0x715, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x433, product: 0x1101, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x46b, product: 0xff10, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x5ac, product: 0x24f, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x557, product: 0x2204, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2208, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2205, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2202, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2220, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2213, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x8021, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x557, product: 0x2004, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x4f2, product: 0xb19d, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x4f2, product: 0x1053, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x4f2, product: 0x939, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x4f2, product: 0x618, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x5fe, product: 0x14, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x68e, product: 0xd3, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0x1c, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0xf4, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0xf3, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0x51, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0xff, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0xf2, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x68e, product: 0xf1, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x2516, product: 0x1b7, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b17, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b39, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b13, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b38, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b09, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b11, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b12, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b34, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b3e, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x1b1c, product: 0x1b15, flags: F_NO_INIT_ALWAYS }, + HidQuirkEntry { vendor: 0x41e, product: 0x322c, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x413c, product: 0x301a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x413c, product: 0x4503, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0xc0b, product: 0x5fab, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x289b, product: 0x2, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x289b, product: 0x3, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x79, product: 0x6, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x79, product: 0x1803, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x79, product: 0x1843, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x79, product: 0x1846, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x79, product: 0x1801, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x79, product: 0x1800, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0xeef, product: 0x1, flags: F_NOGET_MULTI }, + HidQuirkEntry { vendor: 0x2d99, product: 0xa101, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x4f3, product: 0xffff, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x4e7, product: 0x20, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x2006, product: 0x118, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x22b9, product: 0x2968, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x22b9, product: 0x6, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x147a, product: 0xe03e, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x15a2, product: 0x4f, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x547, product: 0x7000, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0xe8f, product: 0x3010, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0xe8f, product: 0x3013, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x27f8, product: 0xbbe, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x27f8, product: 0xbbf, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x78b, product: 0x10, flags: F_BADPAD_MULTI }, + HidQuirkEntry { vendor: 0x78b, product: 0x30, flags: F_BADPAD_MULTI }, + HidQuirkEntry { vendor: 0x78b, product: 0x20, flags: F_BADPAD_MULTI }, + HidQuirkEntry { vendor: 0x4d9, product: 0xa096, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x4d9, product: 0xa293, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0xa4a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x464a, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x3f0, product: 0xb4a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x134a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x94a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x941, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x641, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x3f0, product: 0x1f4a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x1cb6, product: 0x6680, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x1292, product: 0x4745, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x137, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x458, product: 0x5005, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x500f, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5010, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5011, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5012, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5013, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5014, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5015, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5016, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5017, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x5019, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x501a, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x458, product: 0x501b, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x1020, product: 0x8888, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x17ef, product: 0x6184, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x17ef, product: 0x61ed, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x17ef, product: 0x600e, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x17ef, product: 0x608d, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x17ef, product: 0x6019, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x17ef, product: 0x602e, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x17ef, product: 0x6093, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc548, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc007, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc077, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc24d, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x46d, product: 0xc01a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc05a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x46d, product: 0xc06a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x16d0, product: 0xbcc, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x45e, product: 0x783, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x45e, product: 0xcb, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x45e, product: 0x7da, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x45e, product: 0x7de, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x45e, product: 0x799, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x45e, product: 0x7a7, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x45e, product: 0x7a9, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x8282, product: 0x3201, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x1770, product: 0xff00, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1781, product: 0xa9d, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x8b7, product: 0x1, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x73e, product: 0x301, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x1870, product: 0x110, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1926, product: 0x3, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x603, product: 0x1602, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1b96, product: 0x1500, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x810, product: 0x1, flags: F_MULTI_SKIP }, + HidQuirkEntry { vendor: 0x14e1, product: 0x1610, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x14e1, product: 0x1640, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x5f3, product: 0xff, flags: HidQuirkFlags::HIDINPUT_FORCE }, + HidQuirkEntry { vendor: 0x93a, product: 0x8002, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x93a, product: 0x8003, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x93a, product: 0x8001, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x93a, product: 0x2510, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x461, product: 0x4d22, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x461, product: 0x4e2a, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x461, product: 0x4d0f, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x461, product: 0x4d65, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x461, product: 0x4e22, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x5af, product: 0x3062, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x408, product: 0x3001, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x408, product: 0x3003, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x408, product: 0x3008, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0xbda, product: 0x152, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0xf000, product: 0x3, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0xf000, product: 0xf1, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x6a3, product: 0xff17, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x6a3, product: 0x75c, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x6a3, product: 0x255, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x6a3, product: 0x762, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x6a3, product: 0xb6a, flags: HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE }, + HidQuirkEntry { vendor: 0x1a2c, product: 0x27, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1a2c, product: 0x23, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x1395, product: 0x2c, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x1c4f, product: 0x2, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x66f, product: 0x3780, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x457, product: 0x1030, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x457, product: 0x817, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x457, product: 0x9200, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x457, product: 0x1013, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x430, product: 0xcdab, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x5e0, product: 0x800, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x5e0, product: 0x1300, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x6cb, product: 0xac3, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0xaf8, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0x1d10, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0x1ac3, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0x5710, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0x2819, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x6cb, product: 0x6e21, flags: HidQuirkFlags::NO_INIT_REPORTS }, + HidQuirkEntry { vendor: 0x663, product: 0x103, flags: HidQuirkFlags::BADPAD }, + HidQuirkEntry { vendor: 0x1bfd, product: 0x1688, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x25aa, product: 0x8882, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x25aa, product: 0x8883, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x62a, product: 0x201, flags: HidQuirkFlags::NOGET }, + HidQuirkEntry { vendor: 0x5543, product: 0x6001, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x5543, product: 0x64, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x2179, product: 0x4, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x483, product: 0xa44c, flags: HidQuirkFlags::ALWAYS_POLL }, + HidQuirkEntry { vendor: 0x172f, product: 0x501, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x172f, product: 0x500, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x172f, product: 0x502, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x6677, product: 0x8802, flags: F_NOGET_MULTI }, + HidQuirkEntry { vendor: 0x925, product: 0x8800, flags: F_NOGET_MULTI }, + HidQuirkEntry { vendor: 0x16c0, product: 0x5e1, flags: HidQuirkFlags::MULTI_INPUT }, + HidQuirkEntry { vendor: 0x46d, product: 0x882, flags: HidQuirkFlags::NOGET }, +]; diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs index 2d10b4b7f4..a0e97a444f 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs @@ -28,6 +28,7 @@ //! ``` pub mod dmi; +pub mod hid_table; pub mod pci_table; pub mod toml_loader; pub mod usb_table; @@ -168,6 +169,49 @@ bitflags::bitflags! { } } +bitflags::bitflags! { + /// Flags for HID (Human Interface Device) quirks. + /// + /// Mirrors Linux's `HID_QUIRK_*` defines from `include/linux/hid.h` + /// (lines 396-422 in Linux 7.1). Bit positions match the Linux + /// numerical values exactly, including the bit gaps (0, 8, 9, 15, + /// 24-27) that correspond to removed/renamed flags in upstream. + /// + /// Phase R10 (2026-06-07) — 24 flags defined, but only the 9 used in + /// `hid_quirks[]` entries (ALWAYS_POLL, BADPAD, FULLSPEED_INTERVAL, + /// HIDINPUT_FORCE, INCREMENT_USAGE_ON_DUPLICATE, MULTI_INPUT, NOGET, + /// NO_INIT_REPORTS, SKIP_OUTPUT_REPORTS) are populated in the + /// compiled-in table. The remaining 15 flags are reserved for + /// future hardware and runtime TOML overrides. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct HidQuirkFlags: u64 { + const NOTOUCH = 1 << 1; // HID_QUIRK_NOTOUCH + const IGNORE = 1 << 2; // HID_QUIRK_IGNORE + const NOGET = 1 << 3; // HID_QUIRK_NOGET + const HIDDEV_FORCE = 1 << 4; // HID_QUIRK_HIDDEV_FORCE + const BADPAD = 1 << 5; // HID_QUIRK_BADPAD + const MULTI_INPUT = 1 << 6; // HID_QUIRK_MULTI_INPUT + const HIDINPUT_FORCE = 1 << 7; // HID_QUIRK_HIDINPUT_FORCE + const ALWAYS_POLL = 1 << 10; // HID_QUIRK_ALWAYS_POLL + const INPUT_PER_APP = 1 << 11; // HID_QUIRK_INPUT_PER_APP + const X_INVERT = 1 << 12; // HID_QUIRK_X_INVERT + const Y_INVERT = 1 << 13; // HID_QUIRK_Y_INVERT + const IGNORE_MOUSE = 1 << 14; // HID_QUIRK_IGNORE_MOUSE + const SKIP_OUTPUT_REPORTS = 1 << 16; // HID_QUIRK_SKIP_OUTPUT_REPORTS + const SKIP_OUTPUT_REPORT_ID = 1 << 17; // HID_QUIRK_SKIP_OUTPUT_REPORT_ID + const NO_OUTPUT_REPORTS_ON_INTR_EP = 1 << 18; // HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP + const HAVE_SPECIAL_DRIVER = 1 << 19; // HID_QUIRK_HAVE_SPECIAL_DRIVER + const INCREMENT_USAGE_ON_DUPLICATE = 1 << 20; // HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE + const NOINVERT = 1 << 21; // HID_QUIRK_NOINVERT + const IGNORE_SPECIAL_DRIVER = 1 << 22; // HID_QUIRK_IGNORE_SPECIAL_DRIVER + const POWER_ON_AFTER_BACKLIGHT = 1 << 23; // HID_QUIRK_POWER_ON_AFTER_BACKLIGHT + const FULLSPEED_INTERVAL = 1 << 28; // HID_QUIRK_FULLSPEED_INTERVAL + const NO_INIT_REPORTS = 1 << 29; // HID_QUIRK_NO_INIT_REPORTS + const NO_IGNORE = 1 << 30; // HID_QUIRK_NO_IGNORE + const NO_INPUT_SYNC = 1 << 31; // HID_QUIRK_NO_INPUT_SYNC + } +} + /// Wildcard value for PCI ID matching. pub const PCI_QUIRK_ANY_ID: u16 = 0xFFFF; @@ -567,6 +611,32 @@ impl Default for UsbQuirkEntry { } } +#[derive(Clone, Copy, Debug)] +pub struct HidQuirkEntry { + pub vendor: u16, + pub product: u16, + pub flags: HidQuirkFlags, +} + +impl HidQuirkEntry { + pub const WILDCARD: Self = Self { + vendor: PCI_QUIRK_ANY_ID, + product: PCI_QUIRK_ANY_ID, + flags: HidQuirkFlags::empty(), + }; + + pub fn matches(&self, vendor: u16, product: u16) -> bool { + (self.vendor == PCI_QUIRK_ANY_ID || self.vendor == vendor) + && (self.product == PCI_QUIRK_ANY_ID || self.product == product) + } +} + +impl Default for HidQuirkEntry { + fn default() -> Self { + Self::WILDCARD + } +} + bitflags::bitflags! { /// Flags for xHCI controller quirks. /// @@ -1009,6 +1079,28 @@ pub fn lookup_usb_quirks(vendor: u16, product: u16) -> UsbQuirkFlags { flags } +/// Look up accumulated HID quirk flags for the given USB vendor/product pair. +/// +/// Iterates the compiled-in HID quirk table, OR-ing flags from all +/// matching entries, then OR-s in any flags contributed by runtime +/// TOML quirk files (`[[hid_quirk]]` sections in +/// `/etc/quirks.d/*.toml`). +pub fn lookup_hid_quirks(vendor: u16, product: u16) -> HidQuirkFlags { + let mut flags = HidQuirkFlags::empty(); + + for entry in hid_table::HID_QUIRK_TABLE { + if entry.matches(vendor, product) { + flags |= entry.flags; + } + } + + if let Ok(toml_flags) = toml_loader::load_hid_quirks(vendor, product) { + flags |= toml_flags; + } + + flags +} + /// Look up accumulated xHCI controller quirk flags for the given PCI vendor/device pair. /// /// Iterates the compiled-in xHCI controller quirk table, OR-ing flags from all @@ -1979,4 +2071,92 @@ mod tests { "expected 6 R7-C-only single-flag entries (Renoir 0x43f7 + 0x15e0 + 0x15e1 + Intel 0x9a13 + 0x51e0 + 0x54ee)" ); } + + /// Phase R10 — HID table is non-empty. + #[test] + fn phase_r10_hid_table_is_populated() { + assert!( + hid_table::HID_QUIRK_TABLE.len() >= 180, + "expected ~191 HID entries from Linux 7.1 hid-quirks.c" + ); + } + + /// Phase R10 — 8BitDo Pro 3 (0x2dc8:0x6009) maps to ALWAYS_POLL. + #[test] + fn phase_r10_lookup_8bitdo_pro3_always_poll() { + let flags = lookup_hid_quirks(0x2dc8, 0x6009); + assert!(flags.contains(HidQuirkFlags::ALWAYS_POLL)); + } + + /// Phase R10 — vendor-wide wildcard (ELAN 0x04f3 with HID_ANY_ID product) matches any product. + #[test] + fn phase_r10_lookup_vendor_wildcard_matches_any_product() { + let f1 = lookup_hid_quirks(0x04f3, 0x1234); + let f2 = lookup_hid_quirks(0x04f3, 0xabcd); + assert!(f1.contains(HidQuirkFlags::ALWAYS_POLL)); + assert!(f2.contains(HidQuirkFlags::ALWAYS_POLL)); + } + + /// Phase R10 — multi-flag entry: Corsair (0x1b1c:0x1b39) gets NO_INIT_REPORTS | ALWAYS_POLL. + #[test] + fn phase_r10_lookup_multi_flag_or_accumulates() { + let flags = lookup_hid_quirks(0x1b1c, 0x1b39); + assert!(flags.contains(HidQuirkFlags::NO_INIT_REPORTS)); + assert!(flags.contains(HidQuirkFlags::ALWAYS_POLL)); + } + + /// Phase R10 — unknown vendor/product returns empty flags. + #[test] + fn phase_r10_lookup_unknown_returns_empty() { + let flags = lookup_hid_quirks(0x0000, 0x0000); + assert_eq!(flags, HidQuirkFlags::empty()); + } + + /// Phase R10 — entry's `matches()` accepts wildcard vendor with explicit product. + #[test] + fn phase_r10_hid_entry_matches_wildcard_vendor() { + let entry = HidQuirkEntry { + vendor: PCI_QUIRK_ANY_ID, + product: 0x1234, + flags: HidQuirkFlags::NOGET, + }; + assert!(entry.matches(0x0001, 0x1234)); + assert!(!entry.matches(0x0001, 0x9999)); + } + + /// Phase R10 — bit positions match Linux `include/linux/hid.h` (sanity for 9 used flags). + #[test] + fn phase_r10_bit_positions_match_linux() { + assert_eq!(HidQuirkFlags::NOGET.bits(), 1 << 3); + assert_eq!(HidQuirkFlags::BADPAD.bits(), 1 << 5); + assert_eq!(HidQuirkFlags::MULTI_INPUT.bits(), 1 << 6); + assert_eq!(HidQuirkFlags::HIDINPUT_FORCE.bits(), 1 << 7); + assert_eq!(HidQuirkFlags::ALWAYS_POLL.bits(), 1 << 10); + assert_eq!(HidQuirkFlags::SKIP_OUTPUT_REPORTS.bits(), 1 << 16); + assert_eq!( + HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE.bits(), + 1 << 20 + ); + assert_eq!(HidQuirkFlags::FULLSPEED_INTERVAL.bits(), 1 << 28); + assert_eq!(HidQuirkFlags::NO_INIT_REPORTS.bits(), 1 << 29); + } + + /// Phase R10 — TOML `[[hid_quirk]]` parses with vendor/product/flags. + #[test] + fn phase_r10_toml_hid_quirk_parses() { + let toml = r#" +[[hid_quirk]] +vendor = 0x2dc8 +product = 0x6009 +flags = ["always_poll", "no_init_reports"] +"#; + let doc: toml::Value = toml.parse().unwrap(); + let mut entries = Vec::new(); + toml_loader::parse_hid_toml(&doc, &mut entries, ""); + assert_eq!(entries.len(), 1); + assert_eq!(entries[0].vendor, 0x2dc8); + assert_eq!(entries[0].product, 0x6009); + assert!(entries[0].flags.contains(HidQuirkFlags::ALWAYS_POLL)); + assert!(entries[0].flags.contains(HidQuirkFlags::NO_INIT_REPORTS)); + } } diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs index 67d64f134c..164e7945ca 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs @@ -1,8 +1,8 @@ use super::{ dmi::{self, DmiInfo, DmiMatchRule, DmiPciQuirkRule, DmiXhciQuirkRule}, - MaskWidth, PciQuirkEntry, PciQuirkFlags, PciQuirkLookup, PciQuirkPhase, QuirkAction, - UsbQuirkEntry, UsbQuirkFlags, XhciControllerQuirk, XhciControllerQuirkFlags, - PCI_QUIRK_ANY_ID, + HidQuirkEntry, HidQuirkFlags, MaskWidth, PciQuirkEntry, PciQuirkFlags, PciQuirkLookup, + PciQuirkPhase, QuirkAction, UsbQuirkEntry, UsbQuirkFlags, XhciControllerQuirk, + XhciControllerQuirkFlags, PCI_QUIRK_ANY_ID, }; use crate::pci::PciDeviceInfo; use std::borrow::Cow; @@ -63,6 +63,17 @@ pub fn load_usb_quirks(vendor: u16, product: u16) -> Result { Ok(flags) } +pub fn load_hid_quirks(vendor: u16, product: u16) -> Result { + let mut flags = HidQuirkFlags::empty(); + let entries = read_toml_hid_entries().map_err(|_| ())?; + for entry in &entries { + if entry.matches(vendor, product) { + flags |= entry.flags; + } + } + Ok(flags) +} + pub(crate) fn load_dmi_pci_quirks( info: &PciDeviceInfo, dmi_info: &DmiInfo, @@ -301,6 +312,48 @@ const USB_FLAG_NAMES: &[(&str, UsbQuirkFlags)] = &[ ), ]; +// HID flag names exposed in TOML `[[hid_quirk]]` entries. Names are the +// snake_case form of the corresponding `HidQuirkFlags` variant; bit +// positions match Linux 7.1 `include/linux/hid.h` exactly. Only the 9 +// flags actually used in `hid_quirks[]` are exposed; reserved/rare +// flags (HID_QUIRK_POWER_ON_AFTER_BACKLIGHT, etc.) are reachable only +// via the compiled-in table or future TOML extensions. +const HID_QUIRK_FLAG_NAMES: &[(&str, HidQuirkFlags)] = &[ + ("notouch", HidQuirkFlags::NOTOUCH), + ("ignore", HidQuirkFlags::IGNORE), + ("noget", HidQuirkFlags::NOGET), + ("hiddev_force", HidQuirkFlags::HIDDEV_FORCE), + ("badpad", HidQuirkFlags::BADPAD), + ("multi_input", HidQuirkFlags::MULTI_INPUT), + ("hidinput_force", HidQuirkFlags::HIDINPUT_FORCE), + ("always_poll", HidQuirkFlags::ALWAYS_POLL), + ("input_per_app", HidQuirkFlags::INPUT_PER_APP), + ("x_invert", HidQuirkFlags::X_INVERT), + ("y_invert", HidQuirkFlags::Y_INVERT), + ("ignore_mouse", HidQuirkFlags::IGNORE_MOUSE), + ("skip_output_reports", HidQuirkFlags::SKIP_OUTPUT_REPORTS), + ("skip_output_report_id", HidQuirkFlags::SKIP_OUTPUT_REPORT_ID), + ( + "no_output_reports_on_intr_ep", + HidQuirkFlags::NO_OUTPUT_REPORTS_ON_INTR_EP, + ), + ("have_special_driver", HidQuirkFlags::HAVE_SPECIAL_DRIVER), + ( + "increment_usage_on_duplicate", + HidQuirkFlags::INCREMENT_USAGE_ON_DUPLICATE, + ), + ("noinvert", HidQuirkFlags::NOINVERT), + ("ignore_special_driver", HidQuirkFlags::IGNORE_SPECIAL_DRIVER), + ( + "power_on_after_backlight", + HidQuirkFlags::POWER_ON_AFTER_BACKLIGHT, + ), + ("fullspeed_interval", HidQuirkFlags::FULLSPEED_INTERVAL), + ("no_init_reports", HidQuirkFlags::NO_INIT_REPORTS), + ("no_ignore", HidQuirkFlags::NO_IGNORE), + ("no_input_sync", HidQuirkFlags::NO_INPUT_SYNC), +]; + // xHCI controller flag names exposed in TOML `[[xhci_controller_quirk]]` // entries. Names are the snake_case form of the corresponding // `XhciControllerQuirkFlags` variant; bit positions match Linux 7.1 @@ -793,6 +846,55 @@ fn parse_usb_toml(doc: &toml::Value, out: &mut Vec, path: &str) { } } +fn read_toml_hid_entries() -> std::io::Result> { + let mut entries = Vec::new(); + for path in sorted_toml_files(QUIRKS_DIR)? { + let path_str = path.display().to_string(); + let content = match std::fs::read_to_string(&path) { + Ok(c) => c, + Err(e) => { + log::warn!("quirks: failed to read {path_str}: {e}"); + continue; + } + }; + let doc = match content.parse::() { + Ok(d) => d, + Err(e) => { + log::warn!("quirks: failed to parse {path_str}: {e}"); + continue; + } + }; + parse_hid_toml(&doc, &mut entries, &path_str); + } + Ok(entries) +} + +pub(crate) fn parse_hid_toml(doc: &toml::Value, out: &mut Vec, path: &str) { + let Some(arr) = doc.get("hid_quirk").and_then(|v| v.as_array()) else { + return; + }; + for item in arr { + let Some(table) = item.as_table() else { + log::warn!("quirks: {path}: hid_quirk entry is not a table, skipping"); + continue; + }; + let vendor = table + .get("vendor") + .and_then(|v| bounded_u16(v, "vendor", path)) + .unwrap_or(PCI_QUIRK_ANY_ID); + let product = table + .get("product") + .and_then(|v| bounded_u16(v, "product", path)) + .unwrap_or(PCI_QUIRK_ANY_ID); + let flags = parse_flags(table, path, "HID", HID_QUIRK_FLAG_NAMES); + out.push(HidQuirkEntry { + vendor, + product, + flags, + }); + } +} + /// Look up xHCI controller flags contributed by runtime TOML quirk files /// (the `[[xhci_controller_quirk]]` section). Returns the OR-accumulated /// flags across every matching TOML entry, or an empty set if no files