feat(windows-drivers): STEP 4 (1/n) — control-plane IOCTL dispatch (GET_INFO + PING)
apple / swift (push) Successful in 1m8s
windows-drivers / probe-and-proto (push) Successful in 18s
apple / screenshots (push) Failing after 1m34s
windows-drivers / driver-build (push) Successful in 1m3s
windows-host / package (push) Successful in 5m11s
android / android (push) Successful in 4m7s
ci / web (push) Successful in 48s
ci / rust (push) Successful in 4m42s
ci / docs-site (push) Successful in 55s
deb / build-publish (push) Successful in 2m15s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
ci / bench (push) Successful in 4m42s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m20s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m39s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m38s
docker / deploy-docs (push) Successful in 6s
apple / swift (push) Successful in 1m8s
windows-drivers / probe-and-proto (push) Successful in 18s
apple / screenshots (push) Failing after 1m34s
windows-drivers / driver-build (push) Successful in 1m3s
windows-host / package (push) Successful in 5m11s
android / android (push) Successful in 4m7s
ci / web (push) Successful in 48s
ci / rust (push) Successful in 4m42s
ci / docs-site (push) Successful in 55s
deb / build-publish (push) Successful in 2m15s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
ci / bench (push) Successful in 4m42s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m20s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m39s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m38s
docker / deploy-docs (push) Successful in 6s
EvtIddCxDeviceIoControl now dispatches the pf-vdisplay-proto control plane (new
src/control.rs): IOCTL_GET_INFO writes InfoReply{protocol_version, watchdog_timeout_s}
(the host asserts the version + fails loudly on mismatch), IOCTL_PING bumps the watchdog
keepalive. ADD/REMOVE/SET_RENDER_ADAPTER/CLEAR_ALL are dispatched but stubbed
(STATUS_NOT_IMPLEMENTED) pending create_monitor + the real mode DDIs (next). Unknown
IOCTLs -> STATUS_NOT_FOUND. Builds CI-green; warnings are the *2/HDR stubs (STEP 7) +
the stored adapter handle (read by create_monitor, next).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
//! is implemented now because it gates HDR (`HIGH_COLOR_SPACE`) and the adapter (STEP 3) sets FP16.
|
||||
|
||||
use wdk_sys::iddcx;
|
||||
use wdk_sys::{call_unsafe_wdf_function_binding, NTSTATUS, WDFDEVICE, WDFREQUEST};
|
||||
use wdk_sys::{NTSTATUS, WDFDEVICE, WDFREQUEST};
|
||||
|
||||
use crate::{STATUS_NOT_IMPLEMENTED, STATUS_SUCCESS};
|
||||
|
||||
@@ -143,10 +143,8 @@ pub unsafe extern "C" fn device_io_control(
|
||||
request: WDFREQUEST,
|
||||
_output_len: usize,
|
||||
_input_len: usize,
|
||||
_ioctl_code: u32,
|
||||
ioctl_code: u32,
|
||||
) {
|
||||
// SAFETY: `request` is the framework-provided WDFREQUEST; completing it hands it back to the OS.
|
||||
unsafe {
|
||||
call_unsafe_wdf_function_binding!(WdfRequestComplete, request, STATUS_SUCCESS);
|
||||
}
|
||||
// SAFETY: `request` is the framework-provided WDFREQUEST; `control::dispatch` completes it exactly once.
|
||||
unsafe { crate::control::dispatch(request, ioctl_code) };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
//! The `pf-vdisplay-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), and — STEP 4 (next) — ADD/REMOVE/SET_RENDER_ADAPTER/CLEAR_ALL for virtual
|
||||
//! monitors. Every path completes the `WDFREQUEST` exactly once (the `EVT_IDD_CX_DEVICE_IO_CONTROL` shape
|
||||
//! returns `()`).
|
||||
|
||||
use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use pf_vdisplay_proto::control;
|
||||
use wdk_iddcx::nt_success;
|
||||
use wdk_sys::{call_unsafe_wdf_function_binding, NTSTATUS, WDFREQUEST};
|
||||
|
||||
use crate::{STATUS_NOT_FOUND, STATUS_NOT_IMPLEMENTED, STATUS_SUCCESS};
|
||||
|
||||
/// The host must PING within this window or the watchdog reaps all monitors (STEP 4: the watchdog thread).
|
||||
const WATCHDOG_TIMEOUT_S: u32 = 10;
|
||||
|
||||
/// Keepalive counter — PING bumps it; STEP 4's watchdog thread samples it to detect a gone host.
|
||||
static WATCHDOG_PINGS: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
/// Dispatch one control IOCTL and complete the request.
|
||||
///
|
||||
/// # Safety
|
||||
/// `request` is the framework-provided `WDFREQUEST` for an `EvtIddCxDeviceIoControl` call.
|
||||
pub unsafe fn dispatch(request: WDFREQUEST, ioctl_code: u32) {
|
||||
match ioctl_code {
|
||||
control::IOCTL_GET_INFO => unsafe { get_info(request) },
|
||||
control::IOCTL_PING => {
|
||||
WATCHDOG_PINGS.fetch_add(1, Ordering::Relaxed);
|
||||
complete(request, STATUS_SUCCESS);
|
||||
}
|
||||
// STEP 4 (next): ADD -> create_monitor, REMOVE, SET_RENDER_ADAPTER, CLEAR_ALL.
|
||||
control::IOCTL_ADD
|
||||
| control::IOCTL_REMOVE
|
||||
| control::IOCTL_SET_RENDER_ADAPTER
|
||||
| control::IOCTL_CLEAR_ALL => complete(request, STATUS_NOT_IMPLEMENTED),
|
||||
_ => complete(request, STATUS_NOT_FOUND),
|
||||
}
|
||||
}
|
||||
|
||||
/// `IOCTL_GET_INFO`: write [`control::InfoReply`] (protocol version + watchdog timeout). The host asserts
|
||||
/// `protocol_version == PROTOCOL_VERSION` and fails loudly on a mismatch.
|
||||
///
|
||||
/// # Safety
|
||||
/// `request` is the framework `WDFREQUEST`.
|
||||
unsafe fn get_info(request: WDFREQUEST) {
|
||||
let reply = control::InfoReply {
|
||||
protocol_version: pf_vdisplay_proto::PROTOCOL_VERSION,
|
||||
watchdog_timeout_s: WATCHDOG_TIMEOUT_S,
|
||||
};
|
||||
let mut buf: *mut core::ffi::c_void = core::ptr::null_mut();
|
||||
let mut len: usize = 0;
|
||||
// SAFETY: `request` is valid; `buf`/`len` are out-params written by the framework.
|
||||
let st = unsafe {
|
||||
call_unsafe_wdf_function_binding!(
|
||||
WdfRequestRetrieveOutputBuffer,
|
||||
request,
|
||||
core::mem::size_of::<control::InfoReply>(),
|
||||
&mut buf,
|
||||
&mut len
|
||||
)
|
||||
};
|
||||
if !nt_success(st) || buf.is_null() {
|
||||
complete(request, st);
|
||||
return;
|
||||
}
|
||||
// SAFETY: `buf` has >= size_of::<InfoReply>() writable bytes (validated above); InfoReply is Pod.
|
||||
unsafe { buf.cast::<control::InfoReply>().write_unaligned(reply) };
|
||||
complete_info(request, STATUS_SUCCESS, core::mem::size_of::<control::InfoReply>());
|
||||
}
|
||||
|
||||
/// Complete a request with just a status (no output).
|
||||
fn complete(request: WDFREQUEST, status: NTSTATUS) {
|
||||
// SAFETY: completing hands the framework `WDFREQUEST` back to the OS.
|
||||
unsafe { call_unsafe_wdf_function_binding!(WdfRequestComplete, request, status) };
|
||||
}
|
||||
|
||||
/// Complete a request with a status + the number of output bytes written.
|
||||
fn complete_info(request: WDFREQUEST, status: NTSTATUS, info: usize) {
|
||||
// SAFETY: completing hands the framework `WDFREQUEST` back to the OS.
|
||||
unsafe {
|
||||
call_unsafe_wdf_function_binding!(WdfRequestCompleteWithInformation, request, status, info as u64)
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
mod log;
|
||||
mod adapter;
|
||||
mod callbacks;
|
||||
mod control;
|
||||
#[allow(dead_code)] // salvaged verbatim; wired into the mode callbacks in STEP 4
|
||||
mod edid;
|
||||
mod entry;
|
||||
|
||||
Reference in New Issue
Block a user