Skip to content

rtl8733b: add RTL8731BU/RTL8733BU USB RX and TX - #388

Draft
snokvist wants to merge 5 commits into
OpenIPC:masterfrom
snokvist:rtl8733bu-support
Draft

rtl8733b: add RTL8731BU/RTL8733BU USB RX and TX#388
snokvist wants to merge 5 commits into
OpenIPC:masterfrom
snokvist:rtl8733bu-support

Conversation

@snokvist

Copy link
Copy Markdown
Contributor

Summary

Adds a dedicated userspace HALMAC 87xx backend for the RTL8731BU/RTL8733BU Wi-Fi function.

  • Recognizes vendor USB IDs 0bda:f72b and 0bda:b733, while requiring live RTL8733B chip ID 0x16.
  • Implements card power sequencing, cut-selected firmware boot, HALMAC/MAC and EFUSE setup, generated BB/RF/RFK tables, dual-band channel setup, monitor RX, raw TX, thermal telemetry and safe teardown.
  • Advertises the hardware-tested surface only: 1x1 legacy OFDM + HT MCS0-7, BCC, 20/40 MHz, 2.4/5 GHz.
  • Adds reproducible, hash-pinned firmware/table extraction, parser/descriptor/EFUSE/table self-tests, rtl8733bprobe, adapter-doctor integration and capability documentation.
  • Integrates RTL8733B with the new cross-generation rx.parse_abort telemetry added in rx.parse_abort: count the abandoned-aggregate RX loss on every generation #387.

This progresses the USB-first portion of #233. It does not auto-close that issue because narrowband RF validation and combo-module/coexistence work remain outside this PR.

Why a separate backend

RTL8733B is HALMAC 87xx, not a Jaguar2/3 variant. Its power, firmware, MAC, RX/TX descriptor and PHY paths therefore remain isolated under src/rtl8733b/.

Both reviewed vendor trees describe this device as 1SS 802.11b/g/n with a 20/40 MHz capability mask. The 2024 tree also contains a later Fix VHT flags commit that removes the accidentally enabled VHT flag. This PR consequently does not adopt #233's provisional VHT/80 MHz/2T2R assumptions.

Firmware and tables are pinned to libc0607/rtl8733bu-20230626 commit 9e5f6845b4e3393207720fc1886668bc80b6af1c. The implementation was compared with libc0607/rtl8733bu-20240806 commit 2ec19e154cffbc2abd98d43d59278dffa6e50d49, but the already hardware-validated artifacts were not silently replaced.

Hardware tested

Test device: one 0bda:f72b, RTL8733B cut D, USB high speed.

Verified through the normal WiFiDriver / IRtlDevice path:

  • USB discovery/endpoints, repeated power/firmware/MAC/BB/RF bring-up, stable EFUSE reads and permanent MAC extraction.
  • Ambient monitor RX on channels 6 and 36, descriptor aggregation, PHY status, CRC reporting and clean stop.
  • Raw TX captured by an independent receiver on both bands: legacy OFDM and HT MCS0-7 at 20 MHz, plus HT 40 MHz. BCC was forced throughout.
  • Warm reinitialization, concurrent RX/TX, bounded sustained TX, malformed-input rejection, teardown during active work and post-run health checks.
  • Current post-rebase smoke: 10 sampled ambient packets and 0 rx.parse_abort events in 10 seconds.
  • Current adapter-doctor run: HEALTHY; 4/4 identical EFUSE reads, firmware ready, 23 clean + 6 corrupt frames in 3 seconds.
  • Final explicit card-disable readback: RF_CTRL=0x00, CR=0xea.

Checks

  • Full default build: passed.
  • Full CTest matrix: 53/53 passed.
  • RTL8733B-only build (all other chip options disabled): passed.
  • RTL8733B-only CTest matrix: 49/49 passed.
  • Firmware extractor --check: reproduced both checked-in NIC images byte-for-byte.
  • Table extractor --check: reproduced all checked-in MAC/BB/AGC/RF/RFK arrays byte-for-byte.
  • Rebased onto current OpenIPC/devourer:master (da06ccc) before the final build and hardware smoke.

