diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs index c7340c2389..6816e220fb 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs @@ -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)); + } } 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 1e65e879ac..69eb53cd01 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 @@ -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; 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 da5020eb56..02d8286b90 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 @@ -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> { + 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_usb_audio_toml(&doc, &mut entries, &path_str); + } + Ok(entries) +} + +fn parse_usb_audio_toml( + doc: &toml::Value, + out: &mut Vec, + 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 { match val.as_integer() { Some(v) => u16::try_from(v).ok().or_else(|| { diff --git a/local/recipes/system/redbear-quirks/source/quirks.d/35-storage-extended.toml b/local/recipes/system/redbear-quirks/source/quirks.d/35-storage-extended.toml new file mode 100644 index 0000000000..d534044ee1 --- /dev/null +++ b/local/recipes/system/redbear-quirks/source/quirks.d/35-storage-extended.toml @@ -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"] diff --git a/local/recipes/system/redbear-quirks/source/quirks.d/55-network.toml b/local/recipes/system/redbear-quirks/source/quirks.d/55-network.toml new file mode 100644 index 0000000000..a79c10501f --- /dev/null +++ b/local/recipes/system/redbear-quirks/source/quirks.d/55-network.toml @@ -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"] diff --git a/local/recipes/system/redbear-quirks/source/quirks.d/60-usb-audio.toml b/local/recipes/system/redbear-quirks/source/quirks.d/60-usb-audio.toml new file mode 100644 index 0000000000..a2c5747bf9 --- /dev/null +++ b/local/recipes/system/redbear-quirks/source/quirks.d/60-usb-audio.toml @@ -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.