Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/IRtlDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,17 @@ class IRtlDevice {
* from the MAC itself. Keying on it is worse than useless — two adapters in
* one host would share state and silently apply each other's measurements.
*
* `out` receives the 6 bytes in wire order. Returns false where the chip is
* unsupported (the default), or the EFUSE value is unprogrammed/unreadable —
* callers must treat false as "no stable identity available" rather than
* substituting a weaker one silently. The default is a defined answer, not a
* silent no-op: Jaguar2 and Kestrel are expected follow-ups, not permanent
* gaps (HalMAC has the efuse APIs; EFUSE_USB_MAC_ADDR_8852B is already in
* kestrel/MacRegAx.h — each just needs a hardware-verified route here). */
* `out` receives the 6 bytes in wire order. Returns false where the EFUSE
* value is unprogrammed/unreadable — and, on any generation, possibly before
* Init/InitWrite: the EFUSE is only guaranteed readable on a brought-up chip,
* and this accessor never powers the chip on as a side effect (Kestrel serves
* the bring-up parse; the others fall back to a best-effort pre-init read
* that degrades to false on an unpowered adapter). Callers must treat false
* as "no stable identity available" rather than substituting a weaker one
* silently; for a guaranteed answer on a programmed unit, ask after bring-up.
* Implemented on every generation (per-chip offsets at each HAL's perm_mac /
* efuse parse); the interface default stays false so a future generation
* degrades gracefully rather than fabricating an identity. */
virtual bool GetPermanentMacAddress(uint8_t /*out*/[6]) { return false; }

/* Read the 64-bit hardware TSF (Timing Synchronization Function) timer — the
Expand Down
16 changes: 16 additions & 0 deletions src/jaguar2/HalJaguar2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,22 @@ uint8_t HalJaguar2::efuse_logical_byte(uint16_t off) {
return off < sizeof(_efuse_map) ? _efuse_map[off] : 0xFF;
}

bool HalJaguar2::perm_mac(uint8_t out[6]) {
constexpr uint16_t kMacOff = 0x107; /* EEPROM_MAC_ADDR_8822BU == _8821CU */
if (out == nullptr)
return false;
for (int i = 0; i < 6; ++i)
out[i] = efuse_logical_byte(kMacOff + i);
/* Unprogrammed EFUSE reads back all-0xFF; all-zero means the map was never
* read. Neither is an identity (same rule as the other generations). */
bool all_ff = true, all_zero = true;
for (int i = 0; i < 6; ++i) {
if (out[i] != 0xFF) all_ff = false;
if (out[i] != 0x00) all_zero = false;
}
return !all_ff && !all_zero;
}

uint8_t HalJaguar2::read_efuse_rfe() {
constexpr uint16_t kRfeOff = 0xCA; /* EEPROM_RFE_OPTION_8822B */
read_efuse_logical_map(_efuse_map, sizeof(_efuse_map),
Expand Down
8 changes: 8 additions & 0 deletions src/jaguar2/HalJaguar2.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ class HalJaguar2 {
* default (logical 0xB9). */
uint8_t efuse_logical_byte(uint16_t off);

/* Per-unit MAC at logical EFUSE offset 0x107 — the same offset on both dies
* (hal_pg.h: EEPROM_MAC_ADDR_8822BU == EEPROM_MAC_ADDR_8821CU; why the MAC
* is the identity key at all: IRtlDevice::GetPermanentMacAddress). Served
* from the cached logical map — a lookup post-bring-up, a real physical walk
* on a pre-init call. false when unprogrammed (all-0xFF) or unread
* (all-0x00). */
bool perm_mac(uint8_t out[6]);

/* Program the per-rate TXAGC (0x1d00 path A / 0x1d80 path B) from the EFUSE
* power-by-rate calibration for `channel` at bandwidth `bw` (0=20/1=40/2=80;
* 5/6 = 5/10 MHz narrowband, folded to the 20 MHz column — the RF runs in
Expand Down
15 changes: 15 additions & 0 deletions src/jaguar2/RtlJaguar2Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1601,6 +1601,21 @@ size_t RtlJaguar2Device::build_tx_block(const uint8_t *packet, size_t length,

SelectedChannel RtlJaguar2Device::GetSelectedChannel() { return _channel; }

bool RtlJaguar2Device::GetPermanentMacAddress(uint8_t out[6]) {
/* Under _reg_mu like every register-touching entry point: a pre-init call
* triggers the HAL's lazy logical-map walk, which is real register I/O. Any
* of those control-INs can throw on a USB glitch (rtw_read's
* std::ios_base::failure) — the contract folds that into false ("no stable
* identity available"), it must not escape from an accessor. */
std::lock_guard<std::mutex> lk(_reg_mu);
try {
return _hal.perm_mac(out);
} catch (const std::exception &e) {
_logger->warn("GetPermanentMacAddress: efuse walk failed ({})", e.what());
return false;
}
}

bool RtlJaguar2Device::StartBeacon(const uint8_t *beacon, size_t len,
int interval_tu) {
std::lock_guard<std::mutex> lk(_reg_mu);
Expand Down
2 changes: 2 additions & 0 deletions src/jaguar2/RtlJaguar2Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class RtlJaguar2Device : public IRtlDevice {
devourer::AmpduMode GetAmpduMode() override { return _ampdu; }
devourer::TxStats GetTxStats() override { return _device.GetTxStats(); }
SelectedChannel GetSelectedChannel() override;
/* EFUSE MAC at logical 0x107 (both dies — see HalJaguar2::perm_mac). */
bool GetPermanentMacAddress(uint8_t out[6]) override;
uint64_t ReadTsf() override;
void WriteTsf(uint64_t tsf) override;
bool StartBeacon(const uint8_t *beacon, size_t len, int interval_tu) override;
Expand Down
13 changes: 13 additions & 0 deletions src/kestrel/RtlKestrelDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <atomic>
#include <cstdint>
#include <cstring>
#include <optional>
#include <thread>

Expand Down Expand Up @@ -79,6 +80,18 @@ class RtlKestrelDevice : public IRtlDevice {
devourer::TxStats GetTxStats() override { return _device.GetTxStats(); }
SelectedChannel GetSelectedChannel() override { return _channel; }

/* EFUSE MAC at logical 0x488 on both dies: mac_ax's USB efuse-info dispatch
* has no 8852C entry and falls back to the 8852B table (efuse.c
* offset_usb_8852b), so one constant serves both. Served from the bring-up
* parse — false before Init/InitWrite, or when the EFUSE is unprogrammed
* (autoload_ok is exactly the all-FF / all-00 MAC check). */
bool GetPermanentMacAddress(uint8_t out[6]) override {
if (out == nullptr || !_efuse.autoload_ok)
return false;
std::memcpy(out, _efuse.mac.data(), _efuse.mac.size());
Comment thread
josephnef marked this conversation as resolved.
return true;
}

/* Static capability aggregate (resolved from chip identity; thread-safe,
* callable pre-Init). The demos emit it as the adapter.caps JSONL event. */
devourer::TxCaps GetTxCaps() override;
Expand Down
Loading