forked from unom/punktfunk
A woken Windows host refused every connection with "pf-vdisplay driver interface not found", on a box where the driver was installed and running. Resuming re-enters D0 and re-registers the IddCx control interface while the rest of the resume storm is still going. A client reconnecting a second after wake lands inside that gap. `ensure_available` probed exactly ONCE, so it read the gap as a dead driver and answered a device that was seconds from ready by disabling and re-enabling it — then gave the interface 4 s to come back, which a contended post-resume PnP does not meet. The session failed, and the log blamed a missing install. The recovery also could not tell whether it had recovered anything. It ran the whole cycle under `SilentlyContinue` and reported `(Get-PnpDevice).Status` — the DEVICE's status, not the cycle's outcome — so a disable that was REFUSED left the adapter untouched, started, and reading `OK`. That is the reporter's `cycled the adapter device … status=OK` line: a recovery that never happened, announcing success. And a refusal is the expected case here, not the exotic one: reset-pf-vdisplay.ps1 stops the host service first precisely because the host holds the driver's control device open, a step an in-process cycle structurally cannot take. - Distinguish a devnode MID-TRANSITION (interface registered, not started yet, or the open refused) from one genuinely ABSENT. Wait the first out; only the second earns a reload. `Probe` carries the counts. - Report what the reload DID, not what the device looks like afterwards: every failable step is `-ErrorAction Stop` in a `try`, and `pnputil /restart-device` is the fallback for the in-use device that `Disable-PnpDevice` refuses. Failure paths re-enable, so a half-cycle can never strand the adapter DISABLED. - Give the interface 15 s to arrive after a reload, not 4 — under a 30 s hard ceiling so a permanently wedged devnode still fails predictably. - Serialize recovery: N sessions racing in after a wake perform ONE reload, not N interleaved ones. The lock is taken only where no manager lock is held, so the order stays one-way. - Retire the manager's cached control handle when a reload runs, instead of letting the next session discover it via a failed IOCTL. - Surface the real reason. `ensure_available` returns `Result`, so the log names how long it waited, whether a reload ran, and how many interface instances were seen in what state — the detail that would have identified this from the field report's log alone. `VdisplayDriver::open` now shares the wait (brief, no reload) instead of carrying a second, drifted copy of it — that path is also reached by `hw_cursor_capable` mid-handshake, where a reload would be the wrong trade for one capability bool. Windows-gated, so verified with scripts/xcheck.sh (check + clippy -D warnings, --all-targets) and cargo fmt; on-glass wake test still owed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>