quirks: R18+R19+R20 — storage, network, USB audio infrastructure + data
R18 (storage controller): 25-entry data file aggregating
libata (18) + AHCI (3) + PIIX (2) + NVMe (2) quirks.
Uses the existing [[pci_quirk]] table type with
no_msi, no_msix, rom_bar_overlap flags.
R19 (network controller): 23-entry data file covering
RTL8xxx wireless (12: 8192S/C/D, 8723A, 8812, 8172,
8178, 8179, 817C, B723, 8821, B822) + Broadcom TIGON3
(6: 5700-5705) + RTL8169 family (5: 8168, 8169, 8105,
8125, RTL8168). Uses [[pci_quirk]] with no_msi /
force_legacy_irq flags.
R20 (USB audio): UsbAudioQuirkFlags (29 bits matching
Linux 7.1 snd_usb_audio_quirk_flag_names[]) +
UsbAudioQuirkEntry + load_usb_audio_flags() +
30-entry data file in 60-usb-audio.toml covering
the Logitech QuickCam + HD Webcam family, Microsoft
LifeChat / USB Link, HP 320 FHD, Creative Extigy /
Live Cam, and AB13X/AB17X USB audio codecs. The
remaining ~144 Linux entries are mechanical copies
that can land in follow-up commits.
Changes:
1. (R18) 25 entries in 35-storage-extended.toml
sourced from Linux 7.1 drivers/ata/{libata-core,
ahci,ata_piix}.c + drivers/nvme/host/pci.c. Covers
JMicro (0x197B), ServerWorks CSB5, ATI IXP/SBX00,
AMD Hudson2/Bolton, Intel 82801CAM, Nvidia ION,
Marvell 88SE6121/9235, Intel PIIX (ICH3/ICH4), and
Samsung / Toshiba NVMe.
2. (R19) 23 entries in 55-network.toml sourced from
Linux 7.1 drivers/net/wireless/realtek/rtl8xxxu +
drivers/net/ethernet/broadcom/tg3 + drivers/net/
ethernet/realtek/r8169_main. Covers the tabular
subset of network quirks; the algorithmic subset
(e1000e, igb, ixgbe, iwlwifi) is documented in
QUIRKS-SYSTEM.md as deferred.
3. (R20) UsbAudioQuirkFlags (mod.rs:548) with 29 bits
mapping Linux 7.1 snd_usb_audio_quirk_flag_names.
UsbAudioQuirkEntry (mod.rs:583) — vendor + product
+ flags.
USB_AUDIO_FLAG_NAMES + parse_usb_audio_toml +
load_usb_audio_flags (toml_loader.rs) — new
[[usb_audio_quirk]] TOML table type.
1 new unit test: phase_r20_usb_audio_quirk_flags_or_accumulates.
128/128 tests pass.
4. (R20) 30 entries in 60-usb-audio.toml covering
Logitech webcam / ConferenceCam / headset family,
Microsoft LifeChat LX-3000, Microsoft USB Link
headset, HP 320 FHD Webcam, Creative SB Extigy,
Creative Live Cam, AB13X / AB17X USB Audio.
cargo test: 128/128 (was 127, +1 for the new test).
cargo check: clean.
Consumers (R18/R19/R20) are kernel-side:
- nvmed, ahcid, usbscsid for R18
- e1000d, r8169d, virtio-netd for R19
- usb-audio driver for R20
Each reads the existing lookup_pci_quirks /
lookup_usb_quirks / new load_usb_audio_flags at
driver init time.
This commit is contained in:
@@ -1027,4 +1027,17 @@ mod tests {
|
|||||||
// Different class base
|
// Different class base
|
||||||
assert!(!amd_k8.matches(0x1022, 0x1100, 0x0300));
|
assert!(!amd_k8.matches(0x1022, 0x1100, 0x0300));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Phase R20 — `UsbAudioQuirkFlags` OR-accumulation.
|
||||||
|
#[test]
|
||||||
|
fn phase_r20_usb_audio_quirk_flags_or_accumulates() {
|
||||||
|
use super::super::UsbAudioQuirkFlags;
|
||||||
|
let flags = UsbAudioQuirkFlags::GET_SAMPLE_RATE
|
||||||
|
| UsbAudioQuirkFlags::CTL_MSG_DELAY_1M
|
||||||
|
| UsbAudioQuirkFlags::DSD_RAW;
|
||||||
|
assert!(flags.contains(UsbAudioQuirkFlags::GET_SAMPLE_RATE));
|
||||||
|
assert!(flags.contains(UsbAudioQuirkFlags::CTL_MSG_DELAY_1M));
|
||||||
|
assert!(flags.contains(UsbAudioQuirkFlags::DSD_RAW));
|
||||||
|
assert!(!flags.contains(UsbAudioQuirkFlags::FORCE_IFACE_RESET));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -557,6 +557,54 @@ impl ChipsetQuirkEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
/// USB Audio codec quirk flags. Phase R20 (2026-06-07) —
|
||||||
|
/// ported from Linux 7.1 `sound/usb/quirks.c`
|
||||||
|
/// `quirk_flags_table[]` (174 entries) +
|
||||||
|
/// `snd_usb_audio_quirk_flag_names[]` (28 names).
|
||||||
|
/// Bit positions match Linux 0-27.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct UsbAudioQuirkFlags: u64 {
|
||||||
|
const GET_SAMPLE_RATE = 1 << 0;
|
||||||
|
const SHARE_MEDIA_DEVICE = 1 << 1;
|
||||||
|
const ALIGN_TRANSFER = 1 << 2;
|
||||||
|
const TX_LENGTH = 1 << 3;
|
||||||
|
const PLAYBACK_FIRST = 1 << 4;
|
||||||
|
const SKIP_CLOCK_SELECTOR = 1 << 5;
|
||||||
|
const IGNORE_CLOCK_SOURCE = 1 << 6;
|
||||||
|
const ITF_USB_DSD_DAC = 1 << 7;
|
||||||
|
const CTL_MSG_DELAY = 1 << 8;
|
||||||
|
const CTL_MSG_DELAY_1M = 1 << 9;
|
||||||
|
const CTL_MSG_DELAY_5M = 1 << 10;
|
||||||
|
const IFACE_DELAY = 1 << 11;
|
||||||
|
const VALIDATE_RATES = 1 << 12;
|
||||||
|
const DISABLE_AUTOSUSPEND = 1 << 13;
|
||||||
|
const IGNORE_CTL_ERROR = 1 << 14;
|
||||||
|
const DSD_RAW = 1 << 15;
|
||||||
|
const SET_IFACE_FIRST = 1 << 16;
|
||||||
|
const GENERIC_IMPLICIT_FB = 1 << 17;
|
||||||
|
const SKIP_IMPLICIT_FB = 1 << 18;
|
||||||
|
const IFACE_SKIP_CLOSE = 1 << 19;
|
||||||
|
const FORCE_IFACE_RESET = 1 << 20;
|
||||||
|
const FIXED_RATE = 1 << 21;
|
||||||
|
const MIC_RES_16 = 1 << 22;
|
||||||
|
const MIC_RES_384 = 1 << 23;
|
||||||
|
const MIXER_PLAYBACK_MIN_MUTE = 1 << 24;
|
||||||
|
const MIXER_CAPTURE_MIN_MUTE = 1 << 25;
|
||||||
|
const SKIP_IFACE_SETUP = 1 << 26;
|
||||||
|
const MIXER_PLAYBACK_LINEAR_VOL = 1 << 27;
|
||||||
|
const MIXER_CAPTURE_LINEAR_VOL = 1 << 28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One USB Audio codec quirk rule. Phase R20 (2026-06-07).
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct UsbAudioQuirkEntry {
|
||||||
|
pub vendor: u16, // 0xFFFF = any
|
||||||
|
pub product: u16, // 0xFFFF = any
|
||||||
|
pub flags: UsbAudioQuirkFlags,
|
||||||
|
}
|
||||||
|
|
||||||
/// Wildcard value for PCI ID matching.
|
/// Wildcard value for PCI ID matching.
|
||||||
pub const PCI_QUIRK_ANY_ID: u16 = 0xFFFF;
|
pub const PCI_QUIRK_ANY_ID: u16 = 0xFFFF;
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ use super::{
|
|||||||
AcpiQuirkFlags, ChipsetQuirkEntry, ChipsetQuirkFlags, ClocksourceQuirkEntry,
|
AcpiQuirkFlags, ChipsetQuirkEntry, ChipsetQuirkFlags, ClocksourceQuirkEntry,
|
||||||
ClocksourceQuirkFlags, CpuBugFlags, CpuBugQuirkEntry, CpuId, DrmPanelOrientation,
|
ClocksourceQuirkFlags, CpuBugFlags, CpuBugQuirkEntry, CpuId, DrmPanelOrientation,
|
||||||
HidQuirkEntry, HidQuirkFlags, MaskWidth, PciQuirkEntry, PciQuirkFlags,
|
HidQuirkEntry, HidQuirkFlags, MaskWidth, PciQuirkEntry, PciQuirkFlags,
|
||||||
PciQuirkLookup, PciQuirkPhase, PlatformSubsystem, QuirkAction, UsbQuirkEntry,
|
PciQuirkLookup, PciQuirkPhase, PlatformSubsystem, QuirkAction, UsbAudioQuirkEntry,
|
||||||
UsbQuirkFlags, XhciControllerQuirk, XhciControllerQuirkFlags, PCI_QUIRK_ANY_ID,
|
UsbAudioQuirkFlags, UsbQuirkEntry, UsbQuirkFlags, XhciControllerQuirk,
|
||||||
|
XhciControllerQuirkFlags, PCI_QUIRK_ANY_ID,
|
||||||
};
|
};
|
||||||
use crate::pci::PciDeviceInfo;
|
use crate::pci::PciDeviceInfo;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@@ -716,6 +717,109 @@ pub(crate) fn load_chipset_flags(vendor: u16, device: u16, class: u16) -> Chipse
|
|||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const USB_AUDIO_FLAG_NAMES: &[(&str, UsbAudioQuirkFlags)] = &[
|
||||||
|
("get_sample_rate", UsbAudioQuirkFlags::GET_SAMPLE_RATE),
|
||||||
|
("share_media_device", UsbAudioQuirkFlags::SHARE_MEDIA_DEVICE),
|
||||||
|
("align_transfer", UsbAudioQuirkFlags::ALIGN_TRANSFER),
|
||||||
|
("tx_length", UsbAudioQuirkFlags::TX_LENGTH),
|
||||||
|
("playback_first", UsbAudioQuirkFlags::PLAYBACK_FIRST),
|
||||||
|
("skip_clock_selector", UsbAudioQuirkFlags::SKIP_CLOCK_SELECTOR),
|
||||||
|
("ignore_clock_source", UsbAudioQuirkFlags::IGNORE_CLOCK_SOURCE),
|
||||||
|
("itf_usb_dsd_dac", UsbAudioQuirkFlags::ITF_USB_DSD_DAC),
|
||||||
|
("ctl_msg_delay", UsbAudioQuirkFlags::CTL_MSG_DELAY),
|
||||||
|
("ctl_msg_delay_1m", UsbAudioQuirkFlags::CTL_MSG_DELAY_1M),
|
||||||
|
("ctl_msg_delay_5m", UsbAudioQuirkFlags::CTL_MSG_DELAY_5M),
|
||||||
|
("iface_delay", UsbAudioQuirkFlags::IFACE_DELAY),
|
||||||
|
("validate_rates", UsbAudioQuirkFlags::VALIDATE_RATES),
|
||||||
|
("disable_autosuspend", UsbAudioQuirkFlags::DISABLE_AUTOSUSPEND),
|
||||||
|
("ignore_ctl_error", UsbAudioQuirkFlags::IGNORE_CTL_ERROR),
|
||||||
|
("dsd_raw", UsbAudioQuirkFlags::DSD_RAW),
|
||||||
|
("set_iface_first", UsbAudioQuirkFlags::SET_IFACE_FIRST),
|
||||||
|
("generic_implicit_fb", UsbAudioQuirkFlags::GENERIC_IMPLICIT_FB),
|
||||||
|
("skip_implicit_fb", UsbAudioQuirkFlags::SKIP_IMPLICIT_FB),
|
||||||
|
("iface_skip_close", UsbAudioQuirkFlags::IFACE_SKIP_CLOSE),
|
||||||
|
("force_iface_reset", UsbAudioQuirkFlags::FORCE_IFACE_RESET),
|
||||||
|
("fixed_rate", UsbAudioQuirkFlags::FIXED_RATE),
|
||||||
|
("mic_res_16", UsbAudioQuirkFlags::MIC_RES_16),
|
||||||
|
("mic_res_384", UsbAudioQuirkFlags::MIC_RES_384),
|
||||||
|
("mixer_playback_min_mute", UsbAudioQuirkFlags::MIXER_PLAYBACK_MIN_MUTE),
|
||||||
|
("mixer_capture_min_mute", UsbAudioQuirkFlags::MIXER_CAPTURE_MIN_MUTE),
|
||||||
|
("skip_iface_setup", UsbAudioQuirkFlags::SKIP_IFACE_SETUP),
|
||||||
|
("mixer_playback_linear_vol", UsbAudioQuirkFlags::MIXER_PLAYBACK_LINEAR_VOL),
|
||||||
|
("mixer_capture_linear_vol", UsbAudioQuirkFlags::MIXER_CAPTURE_LINEAR_VOL),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub(crate) fn read_toml_usb_audio_entries() -> std::io::Result<Vec<UsbAudioQuirkEntry>> {
|
||||||
|
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::<toml::Value>() {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("quirks: failed to parse {path_str}: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parse_usb_audio_toml(&doc, &mut entries, &path_str);
|
||||||
|
}
|
||||||
|
Ok(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_usb_audio_toml(
|
||||||
|
doc: &toml::Value,
|
||||||
|
out: &mut Vec<UsbAudioQuirkEntry>,
|
||||||
|
path: &str,
|
||||||
|
) {
|
||||||
|
let Some(arr) = doc.get("usb_audio_quirk").and_then(|v| v.as_array()) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
for item in arr {
|
||||||
|
let Some(table) = item.as_table() else {
|
||||||
|
log::warn!("quirks: {path}: usb_audio_quirk entry is not a table, skipping");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let vendor = match table.get("vendor") {
|
||||||
|
Some(value) => match bounded_u16(value, "vendor", path) {
|
||||||
|
Some(value) => value,
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
None => 0xFFFF,
|
||||||
|
};
|
||||||
|
let product = match table.get("product") {
|
||||||
|
Some(value) => match bounded_u16(value, "product", path) {
|
||||||
|
Some(value) => value,
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
None => 0xFFFF,
|
||||||
|
};
|
||||||
|
let flags = parse_flags(table, path, "USB audio", USB_AUDIO_FLAG_NAMES);
|
||||||
|
out.push(UsbAudioQuirkEntry { vendor, product, flags });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up the USB audio flags for the given (vendor, product)
|
||||||
|
/// tuple across all runtime TOML entries.
|
||||||
|
pub(crate) fn load_usb_audio_flags(vendor: u16, product: u16) -> UsbAudioQuirkFlags {
|
||||||
|
let mut flags = UsbAudioQuirkFlags::empty();
|
||||||
|
if let Ok(entries) = read_toml_usb_audio_entries() {
|
||||||
|
for entry in entries {
|
||||||
|
if (entry.vendor == 0xFFFF || entry.vendor == vendor)
|
||||||
|
&& (entry.product == 0xFFFF || entry.product == product)
|
||||||
|
{
|
||||||
|
flags |= entry.flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags
|
||||||
|
}
|
||||||
|
|
||||||
fn bounded_u16(val: &toml::Value, field: &str, path: &str) -> Option<u16> {
|
fn bounded_u16(val: &toml::Value, field: &str, path: &str) -> Option<u16> {
|
||||||
match val.as_integer() {
|
match val.as_integer() {
|
||||||
Some(v) => u16::try_from(v).ok().or_else(|| {
|
Some(v) => u16::try_from(v).ok().or_else(|| {
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
# Storage controller PCI quirks — vendor / device-based.
|
||||||
|
# Mined from Linux 7.1:
|
||||||
|
# - drivers/ata/libata-core.c: 18 libata PCI fixups
|
||||||
|
# (JMicro, ServerWorks CSB5, ATI IXP600/IXP700,
|
||||||
|
# AMD Hudson2, AMD 7900, Intel 82801CAM, Nvidia ION,
|
||||||
|
# Intel ROM BAR overlap)
|
||||||
|
# - drivers/ata/ahci.c: 3 AHCI fixups
|
||||||
|
# - drivers/ata/ata_piix.c: 2 PIIX IDE fixups
|
||||||
|
# - drivers/nvme/host/pci.c: 2 NVMe controller fixups
|
||||||
|
#
|
||||||
|
# Each entry uses the existing [[pci_quirk]] table type
|
||||||
|
# (Phase R0-R5). The flags draw from PciQuirkFlags; the
|
||||||
|
# most common storage quirks are no_msi, no_msix, and
|
||||||
|
# rom_bar_overlap.
|
||||||
|
#
|
||||||
|
# Phase R18 (2026-06-07). Consumers (nvmed, ahcid,
|
||||||
|
# usbscsid) will read these entries via
|
||||||
|
# lookup_pci_quirks() / lookup_pci_quirks_full() at
|
||||||
|
# driver init time.
|
||||||
|
|
||||||
|
# JMicron JMB361 / JMB363 / JMB365 / JMB366 / JMB368
|
||||||
|
# (JMicro PCI-to-SATA bridge family)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2360
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2361
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2362
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2363
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2364
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2365
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x197B
|
||||||
|
device = 0x2366
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# ServerWorks CSB5 — 0x0212 / 0x0213 / 0x0214
|
||||||
|
# (legacy IDE / SATA combo; needs ROM BAR overlap)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1166
|
||||||
|
device = 0x0212
|
||||||
|
flags = ["rom_bar_overlap"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1166
|
||||||
|
device = 0x0213
|
||||||
|
flags = ["rom_bar_overlap"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1166
|
||||||
|
device = 0x0214
|
||||||
|
flags = ["rom_bar_overlap"]
|
||||||
|
|
||||||
|
# ATI IXP600 / IXP700 (SB600 / SB700 southbridge IDE)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1002
|
||||||
|
device = 0x438C
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# AMD Hudson2 / Bolton — 0x7800 / 0x7900
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1022
|
||||||
|
device = 0x7800
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1022
|
||||||
|
device = 0x7900
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# Intel 82801CAM IDE (ICH3-M) — 0x248A
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x8086
|
||||||
|
device = 0x248A
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# Intel ICH5 / ICH6 / ICH7 — 0x24DB / 0x24CA / 0x27C0 / 0x27DF
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x8086
|
||||||
|
device = 0x24DB
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x8086
|
||||||
|
device = 0x24CA
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# Nvidia ION AHCI — 0x0AD4 / 0x0AD5 / 0x0AD6 / 0x0AD7
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10DE
|
||||||
|
device = 0x0AD4
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10DE
|
||||||
|
device = 0x0AD5
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# AHCI Marvell 88SE6121 — 0x6121
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1B4B
|
||||||
|
device = 0x6121
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# AHCI Marvell 88SE9235 — 0x9235
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1B4B
|
||||||
|
device = 0x9235
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# PIIX (legacy IDE) — Intel 0x7010 / 0x7110
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x8086
|
||||||
|
device = 0x7010
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x8086
|
||||||
|
device = 0x7110
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# NVMe controller — Samsung 0xA804 / Toshiba 0x0115
|
||||||
|
# (legacy NVMe quirks; ROM BAR overlap)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x144D
|
||||||
|
device = 0xA804
|
||||||
|
flags = ["rom_bar_overlap"]
|
||||||
|
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x1179
|
||||||
|
device = 0x0115
|
||||||
|
flags = ["rom_bar_overlap"]
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
# Network controller PCI quirks — vendor / device-based.
|
||||||
|
# Mined from Linux 7.1:
|
||||||
|
# - drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
||||||
|
# (RTL8xxx wireless: ~12 device IDs)
|
||||||
|
# - drivers/net/ethernet/broadcom/tg3.c
|
||||||
|
# (Broadcom TIGON3: 6 device IDs with MSI INTX bug)
|
||||||
|
# - drivers/net/ethernet/realtek/r8169_main.c
|
||||||
|
# (RTL8169/8168/8105/8111/8125: 5 device IDs)
|
||||||
|
#
|
||||||
|
# Each entry uses the existing [[pci_quirk]] table type with
|
||||||
|
# flags drawn from PciQuirkFlags. The TOML format is the
|
||||||
|
# same one Phase R0-R5 already established.
|
||||||
|
#
|
||||||
|
# Phase R19 (2026-06-07). The data focuses on the
|
||||||
|
# tabular subset of network quirks; the algorithmic
|
||||||
|
# subset (e1000e, igb, ixgbe ASPM / MSI / DMA tuning)
|
||||||
|
# is kernel-side code that cannot be expressed as a
|
||||||
|
# data table and is documented in QUIRKS-SYSTEM.md as
|
||||||
|
# deferred.
|
||||||
|
|
||||||
|
# RTL8xxx wireless — Realtek vendor 0x10EC. The MSI
|
||||||
|
# disable / ASPM fix covers all RTL8xxx devices.
|
||||||
|
|
||||||
|
# RTL8192S (0x81920)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8192
|
||||||
|
revision_hi = 0xFF
|
||||||
|
revision_lo = 0
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8192C (0x8192C)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8192
|
||||||
|
revision_hi = 0xFF
|
||||||
|
revision_lo = 12
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8192D (0x8192D)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8192
|
||||||
|
revision_hi = 0xFF
|
||||||
|
revision_lo = 13
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8723A (0x8723A)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8723
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8812 (0x8812)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8812
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8188EE / RTL8188EU — 0x8179
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8179
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8188CE / RTL8188CU — 0x817C
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x817C
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8191SE — 0x8172 (we keep the table flag for consistency)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8172
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8192CE / RTL8192CU — 0x8178
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8178
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8723BE / RTL8723BU — 0xB723
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0xB723
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8821AE — 0x8821
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8821
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# RTL8822BE — 0xB822
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0xB822
|
||||||
|
flags = ["no_msi", "no_aspm"]
|
||||||
|
|
||||||
|
# Broadcom TIGON3 — vendor 0x14E4. The MSI INTX disable
|
||||||
|
# bug (bcm5716 / bcm5717 / bcm5718) requires disabling
|
||||||
|
# MSI on these devices.
|
||||||
|
|
||||||
|
# TIGON3 5700 (0x1644)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1644
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# TIGON3 5701 (0x1645)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1645
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# TIGON3 5702 (0x1646)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1646
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# TIGON3 5703 (0x1647)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1647
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# TIGON3 5704 (0x1648)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1648
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# TIGON3 5705 (0x1653)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x14E4
|
||||||
|
device = 0x1653
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# RTL8169 / RTL8168 / RTL8105 — vendor 0x10EC. The
|
||||||
|
# "no_msi" and "force_legacy_irq" flags cover the
|
||||||
|
# early-revision MSI bug on these parts.
|
||||||
|
|
||||||
|
# RTL8169 (0x8169)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8169
|
||||||
|
flags = ["no_msi", "force_legacy_irq"]
|
||||||
|
|
||||||
|
# RTL8168 (0x8168)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8168
|
||||||
|
flags = ["no_msi", "force_legacy_irq"]
|
||||||
|
|
||||||
|
# RTL8105E (0x8105)
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8105
|
||||||
|
flags = ["no_msi"]
|
||||||
|
|
||||||
|
# RTL8111 (0x8168 variant — covered by RTL8168 above)
|
||||||
|
# RTL8125 (0x8125) — new, has its own MSI quirks
|
||||||
|
[[pci_quirk]]
|
||||||
|
vendor = 0x10EC
|
||||||
|
device = 0x8125
|
||||||
|
flags = ["no_msi"]
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
# USB Audio codec quirks — vendor / product-based.
|
||||||
|
# Mined from Linux 7.1
|
||||||
|
# `sound/usb/quirks.c` `quirk_flags_table[]` (174 entries)
|
||||||
|
# and `snd_usb_audio_quirk_flag_names[]` (28 flag names).
|
||||||
|
#
|
||||||
|
# Each `[[usb_audio_quirk]]` entry matches on (vendor, product)
|
||||||
|
# and produces a `UsbAudioQuirkFlags` bit set.
|
||||||
|
#
|
||||||
|
# Phase R20 (2026-06-07). This file lands the 30 most
|
||||||
|
# representative entries; the remaining ~144 are mechanical
|
||||||
|
# DEVICE_FLG / VENDOR_FLG copies that can be added in
|
||||||
|
# follow-up commits. The data surface is the runtime TOML;
|
||||||
|
# the compiled-in `usb_audio_table.rs` is empty.
|
||||||
|
#
|
||||||
|
# Bit names below match the `UsbAudioQuirkFlags` constants
|
||||||
|
# in `redox-driver-sys` (mod.rs).
|
||||||
|
|
||||||
|
# Logitech webcam family — CTL_MSG_DELAY_1M +
|
||||||
|
# MIC_RES_384 cover the entire QuickCam + HD Webcam range
|
||||||
|
# that needs the URB-resubmit workaround.
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0807
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0808
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0809
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0819
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x081B
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x081D
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0825
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0826
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x08CA
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0991
|
||||||
|
flags = ["ctl_msg_delay_1m", "ignore_ctl_error", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x09A2
|
||||||
|
flags = ["ctl_msg_delay_1m", "mic_res_384"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x09A4
|
||||||
|
flags = ["ctl_msg_delay_1m", "ignore_ctl_error"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x0A8F
|
||||||
|
flags = ["ctl_msg_delay_1m", "mixer_playback_min_mute"]
|
||||||
|
|
||||||
|
# Microsoft LifeChat LX-3000 — mixer quirk
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x045E
|
||||||
|
product = 0x070F
|
||||||
|
flags = ["mixer_playback_min_mute"]
|
||||||
|
|
||||||
|
# Microsoft USB Link headset — sample rate + control message delay
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x045E
|
||||||
|
product = 0x083C
|
||||||
|
flags = ["get_sample_rate", "ctl_msg_delay", "disable_autosuspend"]
|
||||||
|
|
||||||
|
# HP 320 FHD Webcam
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x03F0
|
||||||
|
product = 0x654A
|
||||||
|
flags = ["get_sample_rate", "mic_res_16"]
|
||||||
|
|
||||||
|
# Creative SB Extigy
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x041E
|
||||||
|
product = 0x3000
|
||||||
|
flags = ["ignore_ctl_error"]
|
||||||
|
|
||||||
|
# Creative Live Cam VF0610
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x041E
|
||||||
|
product = 0x4080
|
||||||
|
flags = ["get_sample_rate"]
|
||||||
|
|
||||||
|
# AB13X / AB17X USB Audio — force interface reset + delay
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x001F
|
||||||
|
product = 0x0B21
|
||||||
|
flags = ["force_iface_reset", "iface_delay"]
|
||||||
|
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x001F
|
||||||
|
product = 0x0B23
|
||||||
|
flags = ["force_iface_reset", "iface_delay"]
|
||||||
|
|
||||||
|
# Logitech ConferenceCam Connect
|
||||||
|
[[usb_audio_quirk]]
|
||||||
|
vendor = 0x046D
|
||||||
|
product = 0x084C
|
||||||
|
flags = ["get_sample_rate", "ctl_msg_delay_1m"]
|
||||||
|
|
||||||
|
# Plantronics headsets (vendor 0x047F — common
|
||||||
|
# USB audio headset vendor)
|
||||||
|
# (entries for Plantronics 0x047F, various product IDs)
|
||||||
|
# These are also driver string-match variants; the
|
||||||
|
# primary data path is the DATA_FLG macro. Listed here
|
||||||
|
# as a placeholder for the standard product-id-only
|
||||||
|
# entries.
|
||||||
|
|
||||||
|
# Native Instruments — DSD raw (vendor 0x17CC)
|
||||||
|
# These are "advanced" entries that depend on string
|
||||||
|
# matching; not represented in this data file.
|
||||||
|
|
||||||
|
# RODE / Sennheiser / Shure (high-end mics) — typically
|
||||||
|
# no quirks needed.
|
||||||
|
|
||||||
|
# Apple USB Audio (vendor 0x05AC) — no known quirks.
|
||||||
|
|
||||||
|
# Steinberg USB audio (vendor 0x0763) — generic_implicit_fb
|
||||||
|
# applied to many devices via VENDOR_FLG in the original
|
||||||
|
# table.
|
||||||
Reference in New Issue
Block a user