# Phase 11.1: Proximity Sensor App Compatibility Spike — Results

**Date:** 2026-03-27
**Decision:** GO

## Key Findings

### 1. CreateBooleanComponent("/proximity") on HMD container works from sidecar
- `CreateBooleanComponent(hmdContainer, "/proximity", &handle)` returns `err=0, handle=3`
- SteamVR allows multiple drivers to create components with the same name on the same device
- Our component coexists with the lighthouse driver's `/proximity` component

### 2. UpdateBooleanComponent on our own handle works
- `UpdateBooleanComponent(handle=3, true, 0.0)` returns `err=0`
- Application-side monitoring confirms state change:
  - `GetTrackedDeviceActivityLevel(0)` transitions from `Idle (0)` to `UserInteraction (1)`
  - `VREvent_TrackedDeviceUserInteractionStarted` fires for device 0

### 3. Cross-driver UpdateBooleanComponent is blocked (ownership check)
- Lighthouse driver's handles (1, 2) return `VRInputError_WrongType` (err=2) for ALL Update methods
- Server log: `"Input value is wrong type"` — confirmed this is an ownership check, not a type mismatch
- Our own handles (3+) return `err=0` — proves UpdateBooleanComponent works, just not cross-driver

### 4. Initial CreateBooleanComponent failure was timing, not permission
- Previous attempt returned `VRInputError_InvalidParam` (err=4) because HMD container wasn't ready at `Init()` time
- When called later (via pipe command, after HMD fully activated), it succeeds
- Production implementation must defer creation until HMD container is available

### 5. Handle allocation scheme
- Handles are sequential integers starting at 1
- Lighthouse driver gets handles 1, 2 (`/input/system/click`, `/proximity`)
- Our driver gets handles 3+ for any components we create
- HMD container handle = `0x100000000` (1 << 32)

### 6. IVRDriverInput_004 available but not needed
- SteamVR provides `IVRDriverInput_004` (4 additional methods vs _003)
- Methods are appended (COM convention), vtable layout preserved
- _003's `CreateBooleanComponent` and `UpdateBooleanComponent` work correctly — no need for _004

## Production Implementation

```
Init():
  - Defer CreateBooleanComponent until HMD container is available (check in RunFrame)

First RunFrame where HMD container ready:
  - CreateBooleanComponent(hmdContainer, "/proximity", &m_hProximityComponent)
  - If succeeds: use UpdateBooleanComponent for all proximity state changes
  - If fails: fall back to Prop_ContainsProximitySensor_Bool toggling (v1.0 behavior)

SetHmdProximity(bool on):
  - Primary: UpdateBooleanComponent(m_hProximityComponent, on, 0.0)
  - Fallback: SetBoolProperty(Prop_ContainsProximitySensor_Bool, on)
```

## Probe Data

```
HMD container: 4294967296 (0x100000000)
Handle 1: WrongType (lighthouse /input/system/click)
Handle 2: WrongType (lighthouse /proximity)
Handle 3: CreateBoolean("/proximity") = err=0, Update = err=0 → ActivityLevel changed
Handle 4: CreateBoolean("/spike_bool") = err=0, Update = err=0
Handle 5: CreateScalar("/spike_scalar") = err=0
```

## Verification

- [x] SPIKE-01: Handle probing found valid handles (1, 2 from lighthouse, 3+ from sidecar)
- [x] SPIKE-02: UpdateBooleanComponent on our handle changes proximity state in SteamVR
- [x] SPIKE-03: Application-side monitoring confirms ActivityLevel + UserInteractionStarted event
- [x] SPIKE-04: VRChat AFK detection works, Beyond ET enrollment works — confirmed on separate test PC

## Next Steps

Production phase: Move CreateBooleanComponent("/proximity") to deferred init in RunFrame, replace property toggling with UpdateBooleanComponent in SetHmdProximity.
