Skip to content

Add RTL8814AU (Jaguar 4T4R) RX support#23

Merged
josephnef merged 5 commits into
masterfrom
feat/rtl8814au-support
May 21, 2026
Merged

Add RTL8814AU (Jaguar 4T4R) RX support#23
josephnef merged 5 commits into
masterfrom
feat/rtl8814au-support

Conversation

@josephnef
Copy link
Copy Markdown
Collaborator

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

  • Rtl8812aDeviceRtlJaguarDevice rename (deprecated alias kept for one release).
  • Chip-version detection in EepromManager (8813 → CHIP_8814A, RF_TYPE_4T4R, max 3 spatial streams).
  • 8814 vendor data: hal8814a_fw.[ch] blob (~68 KB), Hal8814PhyReg.h, Hal8814PwrSeq.[ch], phydm phy_reg + agc_tab tables auto-generated from upstream phydm.
  • New PhyTableLoader that runtime-evaluates phydm IF/ELSE_IF/ENDIF opcodes 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).
  • BB/RF domain power-on after fwdl (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.
  • Post-fwdl EFUSE read (EepromManager::LateInitFor8814A) — the chip rejects EFUSE reads pre-fwdl, so the constructor skips them on 8814 and LateInit re-runs the parsers against real data once firmware is up.
  • RadioManagementModule loops 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).
  • FrameParser populates path-C/D RSSI + SNR slots from the 8814 RX descriptor.
  • Demo env vars: DEVOURER_PID, DEVOURER_CHANNEL, DEVOURER_SKIP_RESET, DEVOURER_FORCE_TXPWR.

Known limitations

  • TX not validated end-to-end on 8814. Descriptor layout and rate mapping look correct, USB endpoint priority is wired up, but no injected-beacon → peer-sniffer test has been performed yet. The TX-power-by-rate loop (~370 control transfers, 20–30s) is skipped by default in monitor mode for this reason.
  • rfe_type from 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 to rfe_type=1 if EFUSE doesn't carry a value.
  • 160 MHz BW is out of scope. The silicon supports it but no lab path validates it.
  • Path-C/D RF reads are not supported by the chip's 3-wire SI/PI mechanism. This is upstream rtw88's behaviour as well (rtw88xxa_phy_read_rf only indexes paths A/B).

Test plan

  • Build clean: cmake -S . -B build && cmake --build build
  • 8812 regression on existing adapter
  • 8814 RX on CF-938AC, 2.4 GHz channel 6 — beacons + probe req/resp + data frames received
  • 8814 RX on CF-938AC, 5 GHz — frames received
  • 8814 TX → peer sniffer (deferred; TX path not yet validated)
  • 8814 RX on a second board with a non-CF-938AC EFUSE (deferred; no second board available)

🤖 Generated with Claude Code

josephnef and others added 5 commits May 20, 2026 19:55
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>
@josephnef josephnef merged commit f05b743 into master May 21, 2026
5 checks passed
@josephnef josephnef deleted the feat/rtl8814au-support branch May 21, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant