9 Commits

Author SHA1 Message Date
portersky 0f6c985f7f feat: implement rumble TX over the GIP data path
Port the rumble packet from upstream driver/gamepad.c: a 9-byte
GIP_CMD_RUMBLE payload (motors R|L|RT|LT, intensities scaled to the
0..100 GIP range, duration/repeat constants). xone_controller_rumble
now sends it via client::send_rumble; the app button pulses both
motors for 0.6s then stops them. Completes the host to controller
TX remainder of Phase 3 (the dongle LED is already driven at chip
level for pairing and client lifecycle).

Co-Authored-By: qwen3.8-27b@q3_k_xl: implemented rumble TX
2026-08-29 15:19:14 +02:00
portersky 416507ed53 feat: battery indicator and rumble test button
Plumb controller battery type/level from the GIP status packets
through the C API into the card header (SF Symbol battery icon).
Add a per-controller Rumble button wired to a new
xone_controller_rumble() entry point; it validates its arguments
and returns -ENOSYS until host to controller TX is implemented.

Co-Authored-By: qwen3.8-27b@q3_k_xl: battery + rumble button UI
2026-08-29 15:13:18 +02:00
portersky 882b0be827 style: use east const in the C API header
Convert the remaining west-const declarations in xone_api.h to east
const so the whole file matches the controller functions added later.
Update the AGENTS.md C bridge section: east const applies to the C
header too; only trailing returns are exempt.

Co-Authored-By: qwen3.8-27b@q3_k_xl: converted C API header to east const
2026-08-29 14:31:50 +02:00
portersky 9c1b6493d8 feat: show live controller input
Route paired controller QoS data through the existing GIP protocol layer and
expose the latest gamepad report through the C API. Add a SwiftUI monitor for
buttons, d-pad, triggers, and stick positions without registering a native HID
device.

Co-Authored-By: openai/gpt-5.6-luna: GIP bridge and live input monitor
2026-08-29 13:36:54 +02:00
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 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 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