00cf51d610
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>
87 lines
4.2 KiB
Rust
87 lines
4.2 KiB
Rust
//! Minimal UMDF2 driver — the M0/M1 toolchain + `/INTEGRITYCHECK` + IddCx-binding probe (see this
|
|
//! 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-driver-proto` ABI crate (no_std + bytemuck) across the workspace boundary.
|
|
|
|
#![allow(non_snake_case, clippy::missing_safety_doc)]
|
|
|
|
mod iddcx_rt;
|
|
mod iddcx_surface_assert;
|
|
|
|
use wdk_sys::iddcx::{IDARG_IN_ADAPTER_INIT, IDARG_OUT_ADAPTER_INIT, IDD_CX_CLIENT_CONFIG};
|
|
use wdk_sys::{
|
|
NTSTATUS, PCUNICODE_STRING, PDRIVER_OBJECT, PWDFDEVICE_INIT, ULONG, WDF_DRIVER_CONFIG,
|
|
WDF_NO_HANDLE, WDF_NO_OBJECT_ATTRIBUTES, WDFDEVICE, WDFDRIVER,
|
|
call_unsafe_wdf_function_binding,
|
|
};
|
|
|
|
const STATUS_SUCCESS: NTSTATUS = 0;
|
|
|
|
/// 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_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
|
|
/// `IDD_STUB`, so the driver provides it. `4` matches the proven `wdf-umdf` oracle.
|
|
#[unsafe(no_mangle)]
|
|
pub static IddMinimumVersionRequired: ULONG = 4;
|
|
|
|
#[unsafe(export_name = "DriverEntry")]
|
|
pub unsafe extern "system" fn driver_entry(
|
|
driver: PDRIVER_OBJECT,
|
|
registry_path: PCUNICODE_STRING,
|
|
) -> NTSTATUS {
|
|
// SAFETY: zeroed then Size + the device-add callback set, per the WDF_DRIVER_CONFIG contract.
|
|
let mut config: WDF_DRIVER_CONFIG = unsafe { core::mem::zeroed() };
|
|
config.Size = core::mem::size_of::<WDF_DRIVER_CONFIG>() as ULONG;
|
|
config.EvtDriverDeviceAdd = Some(evt_device_add);
|
|
// SAFETY: driver + registry_path are the loader-provided pointers; config is valid for the call.
|
|
unsafe {
|
|
call_unsafe_wdf_function_binding!(
|
|
WdfDriverCreate,
|
|
driver,
|
|
registry_path,
|
|
WDF_NO_OBJECT_ATTRIBUTES,
|
|
&mut config,
|
|
WDF_NO_HANDLE.cast::<WDFDRIVER>()
|
|
)
|
|
}
|
|
}
|
|
|
|
extern "C" fn evt_device_add(_driver: WDFDRIVER, mut device_init: PWDFDEVICE_INIT) -> NTSTATUS {
|
|
// Configure the device for IddCx BEFORE WdfDeviceCreate. The required `EvtIddCx*` callbacks are left
|
|
// null in this probe — its purpose is to prove the `iddcx` DDIs are callable and link against
|
|
// IddCxStub (CI), and that a self-signed IddCx driver loads + dispatches (box); the full callback
|
|
// surface + a valid adapter come with the driver port. At runtime IddCxDeviceInitConfig will reject
|
|
// the null callbacks, but the call site is what links IddCxStub and exercises table dispatch.
|
|
let mut cfg: IDD_CX_CLIENT_CONFIG = unsafe { core::mem::zeroed() };
|
|
cfg.Size = core::mem::size_of::<IDD_CX_CLIENT_CONFIG>() as ULONG;
|
|
// SAFETY: device_init is the framework-provided init; cfg is a valid (if minimal) config.
|
|
let _ = unsafe { iddcx_rt::IddCxDeviceInitConfig(device_init, &cfg) };
|
|
|
|
let mut device: WDFDEVICE = core::ptr::null_mut();
|
|
// SAFETY: device_init is the framework-provided init; attributes null; device receives the handle.
|
|
let _ = unsafe {
|
|
call_unsafe_wdf_function_binding!(
|
|
WdfDeviceCreate,
|
|
&mut device_init,
|
|
WDF_NO_OBJECT_ATTRIBUTES,
|
|
&mut device
|
|
)
|
|
};
|
|
|
|
// SAFETY: device is the just-created WDFDEVICE.
|
|
let _ = unsafe { iddcx_rt::IddCxDeviceInitialize(device) };
|
|
|
|
// SAFETY: zeroed adapter-init args — a link/dispatch reference, not a valid adapter (see above).
|
|
let in_args: IDARG_IN_ADAPTER_INIT = unsafe { core::mem::zeroed() };
|
|
let mut out_args: IDARG_OUT_ADAPTER_INIT = unsafe { core::mem::zeroed() };
|
|
// SAFETY: in/out args are valid local storage for the call.
|
|
let _ = unsafe { iddcx_rt::IddCxAdapterInitAsync(&in_args, &mut out_args) };
|
|
|
|
STATUS_SUCCESS
|
|
}
|