feat: port MT76 radio init and CLI tool

Complete the radio bring-up sequence: init_registers now writes the
upstream register values (PBF out of reset, beacon TX off), crystal
calibration, MAC/BSSID programming, channel evaluation, and beacon
programming through an MCU burst into PBF shared memory. The beacon
txwi is the full 20-byte struct and the RF patch is applied on the
cold firmware path.

Download firmware per product (xone_dongle_02e6.bin / 02fe.bin) and
add the xone_cli debug tool (info, firmware, radio-init/deinit, burst,
reg-read/write, led, recover). Recover uses USBDeviceReEnumerate for a
host-side port reset.

Co-Authored-By: grok4.6: internet search (firmware split, beacon SRAM, upstream issues)
Co-Authored-By: qwen3.8-27b@q2_k_xl: initial radio init and CLI implementation
Co-Authored-By: deepseek/deepseek-v4-pro-0813: final radio init fixes and verification
This commit is contained in:
portersky
2026-08-17 19:29:51 +02:00
parent 4f5f16e43f
commit c9ea1a6919
11 changed files with 1142 additions and 39 deletions
+40
View File
@@ -13,6 +13,8 @@
#include <cstddef>
#include <cstdint>
#include "mt76/mt76_defs.hpp"
namespace xone::usb {
class transport;
}
@@ -48,6 +50,25 @@ public:
// Build string of the loaded firmware image (empty until load_firmware).
auto firmware_build() const -> char const *;
// MCU commands (port of the xone_mt76_* wrappers around send_command).
auto set_led_mode(std::uint32_t mode) -> int;
auto select_function(std::uint32_t func, std::uint32_t val) -> int;
auto set_power_mode(power_mode mode) -> int;
auto load_cr(cr_mode mode) -> int;
auto write_burst(std::uint32_t idx, void *data, std::size_t len) -> int;
auto send_ms_command(ms_command cmd, void *data, std::size_t len) -> int;
auto calibrate(calibration calib, std::uint32_t val) -> int;
// Initialize the radio (port of xone_mt76_init_radio). Returns 0 or -errno.
auto init_radio() -> int;
// Suspend or resume the radio (ports of xone_mt76_suspend/resume_radio).
auto suspend_radio() -> int;
auto resume_radio() -> int;
// Enter or leave pairing mode (port of xone_mt76_set_pairing).
auto set_pairing(bool enable) -> 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.
@@ -61,8 +82,27 @@ private:
auto send_firmware(void const *fw_data, std::size_t fw_size) -> int;
auto reset_firmware() -> int;
// Radio suspend/resume steps (ports of the set_wow_* wrappers).
auto set_wow_enable(bool enable) -> int;
auto set_wow_traffic(wow_traffic traffic) -> int;
// Radio init steps (port of the xone_mt76_init_radio sub-functions).
auto init_registers() -> void;
auto calibrate_crystal() -> int;
auto init_address() -> int;
auto set_idle_time() -> int;
auto calibrate_radio() -> int;
auto get_channel_power(channel *chan) -> int;
auto switch_channel(channel const *chan) -> int;
auto evaluate_channels() -> int;
auto init_channels() -> int;
auto write_beacon(bool pair) -> int;
auto set_channel_candidates() -> int;
usb::transport &transport_;
char build_time_[17] = {};
std::array<channel, num_channels> channels_{};
channel current_channel_{};
};
} // namespace xone::mt76