Files
SteamlessController/third_party
Dylan DeverillandClaude Opus 5 9ef3609da5 Fix orphaned ViGEm pads left behind by a failed target add (#52)
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>
2026-08-05 01:15:29 -07:00
..
2026-05-10 19:28:03 -07:00