This fixes hotplug with DS4 and other DInput-compatible controllers in Tekken 7.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 8 ++++++-- dlls/dinput/device_private.h | 1 + dlls/dinput/dinput_main.c | 8 +++++--- dlls/dinput/joystick_hid.c | 4 ++-- dlls/dinput/tests/joystick8.c | 5 ----- 5 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 47cf4d72dc3..ff8e2252a40 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1553,7 +1553,9 @@ static HRESULT WINAPI dinput_device_GetDeviceState( IDirectInputDevice8W *iface, IDirectInputDevice2_Poll( iface );
EnterCriticalSection( &impl->crit ); - if (impl->status != STATUS_ACQUIRED) + if (impl->status == STATUS_UNPLUGGED) + hr = DIERR_INPUTLOST; + else if (impl->status != STATUS_ACQUIRED) hr = DIERR_NOTACQUIRED; else if (!(user_format = impl->user_format)) hr = DIERR_INVALIDPARAM; @@ -1605,6 +1607,7 @@ static HRESULT WINAPI dinput_device_GetDeviceData( IDirectInputDevice8W *iface, if (This->dinput->dwVersion == 0x0800 || size == sizeof(DIDEVICEOBJECTDATA_DX3)) { if (!This->queue_len) return DIERR_NOTBUFFERED; + if (This->status == STATUS_UNPLUGGED) return DIERR_INPUTLOST; if (This->status != STATUS_ACQUIRED) return DIERR_NOTACQUIRED; }
@@ -1857,7 +1860,8 @@ static HRESULT WINAPI dinput_device_Poll( IDirectInputDevice8W *iface ) HRESULT hr = DI_NOEFFECT;
EnterCriticalSection( &impl->crit ); - if (impl->status != STATUS_ACQUIRED) hr = DIERR_NOTACQUIRED; + if (impl->status == STATUS_UNPLUGGED) hr = DIERR_INPUTLOST; + else if (impl->status != STATUS_ACQUIRED) hr = DIERR_NOTACQUIRED; LeaveCriticalSection( &impl->crit ); if (FAILED(hr)) return hr;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 7865c3a15a9..15a8a6f83b5 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -73,6 +73,7 @@ enum device_status { STATUS_UNACQUIRED, STATUS_ACQUIRED, + STATUS_UNPLUGGED, };
/* Device implementation */ diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 664311b7a31..dbb727c3c43 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -1261,7 +1261,6 @@ static DWORD WINAPI dinput_thread_proc( void *params ) struct dinput_device *impl, *next; SIZE_T events_count = 0; HANDLE finished_event; - HRESULT hr; DWORD ret; MSG msg;
@@ -1282,8 +1281,11 @@ static DWORD WINAPI dinput_thread_proc( void *params ) { if (impl->read_event == events[ret]) { - hr = impl->vtbl->read( &impl->IDirectInputDevice8W_iface ); - if (FAILED( hr )) dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface ); + if (FAILED( impl->vtbl->read( &impl->IDirectInputDevice8W_iface ) )) + { + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface ); + impl->status = STATUS_UNPLUGGED; + } break; } } diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 4caaf01affe..597a3da4ef8 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -872,7 +872,7 @@ static HRESULT hid_joystick_acquire( IDirectInputDevice8W *iface ) { impl->device = CreateFileW( impl->device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, 0 ); - if (impl->device == INVALID_HANDLE_VALUE) return DIERR_INVALIDPARAM; + if (impl->device == INVALID_HANDLE_VALUE) return DIERR_UNPLUGGED; }
memset( &impl->read_ovl, 0, sizeof(impl->read_ovl) ); @@ -882,7 +882,7 @@ static HRESULT hid_joystick_acquire( IDirectInputDevice8W *iface ) { CloseHandle( impl->device ); impl->device = INVALID_HANDLE_VALUE; - return DIERR_INVALIDPARAM; + return DIERR_UNPLUGGED; }
IDirectInputDevice8_SendForceFeedbackCommand( iface, DISFFC_RESET ); diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 9c7200d3202..81c3b2069ba 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -3029,20 +3029,15 @@ static void test_input_lost( DWORD version ) pnp_driver_stop();
hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state ); - todo_wine ok( hr == DIERR_INPUTLOST, "GetDeviceState returned %#x\n", hr ); hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state ); - todo_wine ok( hr == DIERR_INPUTLOST, "GetDeviceState returned %#x\n", hr ); hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &count, DIGDD_PEEK ); - todo_wine ok( hr == DIERR_INPUTLOST, "GetDeviceData returned %#x\n", hr ); hr = IDirectInputDevice8_Poll( device ); - todo_wine ok( hr == DIERR_INPUTLOST, "Poll returned: %#x\n", hr );
hr = IDirectInputDevice8_Acquire( device ); - todo_wine ok( hr == DIERR_UNPLUGGED, "Acquire returned %#x\n", hr ); hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state ); ok( hr == DIERR_NOTACQUIRED, "GetDeviceState returned %#x\n", hr );