Add RTL8814AU (Jaguar 4T4R) RX support#23
Merged
Conversation
Documents the Jaguar-family chipset table (8812AU supported, 8811AU on branch, 8821AU/8814AU unsupported), Linux/macOS/Windows build steps, the caller's libusb responsibilities, and the project layout. Drops the stale spdlog dependency from the vcpkg install line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
RTL8811AU is the 1T1R cut of the same Jaguar silicon as RTL8812AU. The 1T1R BB/RF/TX-power paths are already implemented (PHY_BB8812_Config_1T, numTotalRfPath loops, per-BW L1pkVal branches) but were unreachable because read_chip_version_8812a hardcoded RFType=RF_TYPE_2T2R. - EepromManager: derive RFType from REG_SYS_CFG bit 27 (RF_TYPE_ID); keep registry_priv::special_rf_path as a manual override for mis-burnt EFUSE. - demo: try a small allow-list of known Realtek PIDs (0x8812, 0x0811, 0xa811, 0xb811) instead of hardcoding 0x8812. PID 0xc811 is intentionally excluded because it is shared with the unrelated RTL8811CU chipset. Refs #20 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Devourer now drives the RTL8814AU (VID/PID 0bda:8813), Realtek's
4T4R / 3-SS Jaguar-family chip. Verified on COMFAST CF-938AC: RX/
monitor-mode receives real 802.11 frames (beacons, probe requests/
responses, data) on both 2.4 GHz and 5 GHz bands. TX path
infrastructure is in place but not end-to-end validated yet.
The 8814AU is structurally the same Jaguar baseband as 8812AU but
with 4 RF chains, 3 spatial streams maximum, and a different firmware
download transport (RSVD-page TX via beacon queue + IDDMA copy to
8051/3081 DMEM/IMEM instead of the 8812's page-mapped vendor write).
Most of the existing 8812 HAL infrastructure is reusable; this change
extends each layer where the 8814 diverges.
Key changes
-----------
Refactor Rtl8812aDevice → RtlJaguarDevice. The class is the
orchestrator for the entire Jaguar family (8811/8812/8814), not just
8812. A `using Rtl8812aDevice = RtlJaguarDevice` typedef is left in
RtlJaguarDevice.h with the [[deprecated]] attribute so any external
caller that still references the old name keeps compiling for one
release cycle.
Chip-version detection (EepromManager). PID 0x8813 → CHIP_8814A,
RF_TYPE_4T4R, maxSpatialStreams=3. The +1 on raw cut bits that the
Jaguar code did for 8812A is dropped for 8814A — upstream rtw88's
rtw88xxa_read_efuse only +1's for 8812A.
Vendor data files (hal/). Port hal8814a_fw.[ch] (68 KB blob),
Hal8814PhyReg.h (BB/RF register definitions), Hal8814PwrSeq.[ch]
(power-on/off command tables), plus the phydm directory tree
including Hal8814_PhyTables.[ch] (4622-entry phy_reg + 6280-entry
agc_tab tables auto-generated from upstream phydm via
tools/extract_8814a_phy_tables.py).
PhyTableLoader. New helper that walks a phydm-encoded table at
runtime, evaluating its IF/ELSE_IF/ELSE/ENDIF opcodes against a
chip-version + interface + rfe context. Used for the 8814 BB/AGC/
MAC/RF tables, since the upstream phydm "compile out everything
that doesn't match this build" approach doesn't fit a userspace
runtime driver that may serve multiple boards.
Firmware download (FirmwareManager::FirmwareDownload_8814A). The
8814 uses RSVD-page TX + IDDMA copy. Implementation steps:
• 242-op rtw88_8814au pre-fwdl register replay (writes AND reads
— the reads matter: several Realtek regs have read-side-effects
that gate the chip's subsequent state transitions).
• Beacon-queue submission of the firmware in 4136-byte (or
smaller) chunks via bulk OUT EP 0x02.
• IDDMA controller programming (REG_DDMA_CH0SA/DA/CTRL at
0x1200-0x1208) to copy each chunk from TX FIFO to the 3081's
DMEM/IMEM.
• Per-chunk poll of BIT15 of REG_FIFOPAGE_CTRL_2 (0x0204) for the
chip's "RSVD page write acknowledged" signal.
• Post-fwdl CPU kick: REG_MCUFWDL byte 0 = 0x79, REG_MCUFWDL
word = 0x6078 (clear FWDL_EN, set FW_DW_RDY), REG_RSV_CTRL+1
= 0xfe (set FEN_CPUEN).
• "FW ready" detection by byte 0 of REG_MCUFWDL == 0x78 (stable
post-boot signature). The transient BIT15 (FW_INIT_RDY) that
rtw88 polls is missed by userspace polling.
BB/RF domain power-on. The chip's BB register space (0x800-0xFFF)
silently rejects writes via vendor control transfer unless the BB
and RF domains are explicitly powered on first. After fwdl, write:
• REG_SYS_FUNC_EN (0x0002) |= BIT_FEN_USBA (BIT2) — enable USB→BB
• REG_SYS_CFG3_8814A+2 (0x1002) |= BB_RSTB | BB_GLB_RST (BIT0|BIT1)
• REG_RF_CTRL[0..3] (0x001F / 0x0020 / 0x0021 / 0x0076) = 0x07
(RF_EN | RF_RSTB | RF_SDM_RSTB) — 4 separate registers for the
4 RF chains.
Verified: without these the 1837 BB table writes from
array_mp_8814a_phy_reg apply at the USB layer but the chip leaves
the registers at their reset values. With them, every BB reg lands
at its expected table value.
Post-fwdl EFUSE read. The constructor skips EFUSE on 8814 (pre-fwdl
EFUSE access breaks the chip's RSVD-page state machine), so the
parsers run against an all-0xFF shadow. After fwdl, call
EepromManager::LateInitFor8814A which re-runs the EFUSE read and
the parsers with real data, populating rfe_type, PA/LNA types,
crystal_cap, thermal_meter. Falls back to rfe_type=1 in
GetPhyContext if LateInit hasn't run or the EFUSE doesn't carry an
RFE option (every conditional block in the 8814 BB tables gates on
rfe_type ∈ 1..11).
4-path RadioManagementModule. Numerous loops that hard-coded paths
A and B (phy_RFSerialRead/Write, phy_set_rf_reg dispatch, the
8814-specific path C/D LSSIW reg offsets 0x1890 / 0x1A90 etc.)
extended to walk all numTotalRfPath paths. Path C/D RF reads are
not supported by the chip's 3-wire mechanism (rtw88's
rtw88xxa_phy_read_rf also only indexes A/B); paths C/D are write-
only and rtw88 propagates path-A's RF read to C/D via writes.
RX descriptor unpack. FrameParser populates path-C / path-D RSSI
+ SNR slots from the 8814 RX status descriptor (the storage
already existed in the rx_pkt_attrib struct).
USB endpoint priority. _InitNormalChipFourOutEpPriority_8814AUsb
mirrors the 8812 four-EP setup with the 8814-specific queue→EP
mapping.
Demo. demo/main.cpp adds DEVOURER_PID (restrict to a single VID/
PID), DEVOURER_CHANNEL (override the default monitor channel),
DEVOURER_SKIP_RESET (skip libusb_reset_device on claim — for
rtw88-prime-then-devourer takeover), DEVOURER_FORCE_TXPWR (run
the 4T4R TX-power-by-rate loop, off by default since monitor mode
doesn't need it). Adds RX packet count + size log.
TX-power-by-rate loop is skipped by default for 8814 monitor mode
(370 PHY_SetTxPowerIndex calls × ~20-30s one-time cost during
channel switch; values only consumed by TX path which isn't yet
validated end-to-end on this chip).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The homegrown format_helper was ignoring any spec inside braces,
so {:08x} just streamed values via default stream operator<<. That
silently printed integers as decimal — found while debugging 8814
fwdl, where REG_MCUFWDL=0x00606078 showed up in logs as the
literal string "REG_MCUFWDL:0x6316152" (the decimal representation
of 0x606078), sending us chasing a phantom for several sessions.
Add a minimal parser for the spec subset the codebase uses:
• optional '0' zero-padding flag
• optional width digits
• optional 'x'/'X' for lowercase/uppercase hex
Falls back to default streaming when no spec is given. Verified
against existing 8812 logs (REG_MCUFWDL now prints "0x000607c6"
rather than the decimal 395718).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Hardware matrix: 8814AU row moves from "Not supported" to "RX supported" (VID/PID 0bda:8813); note 4T4R RF / 3-SS baseband cap, 2-SS effective on USB-2, TX path not yet validated. - 8811AU row moves from "in progress" to "Supported". - Family blurb expanded to credit Hal8814PhyReg.h and hal8814a_fw.[ch] as reusable across the Jaguar family. - Build artifacts: WiFiDriverDemo now walks every Realtek device under VID 0bda rather than the old hardcoded 0bda:8812 open. - New "Demo env vars" section documents DEVOURER_PID, DEVOURER_CHANNEL, DEVOURER_SKIP_RESET, DEVOURER_FORCE_TXPWR (the last one explains the slow 8814 TX-power-by-rate loop and why it's skipped by default). - Project layout: add hal/Hal8814PhyReg.h, hal8814a_fw.[ch], Hal8814PwrSeq. [ch], rtl8814a/Hal8814_PhyTables.[ch]; rename Rtl8812aDevice -> RtlJaguar Device; add FirmwareManager and PhyTableLoader entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for the RTL8814AU (VID/PID
0bda:8813) — Realtek's 4T4R / 3-SS Jaguar-family chip. Verified on COMFAST CF-938AC: monitor-mode RX receives real 802.11 frames on both 2.4 GHz and 5 GHz bands. TX infrastructure is in place but not validated end-to-end.Stacked on PR #21 (RTL8811AU support). The first commit on this branch is identical to PR #21; once #21 merges this PR can be rebased.
Highlights
Rtl8812aDevice→RtlJaguarDevicerename (deprecated alias kept for one release).EepromManager(8813 →CHIP_8814A, RF_TYPE_4T4R, max 3 spatial streams).hal8814a_fw.[ch]blob (~68 KB),Hal8814PhyReg.h,Hal8814PwrSeq.[ch], phydm phy_reg + agc_tab tables auto-generated from upstream phydm.PhyTableLoaderthat runtime-evaluates phydmIF/ELSE_IF/ENDIFopcodes against chip-cut + interface + rfe — the phydm "compile out non-matching branches" approach doesn't fit a userspace driver that may serve multiple board variants.FirmwareManager::FirmwareDownload_8814A— RSVD-page TX via beacon queue + IDDMA copy to 3081 DMEM/IMEM (the 8814 download path is structurally different from the 8812's page-mapped vendor write).REG_SYS_FUNC_EN,REG_SYS_CFG3_8814A+2,REG_RF_CTRL[0..3]) — without this the BB writes silently no-op on the chip side.EepromManager::LateInitFor8814A) — the chip rejects EFUSE reads pre-fwdl, so the constructor skips them on 8814 andLateInitre-runs the parsers against real data once firmware is up.RadioManagementModuleloops scaled to up to 4 RF paths; path-C/D writes; path-A/B-only reads (matches rtw88's behaviour — the chip's 3-wire SI/PI mechanism doesn't support C/D reads).FrameParserpopulates path-C/D RSSI + SNR slots from the 8814 RX descriptor.DEVOURER_PID,DEVOURER_CHANNEL,DEVOURER_SKIP_RESET,DEVOURER_FORCE_TXPWR.Known limitations
rfe_typefrom EFUSE only verified on CF-938AC (returns 1). Other 8814 boards may report different RFE options that exercise BB-table branches we haven't touched. Falls back torfe_type=1if EFUSE doesn't carry a value.rtw88xxa_phy_read_rfonly indexes paths A/B).Test plan
cmake -S . -B build && cmake --build build🤖 Generated with Claude Code