Explicitly not tested or claimed

  • No SDR equipment was available. Occupied bandwidth, spectral mask, EVM, absolute output power and SDR duty measurements were not performed.
  • Experimental 5/10 MHz has register-readback and normal-path RX evidence only. Narrowband TX and independent narrowband-peer decode are deferred; narrowband_ok remains false.
  • No physical 0bda:b733 combo module was available. Its ID is from the vendor table; Bluetooth/coexistence is not implemented or claimed.
  • SGI, STBC, LDPC, CCK TX, VHT, 80 MHz, ACK/BlockAck, A-MPDU, fast retune and throughput are not claimed.
  • The hub cannot switch VBUS, so automated repeated true-cold boots were not possible; physical replug and warm reinitialization were tested.
  • A vendor-kernel-driver cross-test was attempted with the 2024 tree on Linux 6.14. Its build first omitted required include paths, then failed on incompatible MODULE_IMPORT_NS syntax and missing platform_ops.h. No vendor module was loaded, so no vendor-driver parity result is claimed.
  • An RTL8731BU-labelled f72b passed early identity/EFUSE/firmware checks, but later stopped enumerating and overheated while attached to a custom power supply. It is excluded from all radio-validation claims.

The full tested/deferred matrix and provenance are in docs/rtl8733b.md.

@snokvist

Copy link
Copy Markdown
Contributor Author

/review

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 10, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (2) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Rtl8733b omits 5/10 MHz 📎 Requirement gap ≡ Correctness
Description
RTL8733B capability reporting currently excludes 5/10 MHz narrowband (and does not advertise
FastRetune), contrary to the narrowband/FastRetune requirement. This prevents the expected
narrowband long-range mode from being enabled/verified through the normal capability surfaces.
Code

src/AdapterCaps.h[R83-86]

+  return g == ChipGeneration::Rtl8733b ? (kBw20 | kBw40)
+         : g == ChipGeneration::Jaguar1  ? ac
       : g == ChipGeneration::Unknown ? 0
                                      : (ac | kBw5 | kBw10);
Evidence
PR Compliance ID 7 expects RTL8733B narrowband 5/10 MHz support (and FastRetune). The PR sets
RTL8733B bandwidth mask to only 20/40 MHz, and GetTxCaps() explicitly documents that 5/10 MHz is
omitted; no RTL8733B caps path marks FastRetune as supported.

