ZakoVirtualGamepad is deliberately a narrow DS5 backend. It does not replace ViGEm's Xbox 360 or DS4 devices and it does not accept caller-provided HID descriptors, vendor IDs, product IDs, or arbitrary feature-report handlers. That keeps the privileged attack surface small and makes compatibility behavior reviewable.
Moonlight input -> Sunshine mapping -> Zako client API -> private IOCTLs
|
v
UMDF 2 driver + VHF
|
v
Windows HID stack / virtual DualSense
Game output (rumble/LED/triggers) -> VHF callback -> semantic output event
-> Sunshine -> Moonlight
Each open control handle owns at most one virtual controller. Closing the handle destroys the child synchronously. This ownership model makes crash recovery predictable and permits several Sunshine sessions without global device IDs.
- Sunshine opens
\\.\ZakoVirtualGamepadwith overlapped I/O. - It calls
GET_DRIVER_INFOand validates both protocol and capabilities. - It calls
CREATE_DUALSENSEwith a stable locally administered MAC address. - It always keeps one
READ_OUTPUTrequest pending. - Input is submitted only when changed or when Sunshine's keepalive policy requires it. The driver does not impose a polling-rate timer.
- On session shutdown Sunshine cancels output I/O, calls
DESTROY_DEVICE, and closes the handle. Close is the authoritative cleanup path.
The output path retains the latest feedback command if no read is pending. It does not retain an unbounded history because rumble and LED commands are state, not an audit stream. A monotonically increasing sequence lets Sunshine detect coalescing.
- Label the option
DualSense (native, experimental)until the compatibility matrix and signing pipeline reach release status. - If unavailable, show the exact reason: not installed, access denied, protocol mismatch, or device creation failure.
- Offer
Use DualShock 4 compatibility modeas the primary recovery action. - Never ask a normal user to enable Windows test-signing mode.
- Driver install/update should be a separate elevated action with progress, publisher identity, reboot state, and a rollback path.
- Preserve the user's explicit controller choice across restarts, but do not repeatedly show modal errors when no gamepad session is active.
There is no UMDF-specific fixed polling-rate limit. SUBMIT_INPUT directly calls
VhfReadReportSubmit; practical latency depends on scheduling, HID consumers,
and Sunshine's network/input loop. The initial target is 250 Hz, with 500 Hz and
1000 Hz treated as measured compatibility goals rather than promises.
The lifecycle lock serializes create, input submission, and destroy so a VHF handle cannot be deleted while a report is being submitted. A separate state lock covers the current input snapshot and one cached output state, allowing VHF callbacks to complete without waiting behind device creation or deletion. No networking, logging, allocation, or blocking user operation belongs under the state lock. VHF operations are completed immediately inside callbacks.
The device ACL permits administrators, LocalSystem, and UMDF drivers. Sunshine must therefore open the driver through its privileged service boundary rather than from the web UI. IOCTLs use fixed-size structures, validate ABI headers, and expose no generic HID construction primitive.