Rémi Bernon : dinput: Write PID device gain reports when necessary.

Alexandre Julliard julliard at winehq.org
Wed Nov 17 16:27:57 CST 2021


Module: wine
Branch: master
Commit: 45986545f82aef8ad7c56ec77a449c45fda8a4fd
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=45986545f82aef8ad7c56ec77a449c45fda8a4fd

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Wed Nov 17 11:51:53 2021 +0100

dinput: Write PID device gain reports when necessary.

Based on a patch from Ivo Ivanov <logos128 at gmail.com>.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dinput/device.c         |  4 +++-
 dlls/dinput/device_private.h |  2 +-
 dlls/dinput/joystick_hid.c   | 42 ++++++++++++++++++++++++++++++++++--------
 dlls/dinput8/tests/hid.c     | 13 -------------
 4 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 449adaffde2..f21d951d268 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1103,6 +1103,8 @@ static HRESULT WINAPI dinput_device_SetProperty( IDirectInputDevice8W *iface, co
         if (value->dwData > 10000) return DIERR_INVALIDPARAM;
         EnterCriticalSection( &impl->crit );
         impl->device_gain = value->dwData;
+        if (!impl->acquired || !(impl->dwCoopLevel & DISCL_EXCLUSIVE)) hr = DI_OK;
+        else hr = impl->vtbl->send_device_gain( iface, impl->device_gain );
         LeaveCriticalSection( &impl->crit );
         return hr;
     }
@@ -1520,7 +1522,7 @@ static HRESULT WINAPI dinput_device_SendForceFeedbackCommand( IDirectInputDevice
 
     EnterCriticalSection( &impl->crit );
     if (!impl->acquired || !(impl->dwCoopLevel & DISCL_EXCLUSIVE)) hr = DIERR_NOTEXCLUSIVEACQUIRED;
-    else hr = impl->vtbl->send_force_feedback_command( iface, command );
+    else hr = impl->vtbl->send_force_feedback_command( iface, command, FALSE );
     LeaveCriticalSection( &impl->crit );
 
     return hr;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index a2110942583..aeab89c840a 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -49,7 +49,7 @@ struct dinput_device_vtbl
                              const DIDEVICEOBJECTINSTANCEW *instance );
     HRESULT (*get_effect_info)( IDirectInputDevice8W *iface, DIEFFECTINFOW *info, const GUID *guid );
     HRESULT (*create_effect)( IDirectInputDevice8W *iface, IDirectInputEffect **out );
-    HRESULT (*send_force_feedback_command)( IDirectInputDevice8W *iface, DWORD command );
+    HRESULT (*send_force_feedback_command)( IDirectInputDevice8W *iface, DWORD command, BOOL unacquire );
     HRESULT (*send_device_gain)( IDirectInputDevice8W *iface, LONG device_gain );
     HRESULT (*enum_created_effect_objects)( IDirectInputDevice8W *iface, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK callback,
                                             void *context, DWORD flags );
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 0502362de2f..6cd537c5776 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -674,11 +674,11 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter,
     return DIENUM_CONTINUE;
 }
 
