diff --git a/docs/windows-host-rewrite.md b/docs/windows-host-rewrite.md index de9e49e..9a8857b 100644 --- a/docs/windows-host-rewrite.md +++ b/docs/windows-host-rewrite.md @@ -615,3 +615,68 @@ What remains are **technical unknowns to confirm on the RTX box** (not user deci - **Big-bang cutover (M6).** Flipping the default and deleting the old monoliths is the riskiest moment; it is gated on the full A/B matrix passing, and the old code is recoverable from git if a regression surfaces post-cutover. + +--- + +## 13. Progress log + M1 IddCx-binding recipe (2026-06-24) + +**M0 COMPLETE** (commits through `f896f70`, on `main`, CI-green + validated on the RTX box): +- `crates/pf-vdisplay-proto` — owned host↔driver ABI (fresh GUID, typed IOCTLs + frame transport, const + size-asserts). Green Linux + MSVC. +- Runner **and** RTX box provisioned: WDK 26100 (WDF 2.31, IddCx 1.10), LLVM **21.1.2** (the runner's + default was a ToT/22-dev build → wdk-sys bindgen `E0080` layout-test overflow; 21.1.2 builds clean — + windows-drivers-rs discussion #591). cargo-wdk on the runner. +- `packaging/windows/drivers/` — unified driver workspace on windows-drivers-rs; `wdk-probe` (minimal + UMDF) builds clean end-to-end (bindgen + WDF link + static-CRT `.cargo/config` + `pf-vdisplay-proto` + path-dep). Build layers solved: in-tree target dir (wdk-build walks OUT_DIR ancestors for `Cargo.lock`); + `[workspace.metadata.wdk.driver-model]` = UMDF 2.31; `target-feature=+crt-static` w/ explicit target; + `Version_Number=10.0.26100.0`; `LIBCLANG_PATH` → LLVM 21.1.2. +- **`/INTEGRITYCHECK` resolved**: wdk-build sets it unconditionally (no opt-out) → `packaging/windows/ + clear-force-integrity.ps1` clears the PE `FORCE_INTEGRITY` bit (0x0080 @ e_lfanew+0x5e) post-link, + before signing. Proven `0x01E0→0x0160` on CI and in PS 5.1 on the box. Self-signed UMDF load itself is + already proven on the box (the gamepad drivers). + +**RTX box** (`ssh "Enrico Bühler"@192.168.1.173`, ENRICOS-DESKTOP, RTX 4090 driver 610.62, PS 5.1 shell): +**ephemeral** — boots to Proxmox on reboot, so unreachable after a reboot. Treat as opportunistic on-glass +(driver load + IDD-push streaming) only; **CI on the windows-amd64 runner is the persistent validator**. +A build clone is at `C:\Users\Public\pf-rewrite`; builds the driver in ~29 s with the box's LLVM 21.1.2. + +### M1 — IddCx binding on windows-drivers-rs (the recipe) + +IddCx DDIs are **function-table dispatched** (`IddFunctions[]` indexed by `IDDFUNCENUM::TableIndex`, +`IddDriverGlobals` implicit first arg) — *exactly* the model wdk-sys already implements for WDF (not direct +`IddCxStub` exports as first assumed). + +**Approach (Option 1, recommended):** vendor windows-drivers-rs **0.5.1** in-tree (pinned; source staged at +`scratchpad/wdr`, commit `0e3499d`), patched via `[patch.crates-io]` for just `wdk-build` + `wdk-sys`, and +add a first-class **`ApiSubset::Iddcx`** that bindgens `iddcx/1.10/IddCx.h` in an extra pass **reusing the +identical `bindgen::Builder::wdk_default(config)` baseline** (so its WDF/DXGI types *resolve to*, not +redefine, wdk-sys's — type identity by construction). This mirrors wdk-sys's existing gpio/hid/spb/usb +versioned-subpath subsets exactly. +- wdk-build: add `ApiSubset::Iddcx`, a `headers` match arm, `iddcx_headers() -> ["iddcx/1.10/IddCx.h"]` + (UMDF-only). +- wdk-sys build.rs: `generate_iddcx` as a copy of `generate_gpio` — `bindgen_header_contents([Base, Wdf, + Iddcx])`, `(TYPES|VARS).complement()`, `.allowlist_file("(?i).*iddcx.*")`; behind an `iddcx` feature; + add to `ENABLED_API_SUBSETS`; `pub mod iddcx` in lib.rs. +- A `wdk-iddcx` wrapper crate (port of `wdf-umdf/src/iddcx.rs`): table dispatch via + `wdk_sys::iddcx::_IDDFUNCENUM::TableIndex as usize` (ModuleConsts const, **not** the oracle's + NewType `.0`); NTSTATUS is plain `i32` in wdk-sys (use `wdk_sys::NT_SUCCESS`, drop the oracle's newtype). +- Driver build.rs: add `link-search` to `Lib//um//iddcx/1.10` (the SDK version that *contains* + iddcx — glob, don't trust max) + `static=IddCxStub`; hand-declare `#[no_mangle] pub static + IddMinimumVersionRequired: ULONG = 4;`; keep the FORCE_INTEGRITY clear. + +**Make-or-break (the spike to run FIRST):** can `IddCx.h` bindgen in wdk-sys's config without a header +conflict? (upstream #514/#516; clean-fix PR #654 is **unmerged**.) Validate by adding the subset + an +`iddcx-probe` that calls `IddCxDeviceInitConfig`/`IddCxDeviceInitialize`/`IddCxAdapterInitAsync` → +**CI gate**: cdylib compiles + links IddCxStub. **On-glass gate (RTX box)**: self-signed driver loads + +the IddCx adapter initializes (runtime table/struct-index correctness only surfaces here). Possible gotcha: +IddCx.h may need an `IDD_STUB` preprocessor define to emit the table model (the oracle's wrapper.h set it). + +**Fallback** if the bindgen header-conflict can't be resolved: keep the proven vendored unified +`wdf-umdf-sys` as a second `-sys` crate for `pf-vdisplay` only (a second stack, contra Decision C, but +already green + on-glass-proven) and track upstream #654. **Reject** Option 2 (standalone `iddcx-sys` + +`use wdk_sys::*` + giant WDF/DXGI blocklist) — version-fragile, structs embed WDF/DXGI by value. + +Only after the spike passes: port the full ~30-DDI / ~40-struct surface (incl. the HDR `*2` DDIs) + the +swap-chain processor + frame transport, with the clean ownership model (DeviceContext-owned state, +`EvtCleanupCallback` on `MonitorContext`, single `Monitor` identity, the owned `pf-vdisplay-proto` plane).