mirror of
https://github.com/ddeverill/SteamlessController.git
synced 2026-10-18 20:59:45 -05:00
vigem_target_add() plugs the child device in with IOCTL_VIGEM_PLUGIN_TARGET, then waits for it to come up with IOCTL_VIGEM_WAIT_DEVICE_READY. When that wait fails, the cleanup path calls vigem_target_remove() -- but target->State is only set to VIGEM_TARGET_CONNECTED on the two success paths above it, so the removal trips its own "State != VIGEM_TARGET_CONNECTED" guard and returns without ever sending IOCTL_VIGEM_UNPLUG_TARGET. The device stays plugged into the bus with no owning process, holding an XInput slot until the machine reboots. Observed locally: a pad created at 19:57:25 outlived the app by five hours and several sessions, and every later session had to take the next serial. The rapid enable/disable churn during device cycling is what triggers the wait timeout in the first place. Mark the target connected before the cleanup so the unplug is actually sent, and pin the return to VIGEM_ERROR_TARGET_NOT_PLUGGED_IN -- a successful unplug would otherwise report VIGEM_ERROR_NONE and register a target in pTargetsList that is no longer plugged in. This is a local patch to the vendored b66d02d ViGEmClient snapshot; upstream is archived, so no future sync will bring it in. Also: - VirtualController records which ViGEm call failed and its error code; ControllerManager logs both. The old driverMissing line could not distinguish a missing bus from a failed target add, which is exactly the distinction needed to spot this leak. - ShowViGEmBalloon() now latches the way ShowElevationBalloon() already did. Every failed enable calls back into UpdateTrayIcon -- several times a second during an acquire-retry loop -- so an unavailable driver produced a wall of identical balloons. The latch clears once the driver is reachable again so a genuine mid-session disappearance still warns. UpdateTrayIcon no longer returns early on vigemMissing, so the icon and tooltip keep tracking the controller instead of freezing. - Reword that balloon: a disabled bus devnode reports the same VIGEM_ERROR_BUS_NOT_FOUND as an uninstalled one, and "is not installed" sends users looking in the wrong place. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>