dae51f085b
Port the MT76 client functions (send_wlan, associate_client, pair_client, set_client_key, remove_client) and wire the RX dispatch into the session: EP IN frames are parsed, ASSOC_REQ associates a controller (WCID plus chip programming), PAIR_REQ replies with PAIR_RESP, and DISASSOC or client-lost removes it. The C API exposes connected controllers and the app lists them by MAC. Bumps xone_cli/xone_app to C++23: they were falling back to the default standard once mt76.hpp started using std::span. Adds a unit test pinning the WCID regions, the 32-byte rxwi, and the new frame control values. Co-Authored-By: qwen3.8-27b@q2_k_xl: client functions, RX dispatch, GUI list
141 lines
5.7 KiB
C++
141 lines
5.7 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>
|
|
#include <span>
|
|
|
|
#include "mt76/mt76_defs.hpp"
|
|
|
|
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;
|
|
|
|
// 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 const *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;
|
|
|
|
// Controller association and data path (ports of the xone_mt76_* client
|
|
// functions). `addr` is a 6-byte controller MAC.
|
|
//
|
|
// send_wlan prepends a TXWI and frames the payload as an MCU message,
|
|
// then bulk-writes it to EP OUT.
|
|
auto send_wlan(std::span<std::uint8_t const> frame) -> int;
|
|
|
|
// Associate a controller: program its WCID MAC, ADD_CLIENT ms_command,
|
|
// and transmit an ASSOC_RESP mgmt frame.
|
|
auto associate_client(std::uint8_t wcid, std::span<std::uint8_t const> addr)
|
|
-> int;
|
|
|
|
// Reply to a pairing request with a PAIR_RESP mgmt frame.
|
|
auto pair_client(std::span<std::uint8_t const> addr) -> int;
|
|
|
|
// Send a reserved (0x70) management command to a client, waiting for an
|
|
// acknowledgment (port of xone_mt76_send_client_command).
|
|
auto send_client_command(std::uint8_t wcid,
|
|
std::span<std::uint8_t const> addr,
|
|
client_cmd cmd,
|
|
std::span<std::uint8_t const> data) -> int;
|
|
|
|
// Install the per-client AES-CCMP key (16 bytes) in the chip WCID
|
|
// registers (port of xone_mt76_set_client_key).
|
|
auto set_client_key(std::uint8_t wcid, std::span<std::uint8_t const> key)
|
|
-> int;
|
|
|
|
// Remove a client: REMOVE_CLIENT ms_command and zero its WCID regions
|
|
// (port of xone_mt76_remove_client).
|
|
auto remove_client(std::uint8_t wcid) -> 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;
|
|
|
|
// 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
|