Implement narrowband 5/10 MHz support and FastRetune (M4 gate)
src/AdapterCaps.h[77-86]
src/rtl8733b/Rtl8733bDevice.cpp[529-536]
src/AdapterCaps.h[213-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
PR Compliance ID 7 requires RTL8733B narrowband 5/10 MHz support plus FastRetune behavior. Current RTL8733B capability reporting excludes 5/10 MHz and does not surface FastRetune support, so narrowband cannot be enabled/validated via the standard capability path.
## Issue Context
- `bw_mask_for_generation(ChipGeneration::Rtl8733b)` currently returns only 20/40.
- `Rtl8733bDevice::GetTxCaps()` explicitly states 5/10 MHz is omitted.
- `AdapterCaps::fastretune_ok` remains at its default (`false`) for RTL8733B.
## Fix Focus Areas
- src/AdapterCaps.h[77-86]
- src/rtl8733b/Rtl8733bDevice.cpp[529-559]
- src/AdapterCaps.h[213-218]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. GetAdapterCaps leaves narrowband_ok false 📎 Requirement gap ≡ Correctness
Description
RTL8733B GetAdapterCaps() does not set narrowband_ok (or fastretune_ok) and hard-codes chain
counts rather than runtime-detecting them, which violates the RTL8733B adapter capability reporting
requirement. This causes demos/telemetry to misrepresent RTL8733B feature availability.
Code

src/rtl8733b/Rtl8733bDevice.cpp[R548-551]

+  caps.tx_chains = 1;
+  caps.rx_chains = 1;
+  caps.tx = GetTxCaps();
+  caps.bw_mask = devourer::bw_mask_for_generation(caps.generation);
Evidence
PR Compliance ID 8 requires RTL8733B capability reporting (including narrowband capability and
correct feature flags). In the added RTL8733B backend, GetAdapterCaps() never assigns
narrowband_ok/fastretune_ok (so they remain false per the struct defaults) and sets chain
counts as fixed constants rather than runtime-derived.

Adapter capabilities reporting for RTL8733B (identity and feature flags)
src/rtl8733b/Rtl8733bDevice.cpp[539-559]
src/AdapterCaps.h[213-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
PR Compliance ID 8 requires RTL8733B `AdapterCaps` to correctly surface identity and feature flags, including narrowband capability, and to avoid misreporting RF chain capabilities.
## Issue Context
- `AdapterCaps::narrowband_ok` and `AdapterCaps::fastretune_ok` default to `false`.
- `Rtl8733bDevice::GetAdapterCaps()` populates identity/bands/`bw_mask`, but does not set `narrowband_ok`/`fastretune_ok` and hard-codes `tx_chains`/`rx_chains`.
## Fix Focus Areas
- src/rtl8733b/Rtl8733bDevice.cpp[539-559]
- src/AdapterCaps.h[118-120]
- src/AdapterCaps.h[213-218]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. UB shift in txdesc ✓ Resolved 🐞 Bug ≡ Correctness
Description
rtl8733b::txdesc_set_bits uses (1u << width) which is undefined behavior for width==32, so encoding
a 32-bit field would produce unpredictable masks and corrupt the TX descriptor. Because this helper
is header-only and reusable, a future call site can trigger this silently.
Code

src/rtl8733b/TxDescriptor8733b.h[R47-50]

+inline void txdesc_set_bits(uint8_t *p, unsigned bit, unsigned width,
+                            uint32_t value) {
+  const uint32_t field = ((1u << width) - 1u) << bit;
+  txdesc_write_le32(p, (txdesc_le32(p) & ~field) |
Evidence
The TX helper computes its mask via 1u << width without guarding width == 32, which is UB. The
nearby RTL8733B RX helper (rx_bits) explicitly special-cases width == 32, demonstrating the
expected safe handling pattern in this repo.

src/rtl8733b/TxDescriptor8733b.h[47-52]
src/rtl8733b/FrameParser8733b.h[21-25]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`txdesc_set_bits()` builds its bitmask with `1u << width`; when `width == 32` this is undefined behavior in C/C++ and can generate an incorrect mask/descriptor.
### Issue Context
The RTL8733B TX descriptor encoder is intended to be a generic bitfield writer; the RX-side helper already special-cases `width == 32`, suggesting 32-bit fields are a known boundary in this codebase.
### Fix Focus Areas
- src/rtl8733b/TxDescriptor8733b.h[47-52]
### Suggested fix
- Special-case `width == 32` (and validate `bit == 0`) or compute the mask using a 64-bit intermediate (`1ull << width`) and validate `bit + width <= 32` before shifting.
- Consider explicitly handling `width == 0` as a no-op to avoid accidental full-clear patterns.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. RX malformed counter misleading ✓ Resolved 🐞 Bug ◔ Observability
Description
Rtl8733bDevice increments malformed on any RX parse failure even when the remainder is all-zero
padding (which emit_rx_parse_abort explicitly treats as benign). This inflates/poisons the RX
summary counters and makes troubleshooting RX parser regressions harder.
Code

src/rtl8733b/Rtl8733bDevice.cpp[R181-184]

+                                    frame)) {
+        ++malformed;
+        devourer::emit_rx_parse_abort(
+            _logger->events(), data + offset,
Evidence
The RX loop counts every parse failure as malformed. However, emit_rx_parse_abort explicitly
excludes all-zero remainder padding, and parse_rx_8733b returns false when frame_len==0—the
decode result you’d get from a zero-filled padded descriptor region—so benign padding can be counted
as malformed.

src/rtl8733b/Rtl8733bDevice.cpp[170-188]
src/RxParseAbort.h[4-10]
src/RxParseAbort.h[19-37]
src/rtl8733b/FrameParser8733b.h[96-103]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The RX loop increments the `malformed` counter before determining whether the parse failure is a real abort or just benign all-zero aggregate padding.
### Issue Context
`emit_rx_parse_abort()` is explicitly designed to suppress events for all-zero remainder padding. Separately, `parse_rx_8733b()` returns `false` when `frame_len == 0`, which is exactly what an all-zero padded “descriptor” would decode as.
### Fix Focus Areas
- src/rtl8733b/Rtl8733bDevice.cpp[170-189]
- src/rtl8733b/FrameParser8733b.h[96-103]
- src/RxParseAbort.h[19-37]
### Suggested fix
- Before incrementing `malformed`, detect the benign-padding case (all-zero remainder) and break without counting it as malformed.
- Alternatively, restructure as:
- detect `all_zero` remainder locally (even when event sink is disabled),
- only then increment `malformed` + emit `rx.parse_abort` for non-zero remainder.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can reply 'qodo' on any finding to push back, ask questions, or dig deeper

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/AdapterCaps.h
Comment thread src/rtl8733b/Rtl8733bDevice.cpp
Comment thread src/rtl8733b/TxDescriptor8733b.h
Comment thread src/rtl8733b/Rtl8733bDevice.cpp Outdated
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