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:
2026-06-07 22:18:53 +03:00
parent 9e7020bc50
commit f0b2b01da0
6 changed files with 641 additions and 2 deletions
@@ -1027,4 +1027,17 @@ mod tests {
// Different class base
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.
pub const PCI_QUIRK_ANY_ID: u16 = 0xFFFF;
@@ -3,8 +3,9 @@ use super::{
AcpiQuirkFlags, ChipsetQuirkEntry, ChipsetQuirkFlags, ClocksourceQuirkEntry,
ClocksourceQuirkFlags, CpuBugFlags, CpuBugQuirkEntry, CpuId, DrmPanelOrientation,
HidQuirkEntry, HidQuirkFlags, MaskWidth, PciQuirkEntry, PciQuirkFlags,
PciQuirkLookup, PciQuirkPhase, PlatformSubsystem, QuirkAction, UsbQuirkEntry,
UsbQuirkFlags, XhciControllerQuirk, XhciControllerQuirkFlags, PCI_QUIRK_ANY_ID,
PciQuirkLookup, PciQuirkPhase, PlatformSubsystem, QuirkAction, UsbAudioQuirkEntry,
UsbAudioQuirkFlags, UsbQuirkEntry, UsbQuirkFlags, XhciControllerQuirk,
XhciControllerQuirkFlags, PCI_QUIRK_ANY_ID,
};
use crate::pci::PciDeviceInfo;
use std::borrow::Cow;
@@ -716,6 +717,109 @@ pub(crate) fn load_chipset_flags(vendor: u16, device: u16, class: u16) -> Chipse
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> {
match val.as_integer() {
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.