From 1a7e3a6e4fe70d3816646bf1f8e4b3b1c425d32c Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 16 Jul 2026 17:45:27 +0200 Subject: [PATCH] fix(host/windows): propagate XUSB devnode-create failure instead of latching a phantom pad MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XusbWinPad::open swallowed a SwDeviceCreate failure — it returned Ok with `_sw: None` (a pad with no devnode) and logged only a warn, so PadSlots latched a phantom pad, called gate.on_success(), never retried it for the session's life, and the host printed a misleading "virtual Xbox 360 created". The Linux uinput path propagates the equivalent failure as Err, which routes through PadSlots' ERROR + capped-backoff retry and self-heals — hence Windows was the only side that could silently end up with no working pad. Propagate the create failure with `?` so Windows gets the same ERROR + backoff retry as Linux. Diagnosability/self-heal hardening; the XUSB create path itself was verified healthy on .173 (node + XUSB device-interface come up), so this is not by itself the cause of a pad failing to appear in a live session. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/inject/windows/gamepad_windows.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/punktfunk-host/src/inject/windows/gamepad_windows.rs b/crates/punktfunk-host/src/inject/windows/gamepad_windows.rs index 5297118f..53a99481 100644 --- a/crates/punktfunk-host/src/inject/windows/gamepad_windows.rs +++ b/crates/punktfunk-host/src/inject/windows/gamepad_windows.rs @@ -159,14 +159,13 @@ impl XusbWinPad { std::ptr::write_unaligned(base.add(OFF_PAD_INDEX) as *mut u32, index as u32); std::ptr::write_unaligned(base as *mut u32, SHM_MAGIC); } - let (hsw, instance_id) = match create_swdevice(index) { - Ok((h, id)) => (Some(h), id), - Err(e) => { - tracing::warn!(error = %format!("{e:#}"), "SwDeviceCreate failed; XUSB devnode unavailable"); - (None, None) - } - }; - let _sw = hsw.map(super::gamepad_raii::SwDevice::new); + // Propagate a devnode-create failure instead of swallowing it: a swallowed failure left the + // pad with no devnode yet still reported success, so PadSlots latched a phantom pad (never + // re-created for the session's life) and the host logged a misleading "virtual Xbox 360 + // created". Returning Err routes it through PadSlots' ERROR + capped-backoff retry — parity + // with the Linux uinput path, which self-heals for exactly this reason. + let (hsw, instance_id) = create_swdevice(index)?; + let _sw = Some(super::gamepad_raii::SwDevice::new(hsw)); // Bounded eager delivery: the driver's EvtDeviceAdd publishes its pid right away; handing it // the DATA handle before we return means the pad is live for the game's first XInput poll. // On a missing/old driver this waits out the window once and the service pump takes over.