docs: bring PLAN.md in line with style guide
Replace em dashes with colons throughout, wrap prose and list lines at 80 columns (Goal, Phase 4 options, Known Challenges), refresh the current status section now that pairing and the RX data path are done, and add src/cli to the directory layout. Table alignment was also normalized as a side effect of the file rewrite. Co-Authored-By: qwen3.8-27b@q3_k_xl: reformatted PLAN.md per style guide
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
# Xbox Wireless Dongle — macOS Port
|
# Xbox Wireless Dongle: macOS Port
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
|
|
||||||
User-space macOS app that speaks to the Xbox Wireless Dongle (MT76xx chip) and exposes connected controllers as HID gamepads.
|
User-space macOS app that speaks to the Xbox Wireless Dongle (MT76xx chip)
|
||||||
|
and exposes connected controllers as HID gamepads.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@@ -15,12 +16,12 @@ User-space macOS app that speaks to the Xbox Wireless Dongle (MT76xx chip) and e
|
|||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ ┌────▼──────────────▼──────────────────────┐ │
|
│ ┌────▼──────────────▼──────────────────────┐ │
|
||||||
│ │ GIP Protocol Layer │ │
|
│ │ GIP Protocol Layer │ │
|
||||||
│ │ (bus/protocol.c — ported, pure C) │ │
|
│ │ (bus/protocol.c: ported, pure C) │ │
|
||||||
│ └──────────────────┬───────────────────────┘ │
|
│ └──────────────────┬───────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ┌──────────────────▼───────────────────────┐ │
|
│ ┌──────────────────▼───────────────────────┐ │
|
||||||
│ │ MT76 Chip Protocol Layer │ │
|
│ │ MT76 Chip Protocol Layer │ │
|
||||||
│ │ (transport/mt76.c — ported, USB calls) │ │
|
│ │ (transport/mt76.c: ported, USB calls) │ │
|
||||||
│ └──────────────────┬───────────────────────┘ │
|
│ └──────────────────┬───────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ┌──────────────────▼───────────────────────┐ │
|
│ ┌──────────────────▼───────────────────────┐ │
|
||||||
@@ -40,18 +41,17 @@ User-space macOS app that speaks to the Xbox Wireless Dongle (MT76xx chip) and e
|
|||||||
- Phase 1 (GIP + auth): ported and unit-tested.
|
- Phase 1 (GIP + auth): ported and unit-tested.
|
||||||
- Phase 2 (USB transport): probe/open, async read pump, vendor requests,
|
- Phase 2 (USB transport): probe/open, async read pump, vendor requests,
|
||||||
bulk write. Verified on hardware.
|
bulk write. Verified on hardware.
|
||||||
- Phase 3 (MT76 chip): register/EFUSE access, firmware load,
|
- Phase 3 (MT76 chip): register/EFUSE access, firmware load, radio init
|
||||||
radio init (registers, crystal, MAC/BSSID, channel eval, beacon). Verified
|
(registers, crystal, MAC/BSSID, channel eval, beacon), pairing mode,
|
||||||
end-to-end: `radio-init` completes, beacon TX enabled, FCE shows firmware
|
controller association, GIP handshake + auth. Verified end-to-end on
|
||||||
running.
|
hardware: live controller input is shown in the app (RX data path).
|
||||||
- C API + Swift app: async session (fast probe; firmware + radio on a worker
|
- C API + Swift app: async session (fast probe; firmware + radio on a worker
|
||||||
thread), state display (idle/starting/ready/error).
|
thread), state display (idle/starting/ready/error), controller list with
|
||||||
|
live input monitor.
|
||||||
|
|
||||||
Remaining for Phase 3: controller association and the data path (design below).
|
Remaining for Phase 3: host to controller TX over the data path (rumble,
|
||||||
Then Phase 4 (HID) and Phase 5 (app polish).
|
LED). Then Phase 4 (HID) and Phase 5 (app polish); exposing the controller
|
||||||
|
as a macOS HID gamepad is the main user-visible gap.
|
||||||
**Immediate goal:** pair a controller and show it in the GUI. Exposing it as
|
|
||||||
a macOS HID device is deferred.
|
|
||||||
|
|
||||||
## Directory Layout
|
## Directory Layout
|
||||||
|
|
||||||
@@ -64,6 +64,7 @@ macos/
|
|||||||
│ ├── gip/ ← GIP protocol (port from bus/protocol.c)
|
│ ├── gip/ ← GIP protocol (port from bus/protocol.c)
|
||||||
│ ├── auth/ ← Auth + crypto (port from auth/)
|
│ ├── auth/ ← Auth + crypto (port from auth/)
|
||||||
│ ├── hid/ ← Virtual HID gamepad (new)
|
│ ├── hid/ ← Virtual HID gamepad (new)
|
||||||
|
│ ├── cli/ ← C++ CLI for manual protocol sequences
|
||||||
│ └── app/ ← macOS app entry point + UI (new)
|
│ └── app/ ← macOS app entry point + UI (new)
|
||||||
├── include/
|
├── include/
|
||||||
│ ├── common/ ← Shared types, platform abstraction
|
│ ├── common/ ← Shared types, platform abstraction
|
||||||
@@ -80,7 +81,7 @@ macos/
|
|||||||
|
|
||||||
## Implementation Phases
|
## Implementation Phases
|
||||||
|
|
||||||
### Phase 1 — Foundation (Linux → C library)
|
### Phase 1: Foundation (Linux → C library)
|
||||||
|
|
||||||
Extract the protocol logic from Linux kernel code into standalone C.
|
Extract the protocol logic from Linux kernel code into standalone C.
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ Extract the protocol logic from Linux kernel code into standalone C.
|
|||||||
- Endianness helpers
|
- Endianness helpers
|
||||||
- Memory allocator abstraction (so we can swap malloc if needed)
|
- Memory allocator abstraction (so we can swap malloc if needed)
|
||||||
|
|
||||||
### Phase 2 — USB Transport (new)
|
### Phase 2: USB Transport (new)
|
||||||
|
|
||||||
**src/usb/**
|
**src/usb/**
|
||||||
|
|
||||||
@@ -112,28 +113,29 @@ Extract the protocol logic from Linux kernel code into standalone C.
|
|||||||
- Open device, claim interface (bInterfaceNumber = 1)
|
- Open device, claim interface (bInterfaceNumber = 1)
|
||||||
- `IOUSBDevInterface` for control transfers (vendor requests)
|
- `IOUSBDevInterface` for control transfers (vendor requests)
|
||||||
- `IOUSBInterfaceInterface` for bulk endpoints:
|
- `IOUSBInterfaceInterface` for bulk endpoints:
|
||||||
- EP 0x04 IN — WLAN data (802.11 frames from controllers)
|
- EP 0x04 IN: WLAN data (802.11 frames from controllers)
|
||||||
- EP 0x04 OUT — Bulk out (commands to chip)
|
- EP 0x04 OUT: Bulk out (commands to chip)
|
||||||
- EP 0x05 IN — MCU commands (firmware load responses)
|
- EP 0x05 IN: MCU commands (firmware load responses)
|
||||||
- Async completion callbacks → callback/dispatch queue
|
- Async completion callbacks → callback/dispatch queue
|
||||||
- Device disconnect handling (chip reconnects during firmware load)
|
- Device disconnect handling (chip reconnects during firmware load)
|
||||||
|
|
||||||
**Key IOKit APIs:**
|
**Key IOKit APIs:**
|
||||||
|
|
||||||
- `IOServiceMatching("IOUSBDevice")` — find dongle
|
- `IOServiceMatching("IOUSBDevice")`: find dongle
|
||||||
- `IOUSBDeviceOpen` / `IOUSBInterfaceOpen` — claim
|
- `IOUSBDeviceOpen` / `IOUSBInterfaceOpen`: claim
|
||||||
- `DeviceRequest` — control transfers (register R/W)
|
- `DeviceRequest`: control transfers (register R/W)
|
||||||
- `WritePipe` / `ReadPipe` — bulk transfers
|
- `WritePipe` / `ReadPipe`: bulk transfers
|
||||||
- `CreateInterruptEndpoint` — for EP 0x05 (MCU)
|
- `CreateInterruptEndpoint`: for EP 0x05 (MCU)
|
||||||
|
|
||||||
### Phase 3 — MT76 Chip Protocol (port)
|
### Phase 3: MT76 Chip Protocol (port)
|
||||||
|
|
||||||
**src/mt76/**
|
**src/mt76/**
|
||||||
|
|
||||||
- Port `transport/mt76.c` → replace USB calls with Phase 2 transport
|
- Port `transport/mt76.c` → replace USB calls with Phase 2 transport
|
||||||
- **Firmware loading:** send binary in 0x3800-byte chunks, poll for completion
|
- **Firmware loading:** send binary in 0x3800-byte chunks, poll for completion
|
||||||
- **EFUSE read:** MAC address, chip ID, crystal trim, TX power calibration
|
- **EFUSE read:** MAC address, chip ID, crystal trim, TX power calibration
|
||||||
- **Radio init:** ~80 hardcoded register writes (AGC, EDCA, TX power, protection)
|
- **Radio init:** ~80 hardcoded register writes (AGC, EDCA, TX power,
|
||||||
|
protection)
|
||||||
- **Channel evaluation:** cycle through 12 channels, pick highest power
|
- **Channel evaluation:** cycle through 12 channels, pick highest power
|
||||||
- **Beacon transmission:** 802.11 beacons with Microsoft OUI IE
|
- **Beacon transmission:** 802.11 beacons with Microsoft OUI IE
|
||||||
- **Pairing mode:** rotate channels every 2s when pairing enabled
|
- **Pairing mode:** rotate channels every 2s when pairing enabled
|
||||||
@@ -149,20 +151,23 @@ Extract the protocol logic from Linux kernel code into standalone C.
|
|||||||
- `ieee80211_*` → custom 802.11 frame builders
|
- `ieee80211_*` → custom 802.11 frame builders
|
||||||
- `cfg80211_*` → nothing (no regulatory domain reporting needed)
|
- `cfg80211_*` → nothing (no regulatory domain reporting needed)
|
||||||
|
|
||||||
### Phase 4 — Virtual HID Gamepad (new)
|
### Phase 4: Virtual HID Gamepad (new)
|
||||||
|
|
||||||
**src/hid/**
|
**src/hid/**
|
||||||
|
|
||||||
- Expose controller as macOS HID device so games work natively
|
- Expose controller as macOS HID device so games work natively
|
||||||
- Options:
|
- Options:
|
||||||
- **HID Proxy Driver (DriverKit)** — Maps USB device to virtual HID. Minimal kernel code. Preferred approach.
|
- **HID Proxy Driver (DriverKit)**: Maps USB device to virtual HID.
|
||||||
- **IOHIDSystem user-space** — Create virtual HID device entirely in user-space. May not work for all games.
|
Minimal kernel code. Preferred approach.
|
||||||
- **Gamepad wrapper** — Lower-level, translate input events to HID reports.
|
- **IOHIDSystem user-space**: Create virtual HID device entirely in
|
||||||
- Map Xbox controller buttons/sticks/triggers to standard Xbox 360/One HID report descriptor
|
user-space. May not work for all games.
|
||||||
- Handle force feedback (rumble) — send back to dongle via GIP
|
- **Gamepad wrapper**: Lower-level, translate input events to HID reports.
|
||||||
|
- Map Xbox controller buttons/sticks/triggers to standard Xbox 360/One HID
|
||||||
|
report descriptor
|
||||||
|
- Handle force feedback (rumble): send back to dongle via GIP
|
||||||
- Battery status reporting
|
- Battery status reporting
|
||||||
|
|
||||||
### Phase 5 — macOS App (new)
|
### Phase 5: macOS App (new)
|
||||||
|
|
||||||
**src/app/**
|
**src/app/**
|
||||||
|
|
||||||
@@ -282,46 +287,53 @@ on first packet, so a fresh adapter yields its single client on demand.
|
|||||||
|
|
||||||
Firmware binaries are downloaded from Microsoft Windows Update driver catalog:
|
Firmware binaries are downloaded from Microsoft Windows Update driver catalog:
|
||||||
|
|
||||||
| PID | Dongle Type | Firmware File |
|
| PID | Dongle Type | Firmware File |
|
||||||
| ---- | ---------------------- | ------------- |
|
| --- | ----------------- | -------------- |
|
||||||
| all | Supported dongles | xow_dongle.bin |
|
| all | Supported dongles | xow_dongle.bin |
|
||||||
|
|
||||||
Downloaded via `scripts/download-firmware.sh` (port of `install/firmware.sh`).
|
Downloaded via `scripts/download-firmware.sh` (port of `install/firmware.sh`).
|
||||||
|
|
||||||
## Known Challenges
|
## Known Challenges
|
||||||
|
|
||||||
1. **USB timing** — MT76 is timing-sensitive. User-space USB on macOS may have different latency than Linux kernel URBs. May need careful tuning of `usleep` values.
|
1. **USB timing**: MT76 is timing-sensitive. User-space USB on macOS may
|
||||||
|
have different latency than Linux kernel URBs. May need careful tuning
|
||||||
|
of `usleep` values.
|
||||||
|
|
||||||
2. **Chip reconnect** — During firmware load, the dongle disconnects and reconnects. IOKit needs to handle this gracefully (close, wait, reopen, re-claim).
|
2. **Chip reconnect**: During firmware load, the dongle disconnects and
|
||||||
|
reconnects. IOKit needs to handle this gracefully (close, wait, reopen,
|
||||||
|
re-claim).
|
||||||
|
|
||||||
3. **Virtual HID** — Games expect a real HID device. HID Proxy Driver (DriverKit) is the cleanest path but requires a minimal kernel extension.
|
3. **Virtual HID**: Games expect a real HID device. HID Proxy Driver
|
||||||
|
(DriverKit) is the cleanest path but requires a minimal kernel extension.
|
||||||
|
|
||||||
4. **5GHz regulatory** — The dongle uses 5GHz channels. macOS may have regulatory restrictions. May need to limit to 2.4GHz only.
|
4. **5GHz regulatory**: The dongle uses 5GHz channels. macOS may have
|
||||||
|
regulatory restrictions. May need to limit to 2.4GHz only.
|
||||||
|
|
||||||
5. **Audio** — Headset audio is complex (real-time PCM streaming). Lower priority, tackle after gamepad works.
|
5. **Audio**: Headset audio is complex (real-time PCM streaming). Lower
|
||||||
|
priority, tackle after gamepad works.
|
||||||
|
|
||||||
## Source Files to Port
|
## Source Files to Port
|
||||||
|
|
||||||
| Linux source | Target | Notes |
|
| Linux source | Target | Notes |
|
||||||
| ----------------------- | -------------------------- | ---------------------------------- |
|
| ----------------------- | ---------------------------- | ---------------------------------- |
|
||||||
| `transport/mt76.c` | `src/mt76/mt76.c` | Replace USB calls, remove cfg80211 |
|
| `transport/mt76.c` | `src/mt76/mt76.c` | Replace USB calls, remove cfg80211 |
|
||||||
| `transport/mt76.h` | `include/mt76/mt76.hpp` | Clean up kernel types |
|
| `transport/mt76.h` | `include/mt76/mt76.hpp` | Clean up kernel types |
|
||||||
| `transport/mt76_defs.h` | `include/mt76/mt76_defs.hpp` | Mostly copy (register defs) |
|
| `transport/mt76_defs.h` | `include/mt76/mt76_defs.hpp` | Mostly copy (register defs) |
|
||||||
| `bus/protocol.c` | `src/gip/protocol.c` | Replace kernel alloc/lock/debug |
|
| `bus/protocol.c` | `src/gip/protocol.c` | Replace kernel alloc/lock/debug |
|
||||||
| `bus/protocol.h` | `include/gip/protocol.hpp` | Clean up kernel types |
|
| `bus/protocol.h` | `include/gip/protocol.hpp` | Clean up kernel types |
|
||||||
| `bus/bus.c` | `src/gip/bus.c` | Client lifecycle management |
|
| `bus/bus.c` | `src/gip/bus.c` | Client lifecycle management |
|
||||||
| `auth/auth.c` | `src/auth/auth.c` | Pure crypto, mostly copy |
|
| `auth/auth.c` | `src/auth/auth.c` | Pure crypto, mostly copy |
|
||||||
| `auth/auth.h` | `include/auth/auth.hpp` | Copy |
|
| `auth/auth.h` | `include/auth/auth.hpp` | Copy |
|
||||||
| `auth/crypto.c` | `src/auth/crypto.cpp` | AES-CCMP, mostly copy |
|
| `auth/crypto.c` | `src/auth/crypto.cpp` | AES-CCMP, mostly copy |
|
||||||
| `auth/crypto.h` | `include/auth/crypto.hpp` | Copy |
|
| `auth/crypto.h` | `include/auth/crypto.hpp` | Copy |
|
||||||
| `driver/gamepad.c` | N/A | Replaced by HID layer |
|
| `driver/gamepad.c` | N/A | Replaced by HID layer |
|
||||||
|
|
||||||
## Build System
|
## Build System
|
||||||
|
|
||||||
- **CMake** or **Xcode project** — either works
|
- **CMake** or **Xcode project**: either works
|
||||||
- Static library for protocol/auth layers
|
- Static library for protocol/auth layers
|
||||||
- macOS app bundle for the final product
|
- macOS app bundle for the final product
|
||||||
- Minimum macOS: 12.0 (Monterey) — for modern IOKit/DriverKit support
|
- Minimum macOS: 12.0 (Monterey): for modern IOKit/DriverKit support
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user