Skip to content

DeviceConfig — env-free library, config struct at the factory#208

Merged
josephnef merged 1 commit into
masterfrom
device-config
Jul 7, 2026
Merged

DeviceConfig — env-free library, config struct at the factory#208
josephnef merged 1 commit into
masterfrom
device-config

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

What

The library read 46 distinct DEVOURER_* environment variables at 72 call sites to select runtime behaviour — bring-up gates, beamforming arming, calibration skips, debug dumps, USB tuning. A library should not read CLI env vars to decide its behaviour; consumers get an explicit API instead.

src/DeviceConfig.h — construction-time configuration struct (rx / tx / bf / tuning / debug / usb sections), passed as CreateRtlDevice's defaulted fourth argument, so existing callers compile unchanged:

devourer::DeviceConfig cfg;
cfg.rx.keep_corrupted = true;      // FCS-failed frames to host
cfg.bf.arm_sounder = true;         // beamformer sounding engine
cfg.debug.log_writes = true;       // <wlog> register-write trace
auto dev = driver.CreateRtlDevice(handle, ctx, lock, cfg);

Every field is doc-tagged with its env-var spelling and value grammar. A MacAddr POD + parse_mac() replaces four copies of inline sscanf MAC parsing. Knobs that change mid-session remain runtime setters on IRtlDevice (SetTxMode, SetTxPowerOffsetQdb, SetRxPathMask, SetCcaMode, ...).

Plumbing — each component (EepromManager, RadioManagementModule, HalModule, FirmwareManager, HalJaguar2, HalJaguar3, RadioManagementJaguar3, Halrf8822e, RtlUsbAdapter, HopProf, ToneMask) takes the config at construction. Static-cached getenv lambdas (TX_EP, TX_TIMEOUT_MS, LOG_WRITES, TX_NDPA) become plain members — per-process knobs become per-device. parse_tx_mode_env leaves the library; BfReportDetect.h (demo-side per-packet debug hook) moves to examples/common/; the TMPDIR read in UsbDeviceLock becomes usb.lock_dir.

examples/common/env_config.{h,cpp} — the demos' env translator: every library-level DEVOURER_* var maps onto a DeviceConfig field there, so all env-driven test scripts run unchanged. The gate holds: grep -rn getenv src/ hal/ returns nothing.

Semantic note: per-channel-set re-read knobs (DUMP_CANARY, SKIP_TXPWR, FORCE_IQK, ...) are fixed at construction. Scripts export env before launch, so none break.

Validation

  • Full all-chips build + two gated per-chip configs; ctest green on each
  • txpwr_offset_regcheck: 49 PASS / 0 FAIL — bring-up register canary byte-identical to master on all 7 plugged DUTs (8812AU, 8821AU, 8814AU, 8822BU, 8811CU, 8822CU, 8812EU), the key no-regression invariant
  • On-air d/d cell 8100/8000 hits (8822CU→8812EU, ch36)
  • tone_mask_regcheck 6/6 (CSI mask + NBI land on every generation incl. 80 MHz)
  • rx_path_mask_check 2/2 (mask spec incl. toggle grammar; functional + sticky)
  • Jaguar2 single-radio BF self-sounding: 85k self-captured reports, armed 880 vs unarmed 0 (exercises enable_with_tx + sounder + NDPA in one process)
  • DEVOURER_HOP_PROF emits per-hop lines with the flag, silent without

The regcheck's first run caught a real bug this PR also fixes: RtlJaguarDevice initialised _eepromManager/_radioManagement from _cfg before _cfg's declaration-order construction (UB, flaky per-process). _cfg is now declared first, with a comment pinning the ordering contract.

🤖 Generated with Claude Code

The library read 46 distinct DEVOURER_* environment variables at 72 call
sites to select runtime behaviour (bring-up gates, beamforming arming,
calibration skips, debug dumps, USB tuning). A library must not read CLI
env vars; consumers get an explicit API instead:

- src/DeviceConfig.h — construction-time config struct (rx / tx / bf /
  tuning / debug / usb sections, every field doc-tagged with its env-var
  spelling and value grammar), passed as CreateRtlDevice's defaulted
  fourth argument. Includes a MacAddr POD + parse_mac() that replaces the
  per-site sscanf MAC parsing.
- Every component (EepromManager, RadioManagementModule, HalModule,
  FirmwareManager, HalJaguar2, HalJaguar3, RadioManagementJaguar3,
  Halrf8822e, RtlUsbAdapter, HopProf, ToneMask) takes the config at
  construction; static-cached getenv lambdas become plain members
  (per-process knobs become per-device — strictly more correct).
- parse_tx_mode_env moves out of the library; BfReportDetect.h (a
  demo-side per-packet debug hook) moves to examples/common/.
- The TMPDIR read in UsbDeviceLock becomes usb.lock_dir, threaded through
  claim_interface_then_reset.
- examples/common/env_config.{h,cpp} — the demos' env translator: every
  DEVOURER_* var maps onto DeviceConfig there, so all env-driven test
  scripts run unchanged. grep getenv src/ hal/ returns nothing.

Semantic change: per-channel-set re-read knobs (DUMP_CANARY, SKIP_TXPWR,
FORCE_IQK, ...) are fixed at construction; scripts export before launch,
so none break.

Validated: full + gated builds, ctest 10/10; on-air d/d 8100/8000
(8822CU->8812EU ch36); tone_mask_regcheck 6/6; rx_path_mask_check 2/2;
txpwr_offset_regcheck 49 PASS / 0 FAIL with the bring-up canary
byte-identical to master on all 7 plugged DUTs; Jaguar2 single-radio BF
self-sounding 85k reports (armed 880 vs unarmed 0); HOP_PROF emits with
the flag and stays silent without. The regcheck's first run caught a real
bug — RtlJaguarDevice initialised _eepromManager/_radioManagement from
_cfg before _cfg's declaration-order construction (UB) — fixed by
declaring _cfg first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@josephnef josephnef merged commit 645eed0 into master Jul 7, 2026
15 checks passed
@josephnef josephnef deleted the device-config branch July 7, 2026 04:34
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