From: Shaun Ren <sren@codeweavers.com> If a requested controller slot is not currently open, rescan the controllers before reporting the slot as disconnected. This matches native Windows behaviour. The game RiME (and possibly others), upon receiving a device addition WM_DEVICECHANGE message, immediately queries all four slots with XInputGetState(), and gives up if none are unavailable. Without the rescan, the game's query can race with the xinput update thread and cause hotplugging failure. --- dlls/xinput1_3/main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index 26098209020..95ed2d8b639 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -865,6 +865,13 @@ static BOOL controller_lock(struct xinput_controller *controller) return TRUE; } +static BOOL controller_lock_or_rescan(struct xinput_controller *controller) +{ + if (controller_lock(controller)) return TRUE; + update_controller_list(); + return controller_lock(controller); +} + static void controller_unlock(struct xinput_controller *controller) { LeaveCriticalSection(&controller->crit); @@ -918,7 +925,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION *vib start_update_thread(); if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; - if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + if (!controller_lock_or_rescan(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; ret = HID_set_state(&controllers[index], vibration); @@ -936,7 +943,7 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state) start_update_thread(); if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; - if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + if (!controller_lock_or_rescan(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; *state = controllers[index].state; controller_unlock(&controllers[index]); @@ -1223,7 +1230,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilitiesEx(DWORD unk, DWORD index, D if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; - if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + if (!controller_lock_or_rescan(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) ret = ERROR_DEVICE_NOT_CONNECTED; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11158