refactor: rename pf-vdisplay-proto -> pf-driver-proto (it spans all drivers)

The shared host<->driver ABI crate already contains more than the virtual
display: the IDD-push frame ring + control plane AND the gamepad shared-memory
layouts (XusbShm / PadShm). "pf-vdisplay-proto" was a misnomer — the name now
represents all the drivers it serves.

Mechanical rename, no behavior change:
- git mv crates/pf-vdisplay-proto -> crates/pf-driver-proto (package name +
  path-deps in the host crate and the driver workspace).
- pf_vdisplay_proto -> pf_driver_proto across host + driver Rust, both Cargo.lock
  files, the workspace members, the CI path triggers (windows-drivers.yml), and
  the docs/INF comments. The runtime Global\pfvd-* shared-object names are a
  SEPARATE contract and are deliberately untouched (host<->driver name matching).
- The pf-vdisplay DRIVER crate + its INF service name (Root\pf_vdisplay,
  UmdfService=pf_vdisplay, pf_vdisplay.dll) are unchanged — only the full
  `pf_vdisplay_proto` token was replaced, never the `pf_vdisplay` driver name.

Linux-verified: cargo test -p pf-driver-proto (const size-asserts compile) +
cargo clippy -p punktfunk-host -D warnings clean; Cargo.lock regenerated. The
driver-workspace side (path-dep + imports + its Cargo.lock) is Windows-CI-gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 05:13:16 +00:00
parent 84a3b95f17
commit 00cf51d610
25 changed files with 75 additions and 75 deletions
@@ -7,7 +7,7 @@
# own OS type. Defining every wire struct ONCE here — with `const` size/offset asserts + bytemuck
# round-trips — makes host<->driver ABI drift a COMPILE error instead of a silent frame/IOCTL corruption.
[package]
name = "pf-vdisplay-proto"
name = "pf-driver-proto"
version = "0.0.1"
edition = "2021"
rust-version = "1.82"
+1 -1
View File
@@ -192,7 +192,7 @@ ffmpeg-next = { version = "8", optional = true }
# (vdisplay/pf_vdisplay.rs): the control-plane IOCTL codes + `#[repr(C)] Pod` request/reply structs,
# defined ONCE so host<->driver ABI drift is a compile error. `bytemuck` serializes those structs
# to/from the DeviceIoControl byte buffers.
pf-vdisplay-proto = { path = "../pf-vdisplay-proto" }
pf-driver-proto = { path = "../pf-driver-proto" }
bytemuck = { version = "1.19", features = ["derive"] }
[features]
@@ -7,13 +7,13 @@
//! `PUNKTFUNK_IDD_PUSH`. Driver counterpart: `packaging/windows/drivers/pf-vdisplay/src/
//! frame_transport.rs`. The shared `SharedHeader` layout, `MAGIC`/`VERSION`/`RING_LEN`, the
//! `DRV_STATUS_*` codes, the `Global\` name scheme and the publish token all come from
//! [`pf_vdisplay_proto::frame`] (which OWNS the contract, with `const` size asserts) — both sides
//! [`pf_driver_proto::frame`] (which OWNS the contract, with `const` size asserts) — both sides
//! `use` it, so drift is a compile error rather than a "must match" comment.
use super::dxgi::{make_device, D3d11Frame, HdrConverter, WinCaptureTarget};
use super::{CapturedFrame, Capturer, FramePayload, PixelFormat};
use anyhow::{bail, Context, Result};
use pf_vdisplay_proto::frame;
use pf_driver_proto::frame;
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use windows::core::{w, Interface, HSTRING};
@@ -42,7 +42,7 @@ use windows::Win32::System::Memory::{
use windows::Win32::System::Threading::{CreateEventW, WaitForSingleObject};
// The frame-transport contract — `SharedHeader` layout, `MAGIC`/`VERSION`/`RING_LEN`, the
// `DRV_STATUS_*` codes and the `Global\` name helpers — lives in `pf_vdisplay_proto::frame`; both sides
// `DRV_STATUS_*` codes and the `Global\` name helpers — lives in `pf_driver_proto::frame`; both sides
// `use frame::*`, so a layout/name/code drift is a compile error (the proto has `const` size asserts).
use frame::{
event_name, header_name, texture_name, SharedHeader, DRV_STATUS_NO_DEVICE1, DRV_STATUS_OPENED,
@@ -59,7 +59,7 @@ const DXGI_SHARED_RESOURCE_RW: u32 = 0x8000_0000 | 0x1;
const OUT_RING: usize = 3;
/// Bring-up debug block (fixed name) — the host creates it; the driver writes diagnostics into it
/// independent of the per-target header. NOT part of `pf_vdisplay_proto` (a host-side bring-up channel,
/// independent of the per-target header. NOT part of `pf_driver_proto` (a host-side bring-up channel,
/// not the data path); the matching `DebugBlock` lives in the OLD oracle driver's `frame_transport.rs`.
#[repr(C)]
struct DebugBlock {
@@ -40,21 +40,21 @@ use windows::Win32::System::Memory::{
};
use windows::Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject};
/// Shared-section layout — the single source of truth is [`pf_vdisplay_proto::gamepad::PadShm`] (offset
/// Shared-section layout — the single source of truth is [`pf_driver_proto::gamepad::PadShm`] (offset
/// asserts pin every field; the `pf_dualsense` driver maps the same struct). Derive the size/offsets/magic
/// from it so a layout change is a compile error, not a hand-synced literal (audit §6.1). `pub(super)` so
/// the sibling DualShock 4 backend ([`super::dualshock4_windows`]) reuses the exact offsets.
pub(super) const SHM_SIZE: usize = core::mem::size_of::<pf_vdisplay_proto::gamepad::PadShm>();
pub(super) const SHM_MAGIC: u32 = pf_vdisplay_proto::gamepad::PAD_MAGIC; // "PFDS"
pub(super) const OFF_INPUT: usize = core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, input);
pub(super) const SHM_SIZE: usize = core::mem::size_of::<pf_driver_proto::gamepad::PadShm>();
pub(super) const SHM_MAGIC: u32 = pf_driver_proto::gamepad::PAD_MAGIC; // "PFDS"
pub(super) const OFF_INPUT: usize = core::mem::offset_of!(pf_driver_proto::gamepad::PadShm, input);
pub(super) const OFF_OUT_SEQ: usize =
core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, out_seq);
pub(super) const OFF_OUTPUT: usize = core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, output);
core::mem::offset_of!(pf_driver_proto::gamepad::PadShm, out_seq);
pub(super) const OFF_OUTPUT: usize = core::mem::offset_of!(pf_driver_proto::gamepad::PadShm, output);
/// Device-type selector the driver reads to choose which HID identity/descriptor it serves: 0 =
/// DualSense (the default — the section is zeroed), 1 = DualShock 4.
pub(super) const OFF_DEVTYPE: usize =
core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, device_type);
pub(super) const DEVTYPE_DUALSHOCK4: u8 = pf_vdisplay_proto::gamepad::DEVTYPE_DUALSHOCK4;
core::mem::offset_of!(pf_driver_proto::gamepad::PadShm, device_type);
pub(super) const DEVTYPE_DUALSHOCK4: u8 = pf_driver_proto::gamepad::DEVTYPE_DUALSHOCK4;
/// A single virtual DualSense: the SwDeviceCreate'd `pf_pad_<index>` software devnode (the driver
/// loads on it and the HID DualSense appears to games) plus the shared-memory section the driver maps.
@@ -243,7 +243,7 @@ pub(super) fn create_swdevice(p: &SwDeviceProfile) -> Result<HSWDEVICE> {
/// caller stamps the device-type + initial input report and finally the magic. Shared by both Windows
/// pad backends (DualSense + DualShock 4).
pub(super) fn create_shm_section(index: u8) -> Result<(HANDLE, *mut u8)> {
let name = HSTRING::from(pf_vdisplay_proto::gamepad::pad_shm_name(index));
let name = HSTRING::from(pf_driver_proto::gamepad::pad_shm_name(index));
let mut psd = PSECURITY_DESCRIPTOR::default();
// SAFETY: the SDDL literal is valid; psd receives an allocated descriptor (freed by the OS when
@@ -32,12 +32,12 @@ use windows::Win32::System::Memory::{
};
use windows::Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject};
// Shared-section layout — the single source of truth is `pf_vdisplay_proto::gamepad::XusbShm` (offset
// Shared-section layout — the single source of truth is `pf_driver_proto::gamepad::XusbShm` (offset
// asserts pin every field; the `pf_xusb` driver maps the same struct). Derive the size/offsets/magic from
// it so a layout change is a compile error, not a hand-synced literal (audit §6.1).
use pf_vdisplay_proto::gamepad::XusbShm;
use pf_driver_proto::gamepad::XusbShm;
const SHM_SIZE: usize = core::mem::size_of::<XusbShm>();
const SHM_MAGIC: u32 = pf_vdisplay_proto::gamepad::XUSB_MAGIC; // "PFXU"
const SHM_MAGIC: u32 = pf_driver_proto::gamepad::XUSB_MAGIC; // "PFXU"
const OFF_PACKET: usize = core::mem::offset_of!(XusbShm, packet);
const OFF_BUTTONS: usize = core::mem::offset_of!(XusbShm, buttons);
const OFF_LT: usize = core::mem::offset_of!(XusbShm, left_trigger);
@@ -160,7 +160,7 @@ struct XusbWinPad {
impl XusbWinPad {
/// Create + map `Global\pfxusb-shm-<index>`, stamp the magic, then spawn the devnode.
fn open(index: u8) -> Result<XusbWinPad> {
let name = HSTRING::from(pf_vdisplay_proto::gamepad::xusb_shm_name(index));
let name = HSTRING::from(pf_driver_proto::gamepad::xusb_shm_name(index));
// Permissive DACL so the WUDFHost (whatever account) can open the section.
let mut psd = PSECURITY_DESCRIPTOR::default();
@@ -5,14 +5,14 @@
//! the returned [`VirtualOutput`]'s keepalive `Drop` removes it (RAII).
//!
//! Control surface: a device-interface-GUID + `CreateFileW` + `DeviceIoControl` IOCTL protocol, with
//! the wire contract OWNED by [`pf_vdisplay_proto::control`] (versioned + `#[repr(C)] Pod` structs,
//! the wire contract OWNED by [`pf_driver_proto::control`] (versioned + `#[repr(C)] Pod` structs,
//! NOT the SudoVDA ABI). No DLL, no named pipe. See `docs/windows-host-rewrite.md`.
//!
//! This is a faithful clone of [`super::sudovda`] (the shipping fallback) repointed at the new driver:
//! same reference-counted/lingering monitor lifecycle, same CCD isolation + active-mode forcing — those
//! backend-NEUTRAL helpers are REUSED from `sudovda` (a pf-vdisplay monitor's `target_id` is a real OS
//! target id, so the CCD/DXGI code works unchanged). Only the driver-specific bits (GUID, IOCTL codes,
//! request/reply structs, the version handshake) differ, per `pf_vdisplay_proto`.
//! request/reply structs, the version handshake) differ, per `pf_driver_proto`.
use std::ffi::c_void;
use std::mem::size_of;
@@ -32,16 +32,16 @@ use windows::Win32::Storage::FileSystem::{
};
use windows::Win32::System::IO::DeviceIoControl;
use pf_vdisplay_proto::control;
use pf_driver_proto::control;
use super::manager::{AddedMonitor, MonitorKey, VdisplayDriver};
use super::{Mode, VirtualDisplay, VirtualOutput};
// pf-vdisplay device-interface GUID (pf_vdisplay_proto::PF_VDISPLAY_INTERFACE_GUID_U128). Deliberately
// pf-vdisplay device-interface GUID (pf_driver_proto::PF_VDISPLAY_INTERFACE_GUID_U128). Deliberately
// NOT SudoVDA's `{e5bcc234-…}` — we own this driver, so a private interface GUID signals it and avoids
// any accidental coexistence with a real SudoVDA install.
const PF_VDISPLAY_INTERFACE: GUID =
GUID::from_u128(pf_vdisplay_proto::PF_VDISPLAY_INTERFACE_GUID_U128);
GUID::from_u128(pf_driver_proto::PF_VDISPLAY_INTERFACE_GUID_U128);
/// Monotonic per-session id keying a pf-vdisplay monitor for `IOCTL_ADD`/`IOCTL_REMOVE`. Unlike
/// SudoVDA's 16-byte GUID + pid-mangling, the proto keys monitors by a plain `u64` — the host-level
@@ -135,7 +135,7 @@ unsafe fn open_device() -> Result<HANDLE> {
}
/// The pf-vdisplay IOCTL surface behind the shared [`VirtualDisplayManager`](super::manager::VirtualDisplayManager)
/// (Goal-1 §2.5) — the wire contract is owned by `pf_vdisplay_proto::control` (versioned, hard-checked).
/// (Goal-1 §2.5) — the wire contract is owned by `pf_driver_proto::control` (versioned, hard-checked).
pub(crate) struct PfVdisplayDriver;
impl VdisplayDriver for PfVdisplayDriver {
@@ -152,14 +152,14 @@ impl VdisplayDriver for PfVdisplayDriver {
.context("pf-vdisplay IOCTL_GET_INFO (version handshake)")?;
let info: control::InfoReply =
bytemuck::pod_read_unaligned(&info_buf[..size_of::<control::InfoReply>()]);
if info.protocol_version != pf_vdisplay_proto::PROTOCOL_VERSION {
if info.protocol_version != pf_driver_proto::PROTOCOL_VERSION {
unsafe {
let _ = CloseHandle(device);
}
anyhow::bail!(
"pf-vdisplay protocol mismatch: host expects {}, driver reports {} — install matching \
host + driver",
pf_vdisplay_proto::PROTOCOL_VERSION,
pf_driver_proto::PROTOCOL_VERSION,
info.protocol_version
);
}