portersky 0ed7a4bc3e debug: trace GIP authentication headers
Log incoming and outgoing authentication context, command, option, and
length fields to isolate the handshake failure before input reports begin.

Co-Authored-By: openai/gpt-5.6-luna: added authentication diagnostics
2026-08-29 14:13:11 +02:00
2026-08-17 14:18:03 +02:00
2026-08-29 13:36:54 +02:00
2026-08-29 13:36:54 +02:00
2026-08-29 13:36:54 +02:00
2026-08-17 14:18:03 +02:00
2026-08-29 13:36:54 +02:00

Xbox Wireless Dongle — macOS Port

User-space macOS app for the Xbox Wireless Dongle (MediaTek MT76xx). Ports the Linux kernel driver xone/ to macOS.

See PLAN.md for full architecture and implementation phases.


Building

Requires CMake ≥ 3.21, Xcode (or Command Line Tools), and Ninja. Swift is only supported by the Ninja and Xcode generators in CMake, so configure with one of them explicitly:

cmake -S . -B build -G Ninja -DBUILD_TESTING=ON
cmake --build build
./build/xone_app
cmake --build build --target check   # run the test suite

Layout (mirrors ../refix/):

  • deps/ — CMake modules: Platform.cmake, Flags.cmake, Sanitizers.cmake, FindUnity.cmake
  • src/{usb,mt76,gip,auth,hid} — C++ protocol stack (ported from medusalix/xone)
  • src/app/ — Swift app entry point + C ABI bridge (include/app/xone_api.h)
  • tests/ — Unity test suite (BUILD_TESTING=ON)

Investigation Checklist

These items need research on macOS before implementation can begin. Strike through or check off as each is resolved.

1. IOKit USB Access

  • IOUSBLib vs IOUSBFamily — Resolved: the SDK exposes only the struct-based IOUSBDeviceInterface / IOUSBInterfaceInterface (v197/v190) via IOCreatePlugInInterfaceForService() + QueryInterface. Implemented in src/usb/usb_transport.cpp.
  • USB device matching — Class match on IOUSBDevice plus a user-space VID/PID filter on the idVendor/idProduct properties (numeric registry matching proved unreliable). Verified with a physical dongle (PID 0x02E6).
  • Interface claiming — All interfaces are opened and pipes mapped by endpoint number + direction (EP 0x04 IN/OUT, EP 0x05 IN). Verified: opens cleanly with no driver conflict.
  • Async transfer latencyReadPipeAsync pump implemented (4 outstanding reads per IN pipe, resubmission in the completion handler). Latency tuning deferred to Phase 3 firmware load.
  • Device reconnect handlingkIOTerminatedNotification with a PID filter fires on unplug and chip re-enumeration. Reliability pending hardware.

2. Firmware Loading

  • Firmware binary availability — Run ../xone/install/firmware.sh (or ported scripts/download-firmware.sh) to confirm the Windows Update CAB URLs still work and firmware hashes match.
  • Firmware load sequence — Trace the Linux xone_mt76_load_firmware() flow: control request to enter firmware mode → bulk transfer in 0x3800-byte chunks → MCU completion poll → chip reset. Map each step to IOKit equivalents.
  • Post-firmware reconnect — After firmware loads, the chip resets and re-enumerates. Verify the USB device reappears with the same VID/PID and can be re-opened.

3. MT76 Register Access

  • Vendor request format — The Linux driver uses usb_control_msg() with vendor requests (bRequest 0x84/0x86 for register R/W). Confirm the exact bmRequestType, bRequest, wValue, wIndex, wLength values work via IOUSBDeviceInterface->DeviceRequest().
  • Register timing — Some register writes require delays between them. Test if usleep() in user-space provides sufficient precision, or if clock_nanosleep() is needed.
  • EFUSE read — Verify the EFUSE read sequence returns valid MAC address, chip ID, and TX power calibration data on macOS.

4. 802.11 Frame Handling

  • Beacon construction — The Linux driver builds raw 802.11 beacon frames with a Microsoft OUI (00:50:f2) information element. Verify the frame format matches what the MT76 chip expects (may include chip-specific headers before the 802.11 frame).
  • Frame encapsulation — The MT76 chip wraps 802.11 frames in a proprietary header. Reverse-engineer or confirm the header format from Linux driver source (xone_mt76_tx() / xone_mt76_rx()).
  • QoS data frames — Controller input/output uses 802.11 QoS data frames. Verify the frame construction and AES-CCMP encryption/decryption flow.

