‹ projects

reverb-m1

Native wired VR on Apple silicon: Reverb G1 display bring-up and stereo demo
git clone https://umhau.org/code/reverb-m1.git
Log | Files | Refs

commit 781550dd9b63ecda54c4cfd18938b1f6e1b0c21a
parent f9e8de8a43182b5ecb9b11e6c9d0e3f413891a95
Author: umhau <umhau@example.invalid>
Date:   Fri, 23 Oct 2026 12:00:01 +0000

Document native desktop bring-up alongside the stereo cube demo

Diffstat:
MSETUP.md | 59++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mtools/build.sh | 7++++++-
2 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/SETUP.md b/SETUP.md @@ -49,26 +49,63 @@ Side effect: HDCP-protected content (some streaming video to external displays) 3. macOS asks **"Allow accessory to connect?"**. Click **Allow**. Until you do, all HID calls fail with `0xe00002cd` (kIOReturnNotOpen). -### 4. Wake the headset over USB HID +### 4. Build the two demonstrations ```sh -cd tools && ./hmdwake # leave running; Ctrl-C to quit +zsh tools/build.sh ``` -It sends (ported from Monado's `wmr_hmd_activate_reverb`): +Run this from the repository root. It builds the stereo application, recovery helper, +USB wake tool, and passive display observer using Apple's Command Line Tools. + +### 5. Native macOS desktop output + +Quit the stereo application first, then run: + +```sh +.build/debug/hmdwake # leave running; Ctrl-C to quit +``` + +macOS treats the headset as an external display. In System Settings > Displays, +choose the headset and use it as an extended display or select mirroring. Any +windows placed on that display are sent directly to the headset by macOS. + +This reproduces the original desktop-output breakthrough. The operating system +sends one desktop image across the headset's display surface: it does not duplicate +the desktop for each eye or apply the demo renderer's lens correction. This is +display bring-up, rather than a comfortable stereo desktop workspace. + +For a passive connection/mode check, run this in another terminal: + +```sh +.build/debug/displaywatch # Ctrl-C to quit +``` + +It reports display connections and pixel modes without capturing desktop pixels. +Its output includes display metadata and timestamps; review it before sharing logs. +Seeing a connected display in software is separate from confirming illumination +and the desktop image inside the headset. The standalone wake tool does not run +the stereo application's automatic link recovery. + +The wake tool sends (ported from Monado's `wmr_hmd_activate_reverb`): - To the QHMD control device `03f0:0c6a` (feature reports): 4x set `[0x50, 0x01]` + get `0x50`, then get `0x09`, `0x08`, `0x06`, then set `[0x04, 0x01]` (screen on). - To the HoloLens Sensors device `045e:0659` (output report): `[0x02, 0x07]` + zero pad to 64 bytes (IMU on). Within ~1.5 s the DP link trains (HBR3, 8.1 Gbps x 4 lanes), macOS adds the 4320x2160 display, and the headset reports `05 01 01 01 01 ...` (panel on). (Drops can still occur later; see NOTES.md "Link reliability".) -The app (step 5) does this wake itself; `hmdwake` is only for diagnostics. Don't run both. +Stop `hmdwake` with Ctrl-C before starting the stereo demo. The application sends +the wake sequence itself; the two programs must not own the HID devices together. -### 5. Build and run the app (owns the headset, recovers it automatically) +### 6. Stereo 3D demo (owns the headset, recovers it automatically) ```sh -zsh tools/build.sh # builds the app + the signed recovery helper -.build/debug/VRWorkstation --run-seconds 600 # run for 10 minutes (omit for indefinite) +.build/debug/VRWorkstation --run-seconds 600 # run for 10 minutes; omit the option for indefinite ``` +Look for a rotating colored cube, a floor grid, and reference objects at several +depths. Each eye receives its own rendered view through the factory lens correction. +The Headset optics window on the Mac provides pattern/tuning controls and Quit. +This demo uses a fixed viewpoint; head tracking is not connected to this scene. + - `tools/build.sh` builds the app with `swift build`, then compiles `tools/hpmctl.c` into the same directory as the app - executable (`swift build --show-bin-path`) and ad-hoc signs it with `tools/hpmctl.entitlements` + executable (`.build/debug`) and ad-hoc signs it with `tools/hpmctl.entitlements` (`com.apple.USBCEntitlement`). - The app runs as a normal non-root user. When the headset display is lost and does not return within a 2 s grace period, it runs that helper directly to send a USB-PD Data Reset to port 2's controller. No sudo, no password: @@ -141,12 +178,12 @@ zsh tools/build.sh # builds the app + the signe Judge the display by the native mode in use and actual Metal presentation counts, not by this byte. ## Tools (`tools/`) -- `hmdwake`: wake sequence + IMU on; logs status reports. `passive` arg = listen only. SIGUSR1 = screen on. -- `displaywatch`: passively logs display add/remove (CoreGraphics callbacks). +- `hmdwake` (`.build/debug/hmdwake`): wake sequence + IMU on, exposing native desktop output. Feature/control payloads are omitted from logs. `passive` arg = listen only. SIGUSR1 = screen on. +- `displaywatch` (`.build/debug/displaywatch`): passively logs display add/remove (CoreGraphics callbacks); does not capture screen pixels. - Never poll `ioreg -c IOPortTransportStateDisplayPort` (the old `linkwatch.sh` did; removed). - `testpattern`: red LEFT / blue RIGHT fullscreen pattern on the headset. - `verify.sh`: passive one-shot check (boot-args + summaries of existing logs). No ioreg/system_profiler/HID. Launches nothing. -- `build.sh`: builds the app and the signed `hpmctl` helper beside it (SETUP step 5). +- `build.sh`: builds the app, signed `hpmctl` helper, `hmdwake`, and `displaywatch` together (step 4). - `hpmctl` / `recovery_trials.py` / the app's LinkRecovery helper: see NOTES.md "Link reliability" (vr0 owns these). ### Optical tuning window diff --git a/tools/build.sh b/tools/build.sh @@ -3,8 +3,13 @@ set -euo pipefail cd "$(dirname "$0")/.." swift build -vr_bin_dir=$(swift build --show-bin-path) +# SwiftPM exposes the default configuration through this relative symlink. +vr_bin_dir=".build/debug" clang -Wall -Wextra -O2 -framework IOKit -framework CoreFoundation tools/hpmctl.c -o "$vr_bin_dir/hpmctl" codesign --force --sign - --entitlements tools/hpmctl.entitlements "$vr_bin_dir/hpmctl" +swiftc tools/hmdwake.swift -framework IOKit -o "$vr_bin_dir/hmdwake" +swiftc tools/displaywatch.swift -o "$vr_bin_dir/displaywatch" print "App: $vr_bin_dir/VRWorkstation" print "Recovery helper: $vr_bin_dir/hpmctl" +print "Native desktop: $vr_bin_dir/hmdwake" +print "Passive display observer: $vr_bin_dir/displaywatch"