Commit Graph

16 Commits

Author SHA1 Message Date
portersky 5fd1b3a11f feat: pairing mode and RX frame logging
The dongle beacon carries a pairing flag in the Microsoft OUI IE; with
it clear, controllers ignore the beacon. Port xone_dongle_toggle_pairing:
xone_set_pairing() rewrites the beacon with the flag set and blinks the
LED, the GUI button triggers it, EVT_BUTTON (dongle button) does too, and
the LED follows upstream state (blink while pairing, on when a controller
is connected, off otherwise). The CLI gains a pair command.
Log every inbound frame (info word + first 16 bytes) so the RX path can
be traced against hardware.

Co-Authored-By: qwen3.8-27b@q2_k_xl: pairing mode and RX logging
2026-08-29 13:36:54 +02:00
portersky dae51f085b feat: pair controllers and show them in the app
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
2026-08-29 13:36:32 +02:00
portersky b3e747b900 feat: async C API and Swift radio state display
Split the dongle session into a fast probe (xone_open) and a background
start (xone_start) that loads the firmware and initializes the radio on
a worker thread, so the app UI never blocks. Add xone_state/xone_error
for progress display, and select the firmware image per product ID when
no path is given. The Swift app polls the state each second and shows
idle/starting/ready/error plus the firmware build or error string.

The session destructor joins the worker so quitting the app does not
terminate on a joinable thread. Note in the CLI and transport that the
recover/re-enumerate path should not be used yet: a crashed SIE drops
off the bus, while the MCU watchdog recovers it after ~90s of quiet.

Co-Authored-By: qwen3.8-27b@q2_k_xl: async C API, Swift state display, and exit-time worker join
2026-08-17 19:57:40 +02:00
portersky c9ea1a6919 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
2026-08-17 19:29:51 +02:00
portersky 4f5f16e43f feat: expose dongle debug info through the C API
Add an opaque xone_dongle session handle to the C ABI bridge:
xone_open() probes, resets, and loads the firmware (path optional),
and xone_pid/xone_chip_id/xone_mac_address/xone_firmware_build return
debug info for the open session. chip captures the firmware build
string from the image header during load.

The Swift app opens a session when the dongle appears and shows PID,
chip ID, MAC address, and firmware build string in a debug section.

Co-Authored-By: qwen3.8-27b@q2_k_xl: added C API session handle and debug UI
2026-08-17 16:44:02 +02:00
portersky 21dc0e09b3 feat: port MT76 firmware load and download script
Add chip::load_firmware(): validates the xow_dongle.bin header, DMAs
the ILM and DLM images in 0x3800-byte chunks over EP 0x04 OUT with
FCE completion polling, then loads the IVB and waits for the firmware
to start. Probe now issues a USB reset first (port of
usb_reset_device), matching xone_dongle_probe.

The chip keeps its firmware across a USB reset on macOS and does not
set the upstream reset-complete bit, so load_firmware falls back to
the running firmware when the chip is still alive. Verified on
hardware: fresh load and re-plug both return success.

Add scripts/download-firmware.sh (port of install/firmware.sh), which
fetches the driver CAB from Windows Update and extracts
firmware/xow_dongle.bin, hash-verified.

Co-Authored-By: qwen3.8-27b@q2_k_xl: ported firmware load and download script
2026-08-17 16:43:52 +02:00
portersky ccc5bc819d feat: port MT76 register and EFUSE access
Add the mt76::chip class on top of the USB transport: 32-bit register
read/write via vendor requests, register polling, and EFUSE reads with
the kick/control sequence from transport/mt76.c. Expose chip_id() and
mac_address() (with the 62:45:bd fallback).

Verified on hardware: chip ID 0x7612 (MT7612) and MAC address read
from EFUSE.

Co-Authored-By: qwen3.8-27b@q2_k_xl: ported register and EFUSE layer
2026-08-17 16:15:56 +02:00
portersky c32976b69d docs: mark USB matching and claiming hardware-verified
Discovery, interface claiming, and vendor control requests are confirmed
working on a physical dongle (PID 0x02E6, MT7612 chip). Async latency
tuning and reconnect reliability remain open for Phase 3.