5. AES-CCMP Encryption

  • Crypto backend choice — CommonCrypto (SHA-256/HMAC), Security.framework (RSA PKCS#1), and a self-contained P-256 ECDH (no public macOS C API for EC key agreement). Implemented in src/auth/crypto.cpp.
  • CCMP mode implementation — Not needed on the host: AES-CCMP runs on the MT76 chip; the host only installs keys via WCID registers (xone_mt76_set_client_key).
  • ECDH key exchange — P-256 implemented and validated against OpenSSL-derived test vectors (tests/test_crypto.cpp).

6. Virtual HID Gamepad

  • HID Proxy Driver feasibility — Research Apple's HID Proxy Driver (DriverKit). Can we create a virtual Xbox controller that games recognize natively?
  • IOHIDDevice user-space alternative — Can we create a virtual HID device entirely in user-space? Test with IOHIDManager and see if games (Steam, Game Center) recognize it.
  • HID report descriptor — Write an Xbox 360/One-compatible HID report descriptor. Test with existing Xbox controller (via Bluetooth) to capture the exact report format macOS expects.
  • Force feedback — Can the virtual HID device receive rumble commands from games and relay them to the controller via GIP?

7. Core Audio (Headset Support)

  • Audio Unit setup — Test creating an AURenderCallback / AUOutputUnit for headset playback and AURecordingCallback / AUInputUnit for mic input.
  • Latency requirements — The GIP protocol sends audio in 8ms intervals. Can Core Audio maintain this latency without glitches?
  • Format negotiation — The headset negotiates audio format (sample rate, channels) via GIP. Map GIP audio formats to Core Audio AudioStreamBasicDescription.

8. Build System

  • CMake vs Xcode — CMake is simpler for the C library portions, but Xcode is needed for the macOS app bundle and any DriverKit extension. Decide on primary build system.
  • Minimum macOS version — Target 12.0 (Monterey) for modern IOKit/DriverKit. Verify all APIs are available.
  • Code signing — IOKit USB access may require specific entitlements (com.apple.kpi.iokit, com.apple.security.device.usb). DriverKit requires notarization. Plan for development vs distribution signing.
  • 5GHz channel restrictions — macOS enforces regulatory domain for 5GHz. The dongle may try to use channels blocked in the current region. May need to limit to 2.4GHz only or find a way to override.
  • Firmware license — The firmware binaries are from Microsoft Windows Update. Confirm they can be redistributed with the macOS port (the Linux driver includes them with a disclaimer).

10. Testing Hardware

  • Dongle — Xbox Wireless Dongle (PID 0x02FE preferred, 0x02E6 also works)
  • Controller — Xbox One or Series X|S controller (for pairing and input testing)
  • Headset — Xbox Wireless Headset (optional, for audio testing)
  • macOS machine — Intel or Apple Silicon (test both if possible, IOKit may differ)

Quick Reference

Linux API macOS Replacement Status
usb_control_msg() IOUSBDeviceInterface->DeviceRequest() Done (send_vendor_request)
usb_bulk_msg() WritePipe() / ReadPipeAsync() Done (bulk_write, reader thread)
usb_submit_urb() ReadPipeAsync() + CFRunLoopSource Done (reader thread)
kzalloc / kfree malloc / free Straightforward
spin_lock_irqsave std::mutex / std::condition_variable Done (usb_transport.cpp)
msleep / mdelay usleep() / clock_nanosleep() ☐ Test timing
crypto_shash_* CommonCrypto / Security.framework Done (auth/crypto.cpp)
input_register_device() HID Proxy Driver / IOHIDSystem ☐ Investigate
snd_pcm_* Core Audio (Audio Units) ☐ Investigate
request_firmware() File I/O (fopen/fread) Straightforward
cfg80211_* Nothing (no regulatory reporting) Remove
bus_register() Custom client management Redesign
device_create() / sysfs Nothing (no sysfs) Remove

First Steps on macOS

  1. Plug in the dongle, run system_profiler SPUSBDataType — confirm it's detected
  2. Check log show --predicate 'subsystem == "com.apple.iokit"' — see if macOS loads any driver
  3. Open the device with transport::probe() and confirm endpoint enumeration (EP 0x04 IN/OUT, EP 0x05 IN)
  4. Try a vendor control request (register read) to verify USB communication works
  5. Attempt firmware load with the binary from firmware/ directory
S
Description
No description provided
Readme 648 KiB
Languages
C++ 86.7%
Swift 8.3%
CMake 2.9%
C 1.5%
Shell 0.6%