[PATCH 07/11] dinput: Implement HID joystick IDirectInputEffect_(Start|Stop).

Rémi Bernon rbernon at codeweavers.com
Thu Oct 7 03:40:04 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/joystick_hid.c | 92 ++++++++++++++++++++++++++++++++++++--
 dlls/dinput8/tests/hid.c   |  5 ---
 2 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 8cdc6696fdc..e0fd2842feb 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -145,6 +145,7 @@ struct hid_joystick_effect
     IDirectInputEffect IDirectInputEffect_iface;
     LONG ref;
     USAGE type;
+    ULONG index;
 
     struct list entry;
     struct hid_joystick *joystick;
@@ -2134,14 +2135,97 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa
 
 static HRESULT WINAPI hid_joystick_effect_Start( IDirectInputEffect *iface, DWORD iterations, DWORD flags )
 {
-    FIXME( "iface %p, iterations %u, flags %#x stub!\n", iface, iterations, flags );
-    return DIERR_UNSUPPORTED;
+    struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
+    struct pid_control_report *effect_control = &impl->joystick->pid_effect_control;
+    ULONG count, report_len = impl->joystick->caps.OutputReportByteLength;
+    PHIDP_PREPARSED_DATA preparsed = impl->joystick->preparsed;
+    HANDLE device = impl->joystick->device;
+    NTSTATUS status;
+    USAGE control;
+    HRESULT hr;
+
+    TRACE( "iface %p, iterations %u, flags %#x.\n", iface, iterations, flags );
+
+    if ((flags & ~(DIES_NODOWNLOAD|DIES_SOLO))) return DIERR_INVALIDPARAM;
+    if (flags & DIES_SOLO) control = PID_USAGE_OP_EFFECT_START_SOLO;
+    else control = PID_USAGE_OP_EFFECT_START;
+
+    EnterCriticalSection( &impl->joystick->base.crit );
+    if (!impl->joystick->base.acquired || !(impl->joystick->base.dwCoopLevel & DISCL_EXCLUSIVE))
+        hr = DIERR_NOTEXCLUSIVEACQUIRED;
+    else if ((flags & DIES_NODOWNLOAD) && !impl->index)
+        hr = DIERR_NOTDOWNLOADED;
+    else if ((flags & DIES_NODOWNLOAD) || !FAILED(hr = IDirectInputEffect_Download( iface )))
+    {
+        count = 1;
+        status = HidP_InitializeReportForID( HidP_Output, effect_control->id, preparsed,
+                                             impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX,
+                                          impl->index, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsages( HidP_Output, HID_USAGE_PAGE_PID, effect_control->control_coll,
+                                      &control, &count, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_LOOP_COUNT,
+                                          iterations, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else if (WriteFile( device, impl->effect_control_buf, report_len, NULL, NULL )) hr = DI_OK;
+        else hr = DIERR_INPUTLOST;
+    }
+    LeaveCriticalSection( &impl->joystick->base.crit );
+
+    return hr;
 }
 
 static HRESULT WINAPI hid_joystick_effect_Stop( IDirectInputEffect *iface )
 {
-    FIXME( "iface %p stub!\n", iface );
-    return DIERR_UNSUPPORTED;
+    struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
+    struct pid_control_report *effect_control = &impl->joystick->pid_effect_control;
+    ULONG count, report_len = impl->joystick->caps.OutputReportByteLength;
+    PHIDP_PREPARSED_DATA preparsed = impl->joystick->preparsed;
+    HANDLE device = impl->joystick->device;
+    NTSTATUS status;
+    USAGE control;
+    HRESULT hr;
+
+    TRACE( "iface %p.\n", iface );
+
+    EnterCriticalSection( &impl->joystick->base.crit );
+    if (!impl->joystick->base.acquired || !(impl->joystick->base.dwCoopLevel & DISCL_EXCLUSIVE))
+        hr = DIERR_NOTEXCLUSIVEACQUIRED;
+    else if (!impl->index)
+        hr = DIERR_NOTDOWNLOADED;
+    else
+    {
+        count = 1;
+        control = PID_USAGE_OP_EFFECT_STOP;
+        status = HidP_InitializeReportForID( HidP_Output, effect_control->id, preparsed,
+                                             impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX,
+                                          impl->index, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsages( HidP_Output, HID_USAGE_PAGE_PID, effect_control->control_coll,
+                                      &control, &count, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_LOOP_COUNT,
+                                          0, preparsed, impl->effect_control_buf, report_len );
+
+        if (status != HIDP_STATUS_SUCCESS) hr = status;
+        else if (WriteFile( device, impl->effect_control_buf, report_len, NULL, NULL )) hr = DI_OK;
+        else hr = DIERR_INPUTLOST;
+    }
+    LeaveCriticalSection( &impl->joystick->base.crit );
+
+    return hr;
 }
 
 static HRESULT WINAPI hid_joystick_effect_GetEffectStatus( IDirectInputEffect *iface, DWORD *status )
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index eb774dd5fe3..a53502ca8d4 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5765,10 +5765,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
     check_member( periodic, expect_periodic, "%u", dwPeriod );
 
     hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
-    todo_wine
     ok( hr == DIERR_NOTDOWNLOADED, "Start returned %#x\n", hr );
     hr = IDirectInputEffect_Stop( effect );
-    todo_wine
     ok( hr == DIERR_NOTDOWNLOADED, "Stop returned %#x\n", hr );
 
     set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) );
@@ -5782,7 +5780,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
     ok( hr == DI_NOEFFECT, "Download returned %#x\n", hr );
 
     hr = IDirectInputEffect_Start( effect, 1, 0xdeadbeef );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "Start returned %#x\n", hr );
 
     set_hid_expect( file, &expect_start_solo, sizeof(expect_start_solo) );
@@ -5845,10 +5842,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
     set_hid_expect( file, NULL, 0 );
 
     hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
-    todo_wine
     ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Start returned %#x\n", hr );
     hr = IDirectInputEffect_Stop( effect );
-    todo_wine
     ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Stop returned %#x\n", hr );
 
     set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
-- 
2.33.0




More information about the wine-devel mailing list