The Realtek 11ac driver that simply devours its competitors.
Devourer is a userspace Wi-Fi driver for Realtek's 802.11ac USB adapters — the cheap, everywhere-available dongles that power most long-range FPV video links. It talks to the chip directly over libusb: no kernel module, no DKMS tree to patch every time your kernel updates, no root filesystem to taint. Build one static library, link it, and you have raw monitor-mode RX and packet injection on three generations of Realtek silicon, from a single API.
It is the OpenIPC project's driver of choice for long-range digital video links.
- No kernel driver, no driver hell. Everything runs in your process via libusb. The same code works on Linux, macOS, Windows, and Android (Termux) — including platforms the vendor drivers never supported.
- Faster on-air than the kernel driver. Ready-to-receive and
ready-to-transmit come up quicker than the vendor
.koon every supported chip (numbers). - Per-packet control. Every injected frame carries its own radiotap header: rate, bandwidth, guard interval, coding, STBC — even TX power and channel — can change frame by frame. That turns one dongle into an adaptive-link engine: unequal error protection for video layers, live power control, per-packet frequency hopping.
- Frequency hopping at FHSS speed. A channel hop costs ~0.5–2.5 ms depending on chip — fast enough to hop on every packet (how).
- Narrowband modes the kernel can't do. 5 and 10 MHz channels on the newest chips — half/quarter the bandwidth, more range from the same power.
- A radio lab in a dongle. Channel sounding, per-antenna signal quality, beamforming report capture (enough to do motion sensing), spectrum sweeps, link-health diagnosis that tells you whether to add or back off power.
- Clean library API. One
DeviceConfigstruct at construction, runtime setters for everything that changes mid-flight, zero environment-variable magic inside the library.
New to low-level RF? Start with the visual RF primer — eight short animations that make the rest click.
Bandwidth cells are devourer's measured on-air TX throughput (Mbps, HT MCS7, 20 MHz) per band:
| Part | RF / streams | 2.4 GHz (ch6) | UNII-1 (ch36) | UNII-2/3 (ch149) | Notes |
|---|---|---|---|---|---|
| RTL8812AU | 2T2R | 56 | 52 | 52 | CHANEVE CHW50L (0bda:8812) |
| RTL8811AU | 1T1R | — | — | — | 1T1R cut of 8812 silicon; rides the 8812 code path. Not benchmarked |
| RTL8814AU | 4T4R, 3-SS max | 65 | †(32) | †(32) | 0bda:8813; tested on COMFAST CF-938AC and CF-960AC — antenna builds differ in realised RX diversity |
| RTL8821AU | 1T1R AC + BT | 54 | 32 | 28 | TP-Link Archer T2U Plus (2357:0120) |
| RTL8822BU | 2T2R + BT | 52 | 50 | 49 | TP-Link Archer T3U (2357:012d) |
| RTL8812BU | 1T1R + BT | — | — | — | 1T1R cut of 8822B silicon; rides the 8822BU code path. Not benchmarked |
| RTL8811CU | 1T1R + BT | 36 | 29 | 28 | COMFAST CF-811AC (0bda:c811) |
| RTL8812CU | 2T2R | 65 | 60 | 60 | LB-LINK WDN1300H (0bda:c812) |
| RTL8822CU | 2T2R + BT | — | — | — | not benchmarked (0bda:c82c) |
| RTL8812EU | 2T2R | 8 | 51 | 47 | LB-LINK BL-M8812EU2 (0bda:a81a); bare 5 GHz FPV module. 5/10 MHz capable |
| RTL8822EU | 2T2R + BT | — | — | — | not benchmarked. 5/10 MHz capable |
† = works on-air but the reading varies run-to-run (bracketed = best clean
reading).
Out of scope: the PCIe siblings (e.g. 8822BE) and the 11ax "Kestrel" generation — same branding, different bus or baseband.
Heads up — some Realtek sticks ship in "ZeroCD" mode and first enumerate as a USB flash drive holding a Windows installer (
0bda:1a2bis the canonical offender). If the device won't open, checklsusb;usb_modeswitchflips it to the real NIC.
Toolchain: CMake ≥ 3.15, a C++20 compiler, libusb-1.0.
# Debian/Ubuntu
sudo apt install build-essential cmake pkg-config libusb-1.0-0-dev
# macOS (Homebrew)
brew install cmake pkg-config libusb
cmake -S . -B build
cmake --build build -jOn Windows, install libusb via vcpkg (vcpkg install libusb) and set
VCPKG_ROOT before configuring.
Then, with a supported dongle plugged in:
sudo ./build/rxdemo # receive: monitor mode, prints frames
sudo ./build/txdemo # transmit: injects a test beacon
DEVOURER_CHANNEL=100 DEVOURER_TX_RATE=MCS7/40 sudo -E ./build/txdemoThe demos find the first supported adapter automatically; DEVOURER_PID /
DEVOURER_VID pin a specific one. Every configuration knob the demos accept
is an environment variable — the complete catalogue, with value grammar, is
the env: tags in src/DeviceConfig.h.
| binary | what it shows |
|---|---|
rxdemo |
monitor-mode RX loop with per-frame signal telemetry |
txdemo |
packet injection, rate/power/channel control, hopping |
streamtx / duplex |
stdin-driven TX / full-duplex packet link |
svctx |
per-video-layer rate ladders (unequal error protection) |
txpower |
runtime TX-power API walkthrough |
sense |
Wi-Fi motion sensing from beamforming reports |
precoder |
OFDM subcarrier shaping proof-of-concept |
All chips compile in by default; per-chip CMake options (DEVOURER_JAGUAR1,
DEVOURER_8814, DEVOURER_JAGUAR2_8822B, DEVOURER_JAGUAR2_8821C,
DEVOURER_JAGUAR3_8822C, DEVOURER_JAGUAR3_8822E) drop unneeded firmware
and tables — an 8812AU-only rxdemo is ~1.0 MB versus ~2.6 MB with
everything on.
You own libusb: init it, open the device, detach any kernel driver, claim
interface 0 — then hand the handle to the factory. examples/rx/main.cpp is
the full boilerplate; the minimal RX path is:
auto logger = std::make_shared<Logger>();
WiFiDriver driver(logger);
auto dev = driver.CreateRtlDevice(handle); // handle is already claimed
dev->Init(packetProcessor, SelectedChannel{
.Channel = 36,
.ChannelOffset = 0,
.ChannelWidth = CHANNEL_WIDTH_20,
});packetProcessor is your void(const Packet&) callback. For TX, call
InitWrite and then send_packet(buffer, len), where the buffer starts with
a radiotap header describing how the frame should fly.
Construction-time options travel in a devourer::DeviceConfig
(src/DeviceConfig.h documents every field):
devourer::DeviceConfig cfg;
cfg.rx.keep_corrupted = true; // deliver CRC-failed frames too
auto dev = driver.CreateRtlDevice(handle, ctx, lock, cfg);Anything that changes mid-session is a runtime setter on the device:
SetTxMode, SetTxPowerOffsetQdb, SetRxPathMask, FastRetune, ...
The device class is chosen automatically from the chip behind the handle;
one IRtlDevice interface covers all three generations.
- Visual RF primer — animated intro to the concepts behind everything below.
- Adaptive link — the energy-minimizing video-link controller design, and its validation.
- Fused FEC — the cross-layer error-protection stack: per-layer PHY rates, corrupt-frame salvage, outer erasure code.
- Frequency hopping — how per-packet hopping works and what it costs on each chip.
- Startup time — devourer vs. kernel driver, measured on every supported chip.
- Adapter doctor — dying-dongle triage: EFUSE read-stability, firmware-boot and RX-smoke probes with a HEALTHY / SUSPECT / FAILING verdict.
- Spectrum sensing, spatial diversity, bench testing near-field — measurement guides for the built-in radio instrumentation.
Headless selftests run with ctest. Hardware regression is
tests/regress.py: a TX/RX matrix between devourer and the kernel driver
across plugged-in adapters, with optional full-pair, encoding-sweep, and
third-adapter-sniffer modes — see tests/README.md.
GPL-2.0. See LICENSE.