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 | 33 ++++++++++++++++++++------------- dlls/dinput/device_private.h | 9 ++++++++- dlls/dinput/dinput_main.c | 4 ++-- dlls/dinput/joystick_hid.c | 6 +++--- dlls/dinput/tests/joystick8.c | 5 ----- 5 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 5f8227acd0c..d3e84edb642 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -84,7 +84,7 @@ static inline const char *debugstr_diobjectdataformat( const DIOBJECTDATAFORMAT
static inline BOOL is_exclusively_acquired( struct dinput_device *device ) { - return device->acquired && (device->dwCoopLevel & DISCL_EXCLUSIVE); + return device->status == STATUS_ACQUIRED && (device->dwCoopLevel & DISCL_EXCLUSIVE); }
/****************************************************************************** @@ -582,7 +582,7 @@ static HRESULT WINAPI dinput_device_Acquire( IDirectInputDevice8W *iface ) TRACE( "iface %p.\n", iface );
EnterCriticalSection( &impl->crit ); - if (impl->acquired) + if (impl->status == STATUS_ACQUIRED) hr = DI_NOEFFECT; else if (!impl->user_format) hr = DIERR_INVALIDPARAM; @@ -590,8 +590,9 @@ static HRESULT WINAPI dinput_device_Acquire( IDirectInputDevice8W *iface ) hr = DIERR_OTHERAPPHASPRIO; else { - impl->acquired = TRUE; - if (FAILED(hr = impl->vtbl->acquire( iface ))) impl->acquired = FALSE; + impl->status = STATUS_ACQUIRED; + if (FAILED(hr = impl->vtbl->acquire( iface ))) + impl->status = STATUS_UNACQUIRED; } LeaveCriticalSection( &impl->crit ); if (hr != DI_OK) return hr; @@ -614,9 +615,9 @@ static HRESULT WINAPI dinput_device_Unacquire( IDirectInputDevice8W *iface ) TRACE( "iface %p.\n", iface );
EnterCriticalSection( &impl->crit ); - if (!impl->acquired) hr = DI_NOEFFECT; + if (impl->status != STATUS_ACQUIRED) hr = DI_NOEFFECT; else hr = impl->vtbl->unacquire( iface ); - impl->acquired = FALSE; + impl->status = STATUS_UNACQUIRED; LeaveCriticalSection( &impl->crit ); if (hr != DI_OK) return hr;
@@ -647,7 +648,7 @@ static HRESULT WINAPI dinput_device_SetDataFormat( IDirectInputDevice8W *iface,
if (format->dwSize != sizeof(DIDATAFORMAT)) return DIERR_INVALIDPARAM; if (format->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) return DIERR_INVALIDPARAM; - if (This->acquired) return DIERR_ACQUIRED; + if (This->status == STATUS_ACQUIRED) return DIERR_ACQUIRED;
EnterCriticalSection(&This->crit);
@@ -696,7 +697,7 @@ static HRESULT WINAPI dinput_device_SetCooperativeLevel( IDirectInputDevice8W *i
/* Store the window which asks for the mouse */ EnterCriticalSection(&This->crit); - if (This->acquired) hr = DIERR_ACQUIRED; + if (This->status == STATUS_ACQUIRED) hr = DIERR_ACQUIRED; else { This->win = hwnd; @@ -1014,7 +1015,7 @@ static HRESULT check_property( struct dinput_device *impl, const GUID *guid, con case (DWORD_PTR)DIPROP_BUFFERSIZE: case (DWORD_PTR)DIPROP_PHYSICALRANGE: case (DWORD_PTR)DIPROP_LOGICALRANGE: - if (impl->acquired) return DIERR_ACQUIRED; + if (impl->status == STATUS_ACQUIRED) return DIERR_ACQUIRED; break; case (DWORD_PTR)DIPROP_FFLOAD: case (DWORD_PTR)DIPROP_GRANULARITY: @@ -1553,7 +1554,9 @@ static HRESULT WINAPI dinput_device_GetDeviceState( IDirectInputDevice8W *iface, IDirectInputDevice2_Poll( iface );
EnterCriticalSection( &impl->crit ); - if (!impl->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,7 +1608,8 @@ 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->acquired) return DIERR_NOTACQUIRED; + if (This->status == STATUS_UNPLUGGED) return DIERR_INPUTLOST; + if (This->status != STATUS_ACQUIRED) return DIERR_NOTACQUIRED; }
if (!This->queue_len) @@ -1857,7 +1861,10 @@ static HRESULT WINAPI dinput_device_Poll( IDirectInputDevice8W *iface ) HRESULT hr = DI_NOEFFECT;
EnterCriticalSection( &impl->crit ); - if (!impl->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;
@@ -2012,7 +2019,7 @@ static HRESULT WINAPI dinput_device_SetActionMap( IDirectInputDevice8W *iface, D break; }
- if (impl->acquired) return DIERR_ACQUIRED; + if (impl->status == STATUS_ACQUIRED) return DIERR_ACQUIRED;
data_format.dwSize = sizeof(data_format); data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT); diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 00a80b16590..15a8a6f83b5 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -69,6 +69,13 @@ struct object_properties DWORD calibration_mode; };
+enum device_status +{ + STATUS_UNACQUIRED, + STATUS_ACQUIRED, + STATUS_UNPLUGGED, +}; + /* Device implementation */ struct dinput_device { @@ -84,7 +91,7 @@ struct dinput_device DIDEVCAPS caps; DWORD dwCoopLevel; HWND win; - int acquired; + enum device_status status;
BOOL use_raw_input; /* use raw input instead of low-level messages */ RAWINPUTDEVICE raw_device; /* raw device to (un)register */ diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 8347e3aa586..a5bb57c64f3 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -128,12 +128,12 @@ static void dinput_device_internal_unacquire( IDirectInputDevice8W *iface ) TRACE( "iface %p.\n", iface );
EnterCriticalSection( &impl->crit ); - if (impl->acquired) + if (impl->status == STATUS_ACQUIRED) { impl->vtbl->unacquire( iface ); - impl->acquired = FALSE; list_remove( &impl->entry ); } + impl->status = STATUS_UNPLUGGED; LeaveCriticalSection( &impl->crit ); }
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 16fcc06b6e8..29cf3afcdd4 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -243,7 +243,7 @@ static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectI
static inline BOOL is_exclusively_acquired( struct hid_joystick *joystick ) { - return joystick->base.acquired && (joystick->base.dwCoopLevel & DISCL_EXCLUSIVE); + return joystick->base.status == STATUS_ACQUIRED && (joystick->base.dwCoopLevel & DISCL_EXCLUSIVE); }
static const GUID *object_usage_to_guid( USAGE usage_page, USAGE usage ) @@ -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 7590835fe55..e7ea5345118 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -2821,20 +2821,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 );