-static void set_parameter_value( struct hid_joystick_effect *impl, char *report_buf,
-                                 struct hid_value_caps *caps, LONG value )
+static void set_report_value( struct hid_joystick *impl, char *report_buf,
+                              struct hid_value_caps *caps, LONG value )
 {
-    ULONG report_len = impl->joystick->caps.OutputReportByteLength;
-    PHIDP_PREPARSED_DATA preparsed = impl->joystick->preparsed;
+    ULONG report_len = impl->caps.OutputReportByteLength;
+    PHIDP_PREPARSED_DATA preparsed = impl->preparsed;
     LONG log_min, log_max, phy_min, phy_max;
     NTSTATUS status;
 
@@ -819,9 +819,23 @@ static void set_extra_caps_range( struct hid_joystick *impl, const DIDEVICEOBJEC
 
 static HRESULT hid_joystick_send_device_gain( IDirectInputDevice8W *iface, LONG device_gain )
 {
-    FIXME( "iface %p stub!\n", iface );
+    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
+    struct pid_device_gain *report = &impl->pid_device_gain;
+    ULONG report_len = impl->caps.OutputReportByteLength;
+    char *report_buf = impl->output_report_buf;
+    NTSTATUS status;
 
-    return DIERR_UNSUPPORTED;
+    TRACE( "iface %p.\n", iface );
+
+    if (!report->id || !report->device_gain_caps) return DI_OK;
+
+    status = HidP_InitializeReportForID( HidP_Output, report->id, impl->preparsed, report_buf, report_len );
+    if (status != HIDP_STATUS_SUCCESS) return status;
+
+    set_report_value( impl, report_buf, report->device_gain_caps, device_gain );
+
+    if (!WriteFile( impl->device, report_buf, report_len, NULL, NULL )) return DIERR_INPUTLOST;
+    return DI_OK;
 }
 
 static HRESULT hid_joystick_set_property( IDirectInputDevice8W *iface, DWORD property,
@@ -884,6 +898,8 @@ static HRESULT hid_joystick_acquire( IDirectInputDevice8W *iface )
     return DI_OK;
 }
 
+static HRESULT hid_joystick_send_force_feedback_command( IDirectInputDevice8W *iface, DWORD command, BOOL unacquire );
+
 static HRESULT hid_joystick_unacquire( IDirectInputDevice8W *iface )
 {
     struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
@@ -895,7 +911,9 @@ static HRESULT hid_joystick_unacquire( IDirectInputDevice8W *iface )
     if (!ret) WARN( "CancelIoEx failed, last error %u\n", GetLastError() );
     else WaitForSingleObject( impl->base.read_event, INFINITE );
 
-    IDirectInputDevice8_SendForceFeedbackCommand( iface, DISFFC_RESET );
+    if (!(impl->base.caps.dwFlags & DIDC_FORCEFEEDBACK)) return DI_OK;
+    if (!impl->base.acquired || !(impl->base.dwCoopLevel & DISCL_EXCLUSIVE)) return DI_OK;
+    hid_joystick_send_force_feedback_command( iface, DISFFC_RESET, TRUE );
     return DI_OK;
 }
 
@@ -1027,7 +1045,7 @@ static BOOL CALLBACK unload_effect_object( IDirectInputEffect *effect, void *con
     return DIENUM_CONTINUE;
 }
 
-static HRESULT hid_joystick_send_force_feedback_command( IDirectInputDevice8W *iface, DWORD command )
+static HRESULT hid_joystick_send_force_feedback_command( IDirectInputDevice8W *iface, DWORD command, BOOL unacquire )
 {
     struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
     struct pid_control_report *report = &impl->pid_device_control;
@@ -1060,6 +1078,8 @@ static HRESULT hid_joystick_send_force_feedback_command( IDirectInputDevice8W *i
     if (status != HIDP_STATUS_SUCCESS) return status;
 
     if (!WriteFile( impl->device, report_buf, report_len, NULL, NULL )) return DIERR_INPUTLOST;
+    if (!unacquire) hid_joystick_send_device_gain( iface, impl->base.device_gain );
+
     return DI_OK;
 }
 
@@ -2655,6 +2675,12 @@ static HRESULT WINAPI hid_joystick_effect_GetEffectStatus( IDirectInputEffect *i
     return DIERR_UNSUPPORTED;
 }
 
+static void set_parameter_value( struct hid_joystick_effect *impl, char *report_buf,
+                                 struct hid_value_caps *caps, LONG value )
+{
+    return set_report_value( impl->joystick, report_buf, caps, value );
+}
+
 static void set_parameter_value_us( struct hid_joystick_effect *impl, char *report_buf,
                                     struct hid_value_caps *caps, LONG value )
 {
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index ba5a26b3945..ac4b8023611 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -754,15 +754,7 @@ static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, voi
     if (!ret && GetLastError() == ERROR_IO_PENDING)
     {
         ret = GetOverlappedResultEx( file, &ovl, &out_len, timeout, TRUE );
-        todo_wine_if( timeout != INFINITE )
         ok( ret, "GetOverlappedResultEx returned %u\n", GetLastError() );
-        if (!ret)
-        {
-            ret = CancelIoEx( file, &ovl );
-            ok( ret, "CancelIoEx returned %u\n", GetLastError() );
-            ret = WaitForSingleObject( ovl.hEvent, INFINITE );
-            ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
-        }
     }
     CloseHandle( ovl.hEvent );
 
@@ -793,7 +785,6 @@ static void set_hid_expect_( int line, HANDLE file, struct hid_expect *expect, D
 static void wait_hid_expect_( int line, HANDLE file, DWORD timeout )
 {
     BOOL ret = sync_ioctl( file, IOCTL_WINETEST_HID_WAIT_EXPECT, NULL, 0, NULL, 0, timeout );
-    todo_wine
     ok( ret, "IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error %u\n", GetLastError() );
 
     set_hid_expect( file, NULL, 0 );
@@ -5584,7 +5575,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
             .report_id = 8,
             .report_len = 2,
             .report_buf = {8, 0x19},
-            .todo = TRUE,
         },
     };
     struct hid_expect expect_reset[] =
@@ -6947,7 +6937,6 @@ static void test_force_feedback_joystick( DWORD version )
             .report_id = 8,
             .report_len = 2,
             .report_buf = {8, 0x19},
-            .todo = TRUE,
         },
     };
     struct hid_expect expect_reset[] =
@@ -6965,7 +6954,6 @@ static void test_force_feedback_joystick( DWORD version )
         .report_id = 8,
         .report_len = 2,
         .report_buf = {8, 0x19},
-        .todo = TRUE,
     };
     struct hid_expect expect_set_device_gain_2 =
     {
@@ -6973,7 +6961,6 @@ static void test_force_feedback_joystick( DWORD version )
         .report_id = 8,
         .report_len = 2,
         .report_buf = {8, 0x33},
-        .todo = TRUE,
     };
 
     const DIDEVICEINSTANCEW expect_devinst =




More information about the wine-cvs mailing list