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:
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the
|
||||
# inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code,
|
||||
# and build+test the owned ABI crate (pf-vdisplay-proto) on MSVC to prove it compiles cross-OS and the
|
||||
# and build+test the owned ABI crate (pf-driver-proto) on MSVC to prove it compiles cross-OS and the
|
||||
# CI wiring works. The runner has no RTX GPU — that's fine: builds, the IddCx bindgen/link, the
|
||||
# /INTEGRITYCHECK self-sign-load, and (later) IDD-push frame flow on the basic display do not need one;
|
||||
# only live NVENC encode does, which defers to the RTX box.
|
||||
@@ -18,12 +18,12 @@ on:
|
||||
branches: [main]
|
||||
paths:
|
||||
- '.gitea/workflows/windows-drivers.yml'
|
||||
- 'crates/pf-vdisplay-proto/**'
|
||||
- 'crates/pf-driver-proto/**'
|
||||
- 'packaging/windows/drivers/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.gitea/workflows/windows-drivers.yml'
|
||||
- 'crates/pf-vdisplay-proto/**'
|
||||
- 'crates/pf-driver-proto/**'
|
||||
- 'packaging/windows/drivers/**'
|
||||
|
||||
# Driver builds need the WDK on the runner (provision once via windows-drivers-provision.yml).
|
||||
@@ -93,17 +93,17 @@ jobs:
|
||||
Write-Host ("CARGO_HOME = " + ($env:CARGO_HOME ?? '<unset>'))
|
||||
Write-Host ("CARGO_TARGET_DIR (daemon) = " + ($env:CARGO_TARGET_DIR ?? '<unset>'))
|
||||
|
||||
- name: Build + test pf-vdisplay-proto (MSVC)
|
||||
- name: Build + test pf-driver-proto (MSVC)
|
||||
run: |
|
||||
# Short target dir to dodge MAX_PATH inside the deep act host workdir (see windows.yml).
|
||||
$env:CARGO_TARGET_DIR = "C:\t\drv"
|
||||
cargo build -p pf-vdisplay-proto
|
||||
cargo test -p pf-vdisplay-proto
|
||||
cargo clippy -p pf-vdisplay-proto --all-targets -- -D warnings
|
||||
cargo fmt -p pf-vdisplay-proto -- --check
|
||||
cargo build -p pf-driver-proto
|
||||
cargo test -p pf-driver-proto
|
||||
cargo clippy -p pf-driver-proto --all-targets -- -D warnings
|
||||
cargo fmt -p pf-driver-proto -- --check
|
||||
|
||||
# Build the UMDF driver workspace (wdk-probe) on windows-drivers-rs: proves wdk-sys bindgen/link works
|
||||
# on the runner's WDK + LLVM, that pf-vdisplay-proto path-deps into a driver, and exposes the produced
|
||||
# on the runner's WDK + LLVM, that pf-driver-proto path-deps into a driver, and exposes the produced
|
||||
# DLL's FORCE_INTEGRITY (/INTEGRITYCHECK) bit — the M0 self-signed-load question.
|
||||
driver-build:
|
||||
runs-on: windows-amd64
|
||||
|
||||
Generated
+2
-2
@@ -2419,7 +2419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "pf-vdisplay-proto"
|
||||
name = "pf-driver-proto"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
@@ -2670,7 +2670,7 @@ dependencies = [
|
||||
"nvidia-video-codec-sdk",
|
||||
"openh264",
|
||||
"opus",
|
||||
"pf-vdisplay-proto",
|
||||
"pf-driver-proto",
|
||||
"pipewire",
|
||||
"punktfunk-core",
|
||||
"quinn",
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ resolver = "2"
|
||||
members = [
|
||||
"crates/punktfunk-core",
|
||||
"crates/punktfunk-host",
|
||||
"crates/pf-vdisplay-proto",
|
||||
"crates/pf-driver-proto",
|
||||
"clients/probe",
|
||||
"clients/linux",
|
||||
"clients/windows",
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
> This file **consolidates and replaces** five earlier docs (now retired into it): the rewrite design
|
||||
> plan, the Goal-1 staged-refactor plan, the audit, the audit-remediation tracker, and the
|
||||
> fullscreen-game capture-bug analysis. See the [consolidation note](#appendix--consolidation-note) for
|
||||
> what moved where. **Last updated 2026-06-25.** Work lives on branch **`windows-host-goal1`** (off
|
||||
> what moved where. **Last updated 2026-06-26.** Work lives on branch **`windows-host-goal1`** (off
|
||||
> `main`, not yet merged).
|
||||
|
||||
---
|
||||
@@ -35,7 +35,7 @@ which kept the live-validated host working at every step. The driver, by contras
|
||||
| **Goal 1** — clean, layered host architecture | ✅ **DONE** | `config.rs` (`HostConfig`), `session_plan.rs` (`SessionPlan`), `SessionContext`, `windows/`+`linux/` confinement (`38c68c3`), `VirtualDisplayManager` (§2.5), `EncoderCaps` (`0ccd0fe`) |
|
||||
| **Goal 2** — drop every trace of SudoVDA | ✅ **DONE** | reach-in decoupled (F1: `d638a93`/`e60cda3` → `win_adapter`/`win_display`), then the `sudovda.rs` backend + the dual-backend select **deleted** (this branch) — pf-vdisplay is the sole Windows virtual-display backend |
|
||||
| **Goal 3** — minimize `unsafe` + P0 lints | 🟡 **PARTIAL** | driver `deny(unsafe_op_in_unsafe_fn)` (`a755d6e`); host crate has **no** P0 lints yet; `OwnedHandle` adopted in `manager.rs`/`pf_vdisplay.rs`/`sudovda.rs`, **not** `idd_push.rs` |
|
||||
| **M0** — proto ABI + driver toolchain + `/INTEGRITYCHECK` + `iddcx` | ✅ **DONE** | `pf-vdisplay-proto`; vendored `windows-drivers-rs` 0.5.1; `clear-force-integrity.ps1`; CI-green |
|
||||
| **M0** — proto ABI + driver toolchain + `/INTEGRITYCHECK` + `iddcx` | ✅ **DONE** | `pf-driver-proto`; vendored `windows-drivers-rs` 0.5.1; `clear-force-integrity.ps1`; CI-green |
|
||||
| **M1** — new IddCx driver, first light + HDR | ✅ **DONE (on-glass)** | STEP 0–8 (`d7a9fbf`…`cd59151`); HDR live ("Mac connects WITH HDR", `6399d28`) |
|
||||
| **M2** — IDD-push capture + NVENC, glass-to-glass | ✅ **DONE (on-glass)** | 5120×1440@240 HDR zero-copy; integrated into the host path |
|
||||
| **M3** — service / input / audio / **secure desktop** | ✅ **DONE (on-glass)** | secure desktop (lock/UAC) **owner-confirmed 2026-06-25** — IDD-push captures it + input reaches it |
|
||||
@@ -57,7 +57,7 @@ which kept the live-validated host working at every step. The driver, by contras
|
||||
and top-level `src/windows/`+`src/linux/`). Module names stay flat (`#[path]`), so caller paths are
|
||||
platform-agnostic.
|
||||
- **`crates/punktfunk-core`** — the one linked protocol/FEC/crypto/QUIC core (unchanged here).
|
||||
- **`crates/pf-vdisplay-proto`** — the owned, `no_std` host↔driver ABI (frame ring + control plane +
|
||||
- **`crates/pf-driver-proto`** — the owned, `no_std` host↔driver ABI (frame ring + control plane +
|
||||
gamepad SHM), consumed by both the host crate and the driver workspace (§2.7).
|
||||
- **`packaging/windows/drivers/`** — the unified driver workspace on `microsoft/windows-drivers-rs`
|
||||
(vendored 0.5.1 + an `iddcx` subset): members `pf-vdisplay` (the IddCx display driver), `wdk-iddcx`
|
||||
@@ -139,7 +139,7 @@ HEVC Main10 + BT.2020 PQ; the client auto-detects PQ from the VUI. The encoder a
|
||||
size/format/HDR change per frame (tears down + re-inits), so the GB1 capturer's resolution changes are
|
||||
handled downstream with no API change.
|
||||
|
||||
### 2.7 Host↔driver ABI — `pf-vdisplay-proto`
|
||||
### 2.7 Host↔driver ABI — `pf-driver-proto`
|
||||
|
||||
One `no_std` crate, both build graphs. Owns the **frame plane** (`SharedHeader`, `FrameToken { generation,
|
||||
seq, slot }` with `pack`/`unpack`, `Global\pfvd-*` name helpers), the **control plane** (fresh interface
|
||||
@@ -155,7 +155,7 @@ All-Rust UMDF IddCx driver on `windows-drivers-rs` + the `iddcx` `wdk-sys` subse
|
||||
(`packaging/windows/drivers/pf-vdisplay/src/`): `entry.rs` (DriverEntry + `IDD_CX_CLIENT_CONFIG`, 15
|
||||
callbacks), `adapter.rs` (caps + FP16 + `SET_RENDER_ADAPTER`), `monitor.rs`/`callbacks.rs` (the `*2` HDR
|
||||
mode DDIs, EDID verbatim), `swap_chain_processor.rs` (the worker, `SetDevice`-retry + top-of-loop
|
||||
`terminate`), `frame_transport.rs` (the `FramePublisher` on `pf_vdisplay_proto::frame`), `control.rs` (the
|
||||
`terminate`), `frame_transport.rs` (the `FramePublisher` on `pf_driver_proto::frame`), `control.rs` (the
|
||||
typed IOCTL dispatch + host-gone **watchdog** + mode bounds). Self-signed-loadable under Secure Boot
|
||||
(FORCE_INTEGRITY cleared post-link). **Known gaps:** ownership state is still partly process-global
|
||||
(`MONITOR_MODES`/`NEXT_ID`/`ADAPTER`/`DEVICE_POOL`) with `EvtCleanupCallback` on the **WDFDEVICE** (not
|
||||
@@ -198,7 +198,7 @@ These are expensive empirical wins; keep them intact when touching the code:
|
||||
gamepads; the encode|send split + microburst pacing; `build_pipeline_with_retry` permanent-vs-transient
|
||||
classification; the GameStream `VideoPacketizer` (GF8 Cauchy, Moonlight byte-exact); the pairing/trust
|
||||
handshake.
|
||||
- **Core discipline:** no async on the per-frame path; `pf-vdisplay-proto` is the single ABI source
|
||||
- **Core discipline:** no async on the per-frame path; `pf-driver-proto` is the single ABI source
|
||||
(drift = compile error); the version handshake the host asserts.
|
||||
|
||||
---
|
||||
@@ -254,7 +254,7 @@ actually needed.** (`monitor.rs` documents this rationale at the `MONITOR_MODES`
|
||||
9. **M4 — gamepad-driver unification.** Fold `pf_dualsense` + `pf_xusb` (standalone
|
||||
`packaging/windows/{dualsense,xusb}-driver/` on the old WDF stack) into the unified `drivers/` workspace
|
||||
on `windows-drivers-rs` with WDF device contexts (true multi-pad), and point the **driver side** at
|
||||
`pf_vdisplay_proto::gamepad::{PadShm,XusbShm}` (host side already does — the `device_type`-at-offset-140
|
||||
`pf_driver_proto::gamepad::{PadShm,XusbShm}` (host side already does — the `device_type`-at-offset-140
|
||||
hand-duplication is the last ABI-drift hazard). Largest item.
|
||||
10. **M5 — reshape WGC/DDA + GameStream onto `session/pipeline`**, then delete the old relay/monoliths.
|
||||
AMF/QSV stays CI-only (no lab hardware).
|
||||
@@ -291,7 +291,7 @@ queue, so driver pushes that avoid `Cargo.toml` skip the fleet serialization.
|
||||
|
||||
Local pre-push checks (this Linux box can't compile the Windows paths):
|
||||
```sh
|
||||
cargo test -p pf-vdisplay-proto # the ABI crate (cross-platform)
|
||||
cargo test -p pf-driver-proto # the ABI crate (cross-platform)
|
||||
cargo check -p punktfunk-host # Linux paths; win_* mods are #[cfg(windows)]
|
||||
cargo clippy -p punktfunk-host --all-targets -- -D warnings
|
||||
# Windows host clippy (on the box): PUNKTFUNK_NVENC_LIB_DIR=C:\t\nvenc;
|
||||
@@ -370,10 +370,10 @@ exactly correct.
|
||||
under Secure Boot, enumerates as an IddCx adapter, Status OK.)
|
||||
4. control plane (`GET_INFO` version handshake the host asserts, ADD/REMOVE/SET_RENDER_ADAPTER/PING/
|
||||
CLEAR_ALL) + create_monitor + real mode DDIs + watchdog + mode bounds; host switched to
|
||||
`pf_vdisplay_proto`.
|
||||
`pf_driver_proto`.
|
||||
5. `Direct3DDevice` + assign/unassign + `SwapChainProcessor` (worker, `SetDevice` 60×@50 ms single-borrow
|
||||
retry, top-of-loop `terminate`, `ReleaseAndAcquireBuffer2`, `from_raw_borrowed`).
|
||||
6. `FramePublisher` on `pf_vdisplay_proto::frame` + keyed-mutex RAII guard; wire into `run_core`. (Box:
|
||||
6. `FramePublisher` on `pf_driver_proto::frame` + keyed-mutex RAII guard; wire into `run_core`. (Box:
|
||||
full IDD-push glass-to-glass + the **secure-desktop** gate — validated 2026-06-25.)
|
||||
7. HDR / FP16 ring (validated: Mac connects WITH HDR).
|
||||
8. its own `.inx` + an `unsafe`-reduction pass (`deny(unsafe_op_in_unsafe_fn)`, per-site `// SAFETY:`).
|
||||
|
||||
@@ -72,7 +72,7 @@ read it from `%ProgramData%\punktfunk\web-password`.
|
||||
| `../../scripts/windows/web-run.cmd` | The `PunktfunkWeb` task action: loads the mgmt token + login password env, runs the bundled `bun` on the Nitro server (`:3000`). |
|
||||
| `../../scripts/windows/web-setup.ps1` | Install-time (elevated): write the ACL'd console password, register the `PunktfunkWeb` task + firewall rule, start it. |
|
||||
| `pf-vdisplay/` | **Vendored** signed pf-vdisplay driver: `pf_vdisplay.inf` / `pf_vdisplay.cat` / `pf_vdisplay.dll` / `punktfunk-driver.cer`. Built from `drivers/`. |
|
||||
| `drivers/` | The all-Rust IddCx **driver source** workspace: the `pf-vdisplay` crate on `wdk-sys` / windows-drivers-rs + the owned `pf-vdisplay-proto` ABI + `wdk-iddcx` / `wdk-probe`, plus `deploy-dev.ps1` (build/sign/install for dev). |
|
||||
| `drivers/` | The all-Rust IddCx **driver source** workspace: the `pf-vdisplay` crate on `wdk-sys` / windows-drivers-rs + the owned `pf-driver-proto` ABI + `wdk-iddcx` / `wdk-probe`, plus `deploy-dev.ps1` (build/sign/install for dev). |
|
||||
| `reset-pf-vdisplay.ps1` | **Dev:** recover a wedged driver — stop host → reap ghost monitor nodes → reload the adapter → start host (no reboot). See *Dev iteration* below. |
|
||||
| `redeploy-pf-vdisplay.ps1` | **Dev:** one-shot redeploy — (optional) build → stop host → `deploy-dev.ps1 -Install` → reload adapter → start host. |
|
||||
| `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). |
|
||||
|
||||
Generated
+3
-3
@@ -398,7 +398,7 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
name = "pf-vdisplay"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"pf-vdisplay-proto",
|
||||
"pf-driver-proto",
|
||||
"thiserror",
|
||||
"wdk",
|
||||
"wdk-build",
|
||||
@@ -408,7 +408,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pf-vdisplay-proto"
|
||||
name = "pf-driver-proto"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
@@ -776,7 +776,7 @@ dependencies = [
|
||||
name = "wdk-probe"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"pf-vdisplay-proto",
|
||||
"pf-driver-proto",
|
||||
"wdk",
|
||||
"wdk-build",
|
||||
"wdk-sys",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# Separate from the main cargo workspace (own [workspace] root) because driver crates are cdylibs built
|
||||
# with the WDK toolchain (cargo-wdk / wdk-build) on Windows only. Path-deps the shared ABI crate
|
||||
# crates/pf-vdisplay-proto from the main tree.
|
||||
# crates/pf-driver-proto from the main tree.
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["wdk-probe", "wdk-iddcx", "pf-vdisplay"]
|
||||
@@ -20,7 +20,7 @@ wdk = "0.4.1"
|
||||
wdk-sys = "0.5.1"
|
||||
wdk-build = "0.5.1"
|
||||
wdk-iddcx = { path = "wdk-iddcx" }
|
||||
pf-vdisplay-proto = { path = "../../../crates/pf-vdisplay-proto" }
|
||||
pf-driver-proto = { path = "../../../crates/pf-driver-proto" }
|
||||
|
||||
# Vendored windows-drivers-rs 0.5.1 (the published, self-contained crates) + an added `iddcx`
|
||||
# ApiSubset (M1 — bindgens iddcx/1.10/IddCx.h reusing wdk_default for WDF type-identity). Redirect ALL
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite onto wdk-sys + the
|
||||
# owned pf-vdisplay-proto ABI). Replaces the vendored-binding oracle at packaging/windows/vdisplay-driver/
|
||||
# owned pf-driver-proto ABI). Replaces the vendored-binding oracle at packaging/windows/vdisplay-driver/
|
||||
# (deleted once on-glass parity is reached, per docs/windows-host-rewrite.md §14 STEP 8).
|
||||
[package]
|
||||
name = "pf-vdisplay"
|
||||
@@ -23,7 +23,7 @@ wdk-build.workspace = true
|
||||
wdk.workspace = true
|
||||
wdk-sys = { workspace = true, features = ["iddcx"] }
|
||||
wdk-iddcx.workspace = true
|
||||
pf-vdisplay-proto.workspace = true
|
||||
pf-driver-proto.workspace = true
|
||||
# STEP 5: the swap-chain processor's render-side D3D11 device + worker. 0.58.0 matches the wdk-build
|
||||
# transitive `windows` already in the workspace lock (one resolved version) AND the proven oracle's
|
||||
# version, so the ported D3D/DXGI/threading calls compile verbatim.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; pf-vdisplay - punktfunk virtual display, UMDF2 IddCx driver INF (template; stampinf -> .inf).
|
||||
;
|
||||
; For the all-Rust wdk-sys / windows-drivers-rs driver in THIS tree
|
||||
; (packaging/windows/drivers/pf-vdisplay/). The driver registers the OWNED pf_vdisplay_proto
|
||||
; (packaging/windows/drivers/pf-vdisplay/). The driver registers the OWNED pf_driver_proto
|
||||
; control-interface GUID in CODE (WdfDeviceCreateDeviceInterface), so this INF is GUID-agnostic and
|
||||
; is byte-identical to the superseded oracle's (packaging/windows/vdisplay-driver/.../pf_vdisplay.inx,
|
||||
; itself adapted from MolotovCherry/virtual-display-rs (MIT) + SudoVDA's control-device security DACL).
|
||||
|
||||
@@ -327,7 +327,7 @@ pub unsafe extern "C" fn unassign_swap_chain(monitor: iddcx::IDDCX_MONITOR) -> N
|
||||
STATUS_SUCCESS
|
||||
}
|
||||
|
||||
/// The pf-vdisplay-proto control plane. Returns `()` and completes the request itself (matches the C
|
||||
/// The pf-driver-proto control plane. Returns `()` and completes the request itself (matches the C
|
||||
/// `EVT_IDD_CX_DEVICE_IO_CONTROL` shape). STEP 4: dispatch the proto IOCTLs; for now just complete.
|
||||
pub unsafe extern "C" fn device_io_control(
|
||||
_device: WDFDEVICE,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! The `pf-vdisplay-proto` control plane (`EvtIddCxDeviceIoControl`). The host opens the device interface
|
||||
//! The `pf-driver-proto` control plane (`EvtIddCxDeviceIoControl`). The host opens the device interface
|
||||
//! (`PF_VDISPLAY_INTERFACE_GUID`) and drives the low-frequency IOCTLs: GET_INFO (version handshake), PING
|
||||
//! (watchdog keepalive), ADD/REMOVE/CLEAR_ALL (virtual monitors), and SET_RENDER_ADAPTER (next). Every
|
||||
//! path completes the `WDFREQUEST` exactly once (the `EVT_IDD_CX_DEVICE_IO_CONTROL` shape returns `()`).
|
||||
@@ -6,7 +6,7 @@
|
||||
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use pf_vdisplay_proto::control;
|
||||
use pf_driver_proto::control;
|
||||
use wdk_iddcx::nt_success;
|
||||
use wdk_sys::{NTSTATUS, WDFREQUEST, call_unsafe_wdf_function_binding};
|
||||
|
||||
@@ -76,7 +76,7 @@ pub unsafe fn dispatch(request: WDFREQUEST, ioctl_code: u32) {
|
||||
match ioctl_code {
|
||||
control::IOCTL_GET_INFO => {
|
||||
let reply = control::InfoReply {
|
||||
protocol_version: pf_vdisplay_proto::PROTOCOL_VERSION,
|
||||
protocol_version: pf_driver_proto::PROTOCOL_VERSION,
|
||||
watchdog_timeout_s: WATCHDOG_TIMEOUT_S,
|
||||
};
|
||||
// SAFETY: `request` is the framework WDFREQUEST.
|
||||
|
||||
@@ -135,7 +135,7 @@ extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTA
|
||||
// Expose the owned pf-vdisplay control interface: the host opens this GUID and drives the proto control
|
||||
// plane (IOCTL_ADD/REMOVE/PING/…) which arrives at EvtIddCxDeviceIoControl. NOT SudoVDA's GUID. (The
|
||||
// upstream uses a socket instead, so it has no interface; ours is IOCTL-based.)
|
||||
let (d1, d2, d3, d4) = pf_vdisplay_proto::interface_guid_fields();
|
||||
let (d1, d2, d3, d4) = pf_driver_proto::interface_guid_fields();
|
||||
let guid = GUID {
|
||||
Data1: d1,
|
||||
Data2: d2,
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
//!
|
||||
//! Host counterpart: `crates/punktfunk-host/src/capture/idd_push.rs`. The shared `SharedHeader` layout,
|
||||
//! the [`FrameToken`] packing, the `Global\` object-name scheme, the `MAGIC`/`RING_LEN` and the
|
||||
//! `DRV_STATUS_*` codes are NOT hand-duplicated here: both sides `use pf_vdisplay_proto::frame::*`, which
|
||||
//! `DRV_STATUS_*` codes are NOT hand-duplicated here: both sides `use pf_driver_proto::frame::*`, which
|
||||
//! OWNS the contract (with `const` size asserts so any drift is a compile error).
|
||||
//!
|
||||
//! Ported from the proven oracle (`packaging/windows/vdisplay-driver/pf-vdisplay/src/frame_transport.rs`).
|
||||
//! Differences from the oracle:
|
||||
//! * the layout/consts/names/token come from `pf_vdisplay_proto::frame` instead of being re-declared;
|
||||
//! * the layout/consts/names/token come from `pf_driver_proto::frame` instead of being re-declared;
|
||||
//! * `dbglog!` replaces `log::info!`;
|
||||
//! * the optional fixed-name `Global\pfvd-dbg` `DebugBlock` bring-up channel is SKIPPED (not on the data
|
||||
//! path). FOLLOW-UP: if the host bring-up diagnostics are needed again, port the oracle's `DebugBlock`
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
|
||||
|
||||
use pf_vdisplay_proto::frame::{
|
||||
use pf_driver_proto::frame::{
|
||||
DRV_STATUS_NO_DEVICE1, DRV_STATUS_OPENED, DRV_STATUS_TEX_FAIL, FrameToken, MAGIC, RING_LEN,
|
||||
SharedHeader, event_name, header_name, texture_name,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite, on wdk-sys + the
|
||||
//! owned pf-vdisplay-proto ABI). See docs/windows-host-rewrite.md §14 for the full port plan.
|
||||
//! owned pf-driver-proto ABI). See docs/windows-host-rewrite.md §14 for the full port plan.
|
||||
//!
|
||||
//! STEP 2: the IddCx driver SKELETON — DriverEntry → driver_add builds the full `IDD_CX_CLIENT_CONFIG`
|
||||
//! (14 IddCx callbacks + the PnP `EvtDeviceD0Entry`, all stubs) sized via the versioned
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! ([`crate::control`], `IOCTL_ADD`): each carries the requested mode (advertised as preferred) plus the
|
||||
//! `session_id` the host keys it by and the OS target id + render-adapter LUID captured at arrival. Ported
|
||||
//! from the working upstream virtual-display-rs (`monitor.rs` + `context.rs::create_monitor`), with
|
||||
//! `guid: u128` → `session_id: u64` for the owned `pf_vdisplay_proto` control plane.
|
||||
//! `guid: u128` → `session_id: u64` for the owned `pf_driver_proto` control plane.
|
||||
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
@@ -301,7 +301,7 @@ pub fn take_swap_chain_processor(
|
||||
}
|
||||
|
||||
/// `IOCTL_ADD`: create + arrive a virtual monitor at `width`x`height`@`refresh`. Returns the OS
|
||||
/// `(target_id, adapter_luid_low, adapter_luid_high)` for the [`AddReply`](pf_vdisplay_proto::control::AddReply),
|
||||
/// `(target_id, adapter_luid_low, adapter_luid_high)` for the [`AddReply`](pf_driver_proto::control::AddReply),
|
||||
/// or `None` on failure (no adapter yet / IddCx error).
|
||||
pub fn create_monitor(
|
||||
session_id: u64,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# M0/M1 toolchain probe: the smallest possible UMDF2 driver on windows-drivers-rs (crates.io wdk 0.5).
|
||||
# Purpose: prove on the windows-amd64 runner that (1) wdk-sys bindgen + WDF stub link works against the
|
||||
# runner's WDK + LLVM, (2) the shared no_std pf-vdisplay-proto ABI crate path-deps cleanly into a driver
|
||||
# runner's WDK + LLVM, (2) the shared no_std pf-driver-proto ABI crate path-deps cleanly into a driver
|
||||
# build graph, and (3) what the produced DLL's PE FORCE_INTEGRITY (/INTEGRITYCHECK) bit is. NOT shipped.
|
||||
[package]
|
||||
name = "wdk-probe"
|
||||
@@ -26,4 +26,4 @@ wdk.workspace = true
|
||||
# This is the M1 make-or-break: does IddCx.h bindgen in wdk-sys's config without a header conflict, and
|
||||
# do its WDF/DXGI types resolve to wdk-sys's (so the generated module compiles)?
|
||||
wdk-sys = { workspace = true, features = ["iddcx"] }
|
||||
pf-vdisplay-proto.workspace = true
|
||||
pf-driver-proto.workspace = true
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! crate's Cargo.toml). DriverEntry → WdfDriverCreate → (EvtDeviceAdd) IddCxDeviceInitConfig →
|
||||
//! WdfDeviceCreate → IddCxDeviceInitialize → IddCxAdapterInitAsync: enough to exercise the wdk-sys WDF
|
||||
//! stub link AND prove the `iddcx` subset is callable + links against `IddCxStub`. Also force-links the
|
||||
//! shared `pf-vdisplay-proto` ABI crate (no_std + bytemuck) across the workspace boundary.
|
||||
//! shared `pf-driver-proto` ABI crate (no_std + bytemuck) across the workspace boundary.
|
||||
|
||||
#![allow(non_snake_case, clippy::missing_safety_doc)]
|
||||
|
||||
@@ -18,10 +18,10 @@ use wdk_sys::{
|
||||
|
||||
const STATUS_SUCCESS: NTSTATUS = 0;
|
||||
|
||||
/// Force `pf-vdisplay-proto` to actually link into the driver build graph (validates the cross-workspace
|
||||
/// Force `pf-driver-proto` to actually link into the driver build graph (validates the cross-workspace
|
||||
/// path-dep + that the no_std bytemuck ABI crate compiles for a UMDF cdylib). `#[used]` keeps it.
|
||||
#[used]
|
||||
static PROTO_GUID_LO: u64 = pf_vdisplay_proto::PF_VDISPLAY_INTERFACE_GUID_U128 as u64;
|
||||
static PROTO_GUID_LO: u64 = pf_driver_proto::PF_VDISPLAY_INTERFACE_GUID_U128 as u64;
|
||||
|
||||
/// IddCx (stub mode) requires the driver to export the minimum IddCx framework version it needs — the
|
||||
/// `#ifndef IDD_STUB` branch of `IddCxFuncEnum.h` (which normally emits it) is compiled out under
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; pf-vdisplay - punktfunk virtual display, UMDF2 IddCx driver INF (template; stampinf -> .inf).
|
||||
;
|
||||
; For the all-Rust wdk-sys / windows-drivers-rs driver in THIS tree
|
||||
; (packaging/windows/drivers/pf-vdisplay/). The driver registers the OWNED pf_vdisplay_proto
|
||||
; (packaging/windows/drivers/pf-vdisplay/). The driver registers the OWNED pf_driver_proto
|
||||
; control-interface GUID in CODE (WdfDeviceCreateDeviceInterface), so this INF is GUID-agnostic and
|
||||
; is byte-identical to the superseded oracle's (packaging/windows/vdisplay-driver/.../pf_vdisplay.inx,
|
||||
; itself adapted from MolotovCherry/virtual-display-rs (MIT) + SudoVDA's control-device security DACL).
|
||||
|
||||
Reference in New Issue
Block a user