[PATCH 7/7] dinput: Return DIERR_INPUTLOST when device is removed.

Rémi Bernon rbernon at codeweavers.com
Thu Jan 20 02:28:45 CST 2022


This fixes hotplug with DS4 and other DInput-compatible controllers in
Tekken 7.

Signed-off-by: Rémi Bernon <rbernon at 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 );
-- 
2.34.1




More information about the wine-devel mailing list