Co-Authored-By: qwen3.8-27b@q2_k_xl: verified transport on hardware
2026-08-17 16:06:53 +02:00
portersky aab44fd7aa fix: use class matching and double-pointer refs
IOServiceMatching on idVendor/idProduct numbers is unreliable (single-key
matches fail), so match the IOUSBDevice class and filter VID/PID in user
space via the idVendor/idProduct properties.

QI'd interfaces are double-pointer references: *ref is the interface
struct and methods are called as (*ref)->Method(ref, ...). The old code
treated the slot as the struct and crashed on the first method call.

Verified on a physical dongle (PID 0x02E6): probe opens the device,
enumerates EP 0x04 IN/OUT and EP 0x05 IN, and register reads via
DeviceRequest return valid values (MT7612 ASIC version).

Co-Authored-By: qwen3.8-27b@q2_k_xl: fixed USB transport for hardware
2026-08-17 16:06:53 +02:00
portersky 4f0f1ff75d feat: add IOKit-based USB transport
Replace the stub probe with a real IOKit/IOUSBFamily transport:
discovery by VID/PID, device and interface connections, vendor
control requests on EP0, bulk writes to EP 0x04 OUT, and an async
read pump (EP 0x05 IN / EP 0x04 IN) on a dedicated CFRunLoop
thread with disconnect notification.

Add the test_usb suite, link IOKit/CoreFoundation into xone_usb,
and update the README investigation checklist.

Co-Authored-By: qwen3.8-27b@q2_k_xl: implemented USB transport layer
2026-08-17 15:52:22 +02:00
portersky 5a102bb511 docs: mark crypto checklist items resolved
Update the AES-CCMP investigation checklist and quick reference to
reflect the completed crypto backend choice, on-chip CCMP, and validated
P-256 ECDH.

Co-Authored-By: deepseek (deepseek/deepseek-v4-pro-0813): updated crypto docs
2026-08-17 15:05:08 +02:00
portersky 0f85b59237 feat: add SwiftUI app shell
Replace the command-line entry point with a windowed SwiftUI app
showing live dongle status, a controller placeholder, and a pair button.
The app runs as a regular foreground app even when launched directly
from the build directory.

Co-Authored-By: deepseek (deepseek/deepseek-v4-pro-0813): built SwiftUI app shell
2026-08-17 15:04:59 +02:00
portersky 2d4366f454 feat: port GIP protocol and auth stack
Port the GIP protocol and authentication layers from medusalix/xone
into the C++ stack:

- crypto: SHA-256/HMAC (CommonCrypto), RSA PKCS#1 (Security.framework),
  and a self-contained P-256 ECDH validated against OpenSSL vectors
- auth: v1 (RSA) and v2 (ECDH) handshake state machine
- gip: header/varint/chunk handling and packet dispatch, with the kernel
  device model replaced by transport + client_listener interfaces

Adds test_crypto, test_auth, and test_gip suites.

Co-Authored-By: deepseek (deepseek/deepseek-v4-pro-0813): ported crypto, auth, and GIP
2026-08-17 15:04:44 +02:00
portersky 95e958a7e8 docs: add AGENTS.md coding conventions
Adapt the refix AGENTS.md to this project: build commands, module
layout, C++/Swift/C-bridge style rules, and commit guidelines. C++
headers use .hpp and C headers use .h; the PLAN.md port table is
updated to match.

Co-Authored-By: qwen (qwen/qwen3.8-27b@q2_k_xl): wrote coding conventions
2026-08-17 14:18:06 +02:00
portersky a7d7d0f253 chore: scaffold CMake build system
Add the CMake build for the Swift + C++ macOS port, mirroring the
refix layout: deps/ modules (Platform, Flags, Sanitizers, FindUnity),
per-module static libraries (usb, auth, mt76, gip, hid, api), a Swift
app entry point with a pure C bridge header, and a Unity test suite
behind BUILD_TESTING.

Swift requires the Ninja or Xcode generator; a guard in
CMakeLists.txt rejects anything else.

Co-Authored-By: qwen (qwen/qwen3.8-27b@q2_k_xl): scaffolded CMake build + tests
2026-08-17 14:18:03 +02:00
portersky 78f042ab84 Initial commit 2026-08-04 17:12:54 +02:00