A field log (2026-07-30) showed a game driving the virtual DualSense's output endpoint at >2 kHz sustained for tens of seconds. The 8-slot ring — sized on the assumption that 2 kHz is double any real HID output rate — overflowed every 4 ms poll, which force-silenced rumble for each storm's whole duration and flooded the log at ~230 WARN lines/s (96 % of the user's 5000-line web-console export, evicting the session history it was needed to diagnose). Three legs, negotiated so every old/new host×driver pairing keeps working: - pf-driver-proto: the ring grows in place 8 -> 56 slots; PadShm becomes exactly one page (4096 B), the hard ceiling that keeps cross-generation section views mappable. A new out_ring_len field carries the driver's side of the length negotiation. Deliberately NOT a GAMEPAD_PROTO_VERSION bump (that fails closed - no pad at all). - pf-gamepad driver: picks its ring length from the host's out_ring_ver stamp (>= 2 + a full-size map -> 56) and echoes it before every ring_head bump (now a Release store), so an Acquire-observing drain always reads the modulo that indexed the slots it copies. - host drain: follows the echo (0 = old driver = 8); on genuine overflow it now salvages the legacy latest-report slot - the freshest coalesced state - instead of total silence, and the per-poll overflow WARN is rate-limited to 1 line/s per pad with a suppressed count. Verified on the Windows CI runner (drivers workspace build + clippy -D warnings against the WDK; 64 pf-inject tests incl. the new negotiation/ salvage/limiter tests; pf-inject clippy -D warnings) and on Linux via the CI docker image (82 pf-inject tests). DriverVer needs no manual bump - the installer stamps a strictly-increasing build timestamp per release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pf-driver-proto
The shared host ↔ driver binary contract for punktfunk's Windows pf-vdisplay virtual display — the control IOCTLs and the IDD-push frame transport, defined exactly once.
It's a path dependency of both the host workspace (crates/punktfunk-host)
and the out-of-workspace driver workspace (packaging/windows/drivers/),
so it must resolve identically from either build graph. That's why it's deliberately self-contained:
no_std (+ alloc), platform-neutral (GUID/LUID are plain integers each side converts to its own OS
type), and free of *.workspace = true inheritance.
Defining every wire struct here — with const size/offset asserts and bytemuck round-trips — turns
host↔driver ABI drift into a compile error instead of a silent frame or IOCTL corruption.
See the crate root (src/) for the wire types; the Windows virtual-display design is in
the internal planning repo (punktfunk-planning: windows-virtual-display-rust-port.md).