fix: use upstream dongle firmware

Use the common xow_dongle.bin image from the upstream driver for the
GUI session instead of selecting the older 02E6-specific image. Update
the firmware download script and plan to document the same upstream flow.
Keep the extended RX diagnostics used to inspect controller discovery.

Co-Authored-By: openai/gpt-5.6-luna: traced firmware and pairing behavior
This commit is contained in:
portersky
2026-08-29 12:35:50 +02:00
parent 5fd1b3a11f
commit baebcb73c2
5 changed files with 16 additions and 25 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ if(NOT CMAKE_GENERATOR MATCHES "^(Ninja|Xcode)$")
endif()
cmake_minimum_required(VERSION 3.21)
project(xone_macos VERSION 0.1.11 LANGUAGES CXX Swift)
project(xone_macos VERSION 0.1.12 LANGUAGES CXX Swift)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+4 -7
View File
@@ -40,7 +40,7 @@ User-space macOS app that speaks to the Xbox Wireless Dongle (MT76xx chip) and e
- Phase 1 (GIP + auth): ported and unit-tested.
- Phase 2 (USB transport): probe/open, async read pump, vendor requests,
bulk write. Verified on hardware.
- Phase 3 (MT76 chip): register/EFUSE access, firmware load (per-PID images),
- Phase 3 (MT76 chip): register/EFUSE access, firmware load,
radio init (registers, crystal, MAC/BSSID, channel eval, beacon). Verified
end-to-end: `radio-init` completes, beacon TX enabled, FCE shows firmware
running.
@@ -282,12 +282,9 @@ on first packet, so a fresh adapter yields its single client on demand.
Firmware binaries are downloaded from Microsoft Windows Update driver catalog:
| PID | Dongle Type | Firmware File |
| ---- | ---------------------- | -------------------- |
| 02E6 | Old dongle | xone_dongle_02e6.bin |
| 02FE | New dongle | xone_dongle_02fe.bin |
| 02F9 | Built-in (ASUS/Lenovo) | xone_dongle_02f9.bin |
| 091E | Surface Book 2 | xone_dongle_091e.bin |
| PID | Dongle Type | Firmware File |
| ---- | ---------------------- | ------------- |
| all | Supported dongles | xow_dongle.bin |
Downloaded via `scripts/download-firmware.sh` (port of `install/firmware.sh`).
+4 -8
View File
@@ -1,7 +1,6 @@
#!/bin/sh
# Download and extract the wireless dongle firmware from Windows Update.
# Port of install/firmware.sh from medusalix/xone, extended with the
# per-product split from dlundqvist/xone.
# Port of install/firmware.sh from medusalix/xone.
#
# The firmware is subject to Microsoft's Terms of Use:
# https://www.microsoft.com/en-us/legal/terms-of-use
@@ -10,10 +9,8 @@ set -eu
cd "$(dirname "$0")/.."
firmware_url_02e6='http://catalog.s.download.windowsupdate.com/d/msdownload/update/driver/drvs/2017/03/2ea9591b-f751-442c-80ce-8f4692cdc67b_6b555a3a288153cf04aec6e03cba360afe2fce34.cab'
firmware_hash_02e6='080ce4091e53a4ef3e5fe29939f51fd91f46d6a88be6d67eb6e99a5723b3a223'
firmware_url_02fe='http://download.windowsupdate.com/c/msdownload/update/driver/drvs/2017/07/1cd6a87c-623f-4407-a52d-c31be49e925c_e19f60808bdcbfbd3c3df6be3e71ffc52e43261e.cab'
firmware_hash_02fe='48084d9fa53b9bb04358f3bb127b7495dc8f7bb0b3ca1437bd24ef2b6eabdf66'
firmware_url='http://download.windowsupdate.com/c/msdownload/update/driver/drvs/2017/07/1cd6a87c-623f-4407-a52d-c31be49e925c_e19f60808bdcbfbd3c3df6be3e71ffc52e43261e.cab'
firmware_hash='48084d9fa53b9bb04358f3bb127b7495dc8f7bb0b3ca1437bd24ef2b6eabdf66'
echo "The firmware for the wireless dongle is subject to Microsoft's Terms of Use:"
echo 'https://www.microsoft.com/en-us/legal/terms-of-use'
@@ -57,5 +54,4 @@ fetch_firmware() {
echo "Firmware written to firmware/$outname"
}
fetch_firmware "$firmware_url_02e6" "$firmware_hash_02e6" xone_dongle_02e6.bin
fetch_firmware "$firmware_url_02fe" "$firmware_hash_02fe" xone_dongle_02fe.bin
fetch_firmware "$firmware_url" "$firmware_hash" xow_dongle.bin
+5 -7
View File
@@ -85,12 +85,10 @@ std::mutex session_mutex; // guards current_session
// 802.11 management frame header length (three addresses, no extensions).
constexpr std::size_t k_mgmt_hdr_len = 24;
// Select the firmware image for a product ID: firmware/xone_dongle_<pid>.bin.
auto firmware_path_for(std::uint16_t pid) -> std::string
// Upstream xone loads one common firmware image for every dongle PID.
auto firmware_path_for(std::uint16_t) -> std::string
{
char path[64];
std::snprintf(path, sizeof(path), "firmware/xone_dongle_%04x.bin", pid);
return path;
return "firmware/xow_dongle.bin";
}
} // namespace
@@ -117,9 +115,9 @@ auto xone_dongle::process_message(void const *data, std::size_t len) -> void
// Strip the header + trailer.
buf = buf.subspan(cmd_hdr_len, len - 2 * cmd_hdr_len);
char hex[64] = "";
char hex[192] = "";
int off = 0;
for (std::size_t i = 0; i < buf.size() && i < 16 && off < 48; ++i)
for (std::size_t i = 0; i < buf.size() && i < 48 && off < 144; ++i)
off += std::snprintf(hex + off, sizeof(hex) - off, "%02x ", buf[i]);
xone::log_msg(xone::log_level::debug,
"api: rx info=0x%08x port=%d len=%zu %s",
+2 -2
View File
@@ -140,9 +140,9 @@ auto main(int argc, char **argv) -> int
auto on_frame = [](std::uint8_t ep, void const *data, std::size_t len) {
auto const *p = static_cast<std::uint8_t const *>(data);
std::fprintf(stderr, "[in] ep=0x%02x len=%zu: ", ep, len);
for (std::size_t i = 0; i < len && i < 32; i++)
for (std::size_t i = 0; i < len && i < 512; i++)
std::fprintf(stderr, "%02x", p[i]);
if (len > 32)
if (len > 512)
std::fprintf(stderr, "...");
std::fprintf(stderr, "\n");
};