Files
xone_macos/include/mt76/mt76.hpp
T
portersky 21dc0e09b3 feat: port MT76 firmware load and download script
Add chip::load_firmware(): validates the xow_dongle.bin header, DMAs
the ILM and DLM images in 0x3800-byte chunks over EP 0x04 OUT with
FCE completion polling, then loads the IVB and waits for the firmware
to start. Probe now issues a USB reset first (port of
usb_reset_device), matching xone_dongle_probe.

The chip keeps its firmware across a USB reset on macOS and does not
set the upstream reset-complete bit, so load_firmware falls back to
the running firmware when the chip is still alive. Verified on
hardware: fresh load and re-plug both return success.

Add scripts/download-firmware.sh (port of install/firmware.sh), which
fetches the driver CAB from Windows Update and extracts
firmware/xow_dongle.bin, hash-verified.

Co-Authored-By: qwen3.8-27b@q2_k_xl: ported firmware load and download script
2026-08-17 16:43:52 +02:00

65 lines
2.5 KiB
C++

#pragma once
// ==============================================================================
// MT76 chip protocol (MediaTek MT76xx radio in the dongle)
// ==============================================================================
// Port target: medusalix/xone transport/mt76.c + mt76.h + mt76_defs.h.
// Firmware load (0x3800-byte chunks), EFUSE read, radio init (~80 register
// writes), channel evaluation, beacon transmission, pairing mode, client
// association and WCID/AES-CCMP key setup (encryption runs on-chip).
// ==============================================================================
#include <array>
#include <cstddef>
#include <cstdint>
namespace xone::usb {
class transport;
}
namespace xone::mt76 {
// Owns the MT76 chip protocol on top of an open USB transport. Port of
// struct xone_mt76 plus the register/EFUSE layer of transport/mt76.c.
class chip {
public:
explicit chip(usb::transport &transport);
// 32-bit register read/write (addr may include mt_vend_type_cfg).
auto read_register(std::uint32_t addr) -> std::uint32_t;
auto write_register(std::uint32_t addr, std::uint32_t val) -> void;
// Poll until (read_register(offset) & mask) == val. False on timeout.
auto poll(std::uint32_t offset, std::uint32_t mask, std::uint32_t val) -> bool;
// Read EFUSE bytes at the 16-bit block address. Returns 0 or -errno.
auto read_efuse(std::uint16_t addr, void *data, std::size_t len) -> int;
// Chip ID from EFUSE (e.g. MT7612). 0 on failure.
auto chip_id() -> std::uint16_t;
// MAC address from EFUSE with the 62:45:bd fallback applied.
auto mac_address() -> std::array<std::uint8_t, 6>;
// Load the firmware image from a file (port of xone_mt76_load_firmware).
// Resets the MCU if firmware is already loaded. Returns 0 or -errno.
auto load_firmware(char const *path) -> int;
private:
// Send an MCU command (port of xone_mt76_send_command). `cmd` is the
// MT_MCU_MSG_CMD_TYPE field. Returns bytes written, or a negative errno.
auto send_command(std::uint32_t cmd, void const *payload,
std::size_t payload_len) -> int;
// Firmware load steps (port of xone_mt76_*).
auto load_ivb() -> int;
auto send_firmware_part(std::uint32_t offset, void const *data,
std::size_t len) -> int;
auto send_firmware(void const *fw_data, std::size_t fw_size) -> int;
auto reset_firmware() -> int;
usb::transport &transport_;
};
} // namespace xone::mt76