Module: wine Branch: master Commit: 33dc3db01e5a972cbc58f795869b44d9c61ed89e URL: https://source.winehq.org/git/wine.git/?a=commit;h=33dc3db01e5a972cbc58f7958...
Author: Rémi Bernon rbernon@codeweavers.com Date: Thu Oct 7 10:40:04 2021 +0200
dinput: Implement HID joystick IDirectInputEffect_(Start|Stop).
Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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 624cea4d77a..002b16fe84b 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) );