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
+78
View File
@@ -43,11 +43,89 @@ void test_firmware_layout(void)
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_fce_dma_len, 0x0234);
}
// Pin the MCU command layer to transport/mt76_defs.h values.
void test_mcu_commands(void)
{
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::mcu_cmd::cmd_fun_set_op), 1);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::mcu_cmd::cmd_burst_write), 8);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::mcu_cmd::cmd_power_saving_op), 20);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::mcu_cmd::cmd_switch_channel_op), 30);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::power_mode::radio_off), 0x30);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::power_mode::radio_on), 0x31);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::ms_command::ms_set_mac_address),
0x00);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(xone::mt76::ms_command::ms_set_idle_time), 0x05);
TEST_ASSERT_EQUAL_UINT32(
static_cast<std::uint32_t>(
xone::mt76::ms_command::ms_set_chan_candidates), 0x07);
}
// Pin the radio init register addresses to transport/mt76_defs.h values.
void test_radio_registers(void)
{
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_mac_sys_ctrl, 0x1004);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_usb_dma_cfg, 0x0238);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_edca_cfg_ac(2), 0x1308);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_bbp_agc(1), 0x2304);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_beacon_time_cfg, 0x1114);
TEST_ASSERT_EQUAL_UINT32(
xone::mt76::mt_beacon_time_cfg_beacon_tx,
static_cast<std::uint32_t>(xone::mt76::bit(20)));
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_mcu_memmap_wlan, 0x410000);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_mac_addr_dw0, 0x1008);
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_mac_bssid_dw0, 0x1010);
}
// Pin the channel table to transport/mt76.c values.
void test_channel_table(void)
{
using namespace xone::mt76;
TEST_ASSERT_EQUAL_UINT32(num_channels, 12);
TEST_ASSERT_EQUAL_UINT8(channels[0].index, 0x01);
TEST_ASSERT_EQUAL_UINT8(channels[0].bandwidth,
static_cast<std::uint8_t>(phy_bandwidth::bw_20));
TEST_ASSERT_TRUE(channels[0].scan);
TEST_ASSERT_EQUAL_UINT8(channels[3].index, 0x24);
TEST_ASSERT_EQUAL_UINT8(channels[3].group,
static_cast<std::uint8_t>(cal_channel_group::ch_5g_unii_1));
TEST_ASSERT_EQUAL_UINT8(channels[7].index, 0x95);
TEST_ASSERT_EQUAL_UINT8(channels[7].bandwidth,
static_cast<std::uint8_t>(phy_bandwidth::bw_80));
TEST_ASSERT_EQUAL_UINT8(channels[11].index, 0xa5);
TEST_ASSERT_FALSE(channels[11].scan);
}
// Pin the beacon frame layout to transport/mt76.c values.
void test_beacon_layout(void)
{
TEST_ASSERT_EQUAL_UINT32(xone::mt76::mt_beacon_base, 0xc000);
TEST_ASSERT_EQUAL_UINT16(xone::mt76::ieee80211_fc_beacon, 0x0080);
TEST_ASSERT_EQUAL_UINT32(
xone::mt76::field_prep(xone::mt76::mt_rxwi_rate_phy,
static_cast<std::uint32_t>(
xone::mt76::phy_type::phy_ofdm)),
0x2000u);
TEST_ASSERT_EQUAL_UINT8(xone::mt76::mt_txwi_ack_ctl_nseq, 0x02);
TEST_ASSERT_EQUAL_UINT32(sizeof(xone::mt76::broadcast_address), 6);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_bitfield_helpers);
RUN_TEST(test_efuse_registers);
RUN_TEST(test_firmware_layout);
RUN_TEST(test_mcu_commands);
RUN_TEST(test_radio_registers);
RUN_TEST(test_channel_table);
RUN_TEST(test_beacon_layout);
return UNITY_END();
}