Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 2ef01ac6ace..d2aa352b6e2 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -1195,7 +1195,7 @@ static HRESULT WINAPI hid_joystick_EnumCreatedEffectObjects( IDirectInputDevice8 struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); struct hid_joystick_effect *effect, *next;
- FIXME( "iface %p, callback %p, context %p, flags %#x stub!\n", iface, callback, context, flags ); + TRACE( "iface %p, callback %p, context %p, flags %#x.\n", iface, callback, context, flags );
if (!callback) return DIERR_INVALIDPARAM; if (flags) return DIERR_INVALIDPARAM;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index d2aa352b6e2..bcc13c21ff2 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -147,6 +147,9 @@ struct hid_joystick_effect
struct list entry; struct hid_joystick *joystick; + + char *effect_control_buf; + char *effect_update_buf; };
static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface ) @@ -2048,6 +2051,8 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) list_remove( &impl->entry ); LeaveCriticalSection( &impl->joystick->base.crit ); hid_joystick_private_decref( impl->joystick ); + HeapFree( GetProcessHeap(), 0, impl->effect_update_buf ); + HeapFree( GetProcessHeap(), 0, impl->effect_control_buf ); HeapFree( GetProcessHeap(), 0, impl ); } return ref; @@ -2140,6 +2145,8 @@ static IDirectInputEffectVtbl hid_joystick_effect_vtbl = static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirectInputEffect **out ) { struct hid_joystick_effect *impl; + ULONG report_len; + NTSTATUS status;
if (!(impl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*impl) ))) return DIERR_OUTOFMEMORY; @@ -2152,6 +2159,16 @@ static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirec list_add_tail( &joystick->effect_list, &impl->entry ); LeaveCriticalSection( &joystick->base.crit );
+ status = HIDP_STATUS_SUCCESS; + report_len = joystick->caps.OutputReportByteLength; + if (!(impl->effect_control_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed; + if (!(impl->effect_update_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed; + *out = &impl->IDirectInputEffect_iface; return DI_OK; + +failed: + IDirectInputEffect_Release( &impl->IDirectInputEffect_iface ); + if (status != HIDP_STATUS_SUCCESS) return DIERR_GENERIC; + return DIERR_OUTOFMEMORY; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 25 ++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 7 ------- 2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index bcc13c21ff2..924438daf7c 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -144,6 +144,7 @@ struct hid_joystick_effect { IDirectInputEffect IDirectInputEffect_iface; LONG ref; + USAGE type;
struct list entry; struct hid_joystick *joystick; @@ -2061,7 +2062,29 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface, HINSTANCE inst, DWORD version, REFGUID guid ) { - FIXME( "iface %p, inst %p, version %u, guid %s stub!\n", iface, inst, version, debugstr_guid( guid ) ); + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + struct hid_joystick *joystick = impl->joystick; + ULONG report_len = joystick->caps.OutputReportByteLength; + NTSTATUS status; + ULONG count; + USAGE type; + + TRACE( "iface %p, inst %p, version %u, guid %s\n", iface, inst, version, debugstr_guid( guid ) ); + + if (!inst) return DIERR_INVALIDPARAM; + if (!guid) return E_POINTER; + if (!(type = effect_guid_to_usage( guid ))) return DIERR_DEVICENOTREG; + + status = HidP_InitializeReportForID( HidP_Output, joystick->pid_effect_update.id, + joystick->preparsed, impl->effect_update_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return DIERR_DEVICENOTREG; + + count = 1; + status = HidP_SetUsages( HidP_Output, HID_USAGE_PAGE_PID, joystick->pid_effect_update.type_coll, + &type, &count, joystick->preparsed, impl->effect_update_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return DIERR_DEVICENOTREG; + + impl->type = type; return DI_OK; }
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index e55adb0aa56..35a7d4b3bb7 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5159,13 +5159,9 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, NULL, NULL ); ok( hr == E_POINTER, "CreateEffect returned %#x\n", hr ); hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL ); - todo_wine ok( hr == E_POINTER, "CreateEffect returned %#x\n", hr ); - if (hr == DI_OK) IDirectInputEffect_Release( effect ); hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL ); - todo_wine ok( hr == DIERR_DEVICENOTREG, "CreateEffect returned %#x\n", hr ); - if (hr == DI_OK) IDirectInputEffect_Release( effect );
hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL ); ok( hr == DI_OK, "CreateEffect returned %#x\n", hr ); @@ -5179,17 +5175,14 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count );
hr = IDirectInputEffect_Initialize( effect, NULL, DIRECTINPUT_VERSION, &GUID_Sine ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#x\n", hr ); hr = IDirectInputEffect_Initialize( effect, instance, 0, &GUID_Sine ); todo_wine ok( hr == DIERR_NOTINITIALIZED, "Initialize returned %#x\n", hr ); hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, NULL ); - todo_wine ok( hr == E_POINTER, "Initialize returned %#x\n", hr );
hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, &GUID_NULL ); - todo_wine ok( hr == DIERR_DEVICENOTREG, "Initialize returned %#x\n", hr ); hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, &GUID_Sine ); ok( hr == DI_OK, "Initialize returned %#x\n", hr );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 33 +++++++++++++++++++++++++++++---- dlls/dinput8/tests/hid.c | 3 --- 2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 924438daf7c..8cdc6696fdc 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -199,6 +199,26 @@ static inline USAGE effect_guid_to_usage( const GUID *guid ) return 0; }
+static inline const GUID *effect_usage_to_guid( USAGE usage ) +{ + switch (usage) + { + case PID_USAGE_ET_CUSTOM_FORCE_DATA: return &GUID_CustomForce; + case PID_USAGE_ET_CONSTANT_FORCE: return &GUID_ConstantForce; + case PID_USAGE_ET_RAMP: return &GUID_RampForce; + case PID_USAGE_ET_SQUARE: return &GUID_Square; + case PID_USAGE_ET_SINE: return &GUID_Sine; + case PID_USAGE_ET_TRIANGLE: return &GUID_Triangle; + case PID_USAGE_ET_SAWTOOTH_UP: return &GUID_SawtoothUp; + case PID_USAGE_ET_SAWTOOTH_DOWN: return &GUID_SawtoothDown; + case PID_USAGE_ET_SPRING: return &GUID_Spring; + case PID_USAGE_ET_DAMPER: return &GUID_Damper; + case PID_USAGE_ET_INERTIA: return &GUID_Inertia; + case PID_USAGE_ET_FRICTION: return &GUID_Friction; + } + return &GUID_Unknown; +} + static const WCHAR *effect_guid_to_string( const GUID *guid ) { static const WCHAR guid_customforce_w[] = {'G','U','I','D','_','C','u','s','t','o','m','F','o','r','c','e',0}; @@ -2064,9 +2084,8 @@ static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface, { struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); struct hid_joystick *joystick = impl->joystick; - ULONG report_len = joystick->caps.OutputReportByteLength; + ULONG count, report_len = joystick->caps.OutputReportByteLength; NTSTATUS status; - ULONG count; USAGE type;
TRACE( "iface %p, inst %p, version %u, guid %s\n", iface, inst, version, debugstr_guid( guid ) ); @@ -2090,8 +2109,14 @@ static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface,
static HRESULT WINAPI hid_joystick_effect_GetEffectGuid( IDirectInputEffect *iface, GUID *guid ) { - FIXME( "iface %p, guid %p stub!\n", iface, guid ); - return DIERR_UNSUPPORTED; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + + TRACE( "iface %p, guid %p.\n", iface, guid ); + + if (!guid) return E_POINTER; + *guid = *effect_usage_to_guid( impl->type ); + + return DI_OK; }
static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags ) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 35a7d4b3bb7..3ec837abee4 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5190,12 +5190,9 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Initialize returned %#x\n", hr );
hr = IDirectInputEffect_GetEffectGuid( effect, NULL ); - todo_wine ok( hr == E_POINTER, "GetEffectGuid returned %#x\n", hr ); hr = IDirectInputEffect_GetEffectGuid( effect, &guid ); - todo_wine ok( hr == DI_OK, "GetEffectGuid returned %#x\n", hr ); - todo_wine ok( IsEqualGUID( &guid, &GUID_Square ), "got guid %s, expected %s\n", debugstr_guid( &guid ), debugstr_guid( &GUID_Square ) );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 153 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 3ec837abee4..7388a7499c4 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5087,6 +5087,57 @@ static BOOL test_device_types(void)
static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) { + struct hid_expect expect_download[] = + { + /* set periodic */ + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 5, + .report_len = 2, + .report_buf = {0x05,0x19}, + }, + /* set envelope */ + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 6, + .report_len = 7, + .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00}, + }, + /* update effect */ + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 3, + .report_len = 9, + .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,0x06,0x00,0x01}, + }, + /* start command when DIEP_START is set */ + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02,0x01,0x01,0x01}, + }, + }; + struct hid_expect expect_unload[] = + { + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02,0x01,0x03,0x00}, + }, + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 1, + .report_len = 2, + .report_buf = {1,0x01}, + }, + }; struct hid_expect expect_dc_reset = { .code = IOCTL_HID_WRITE_REPORT, @@ -5368,6 +5419,25 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( desc, expect_desc_init, "%u", dwStartDelay );
+ set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); + hr = IDirectInputDevice8_Unacquire( device ); + ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Download returned %#x\n", hr ); + set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); + hr = IDirectInputDevice8_Acquire( device ); + ok( hr == DI_OK, "Acquire returned: %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + hr = IDirectInputEffect_SetParameters( effect, NULL, DIEP_NODOWNLOAD ); todo_wine ok( hr == E_POINTER, "SetParameters returned %#x\n", hr ); @@ -5412,6 +5482,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams ); check_member( desc, expect_desc_init, "%u", dwStartDelay );
+ hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL | DIEP_NODOWNLOAD ); @@ -5438,6 +5515,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( desc, expect_desc, "%u", dwStartDelay );
+ hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + desc.lpEnvelope = NULL; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD ); todo_wine @@ -5466,6 +5550,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( envelope, expect_envelope, "%u", dwFadeTime );
+ hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + desc.dwFlags = 0; desc.cAxes = 0; desc.rgdwAxes = NULL; @@ -5532,6 +5623,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine ok( desc.rgdwAxes[2] == 4, "got %#x expected %#x\n", desc.rgdwAxes[2], 4 );
+ hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + desc.dwFlags = DIEFF_CARTESIAN; desc.cAxes = 0; desc.rglDirection = directions; @@ -5593,6 +5691,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
+ hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = &periodic; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD ); @@ -5618,6 +5723,54 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( periodic, expect_periodic, "%u", dwPeriod );
+ set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) ); + hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DI_OK, "Download returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Download returned %#x\n", hr ); + + set_hid_expect( file, expect_unload, sizeof(struct hid_expect) ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_OK, "Unload returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, expect_download, 4 * sizeof(struct hid_expect) ); + hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_START ); + todo_wine + ok( hr == DI_OK, "SetParameters returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, expect_unload, sizeof(struct hid_expect) ); + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_OK, "Unload returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) ); + hr = IDirectInputEffect_Download( effect ); + todo_wine + ok( hr == DI_OK, "Download returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, expect_unload, 2 * sizeof(struct hid_expect) ); + hr = IDirectInputDevice8_Unacquire( device ); + ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); + hr = IDirectInputDevice8_Acquire( device ); + ok( hr == DI_OK, "Acquire returned: %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + hr = IDirectInputEffect_Unload( effect ); + todo_wine + ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr ); + ref = IDirectInputEffect_Release( effect ); ok( ref == 0, "Release returned %d\n", ref );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 89 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 7388a7499c4..eb774dd5fe3 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5122,6 +5122,46 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) .report_buf = {0x02,0x01,0x01,0x01}, }, }; + struct hid_expect expect_start = + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02, 0x01, 0x01, 0x01}, + }; + struct hid_expect expect_start_solo = + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02, 0x01, 0x02, 0x01}, + }; + struct hid_expect expect_start_0 = + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02, 0x01, 0x01, 0x00}, + }; + struct hid_expect expect_start_4 = + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02, 0x01, 0x01, 0x04}, + }; + struct hid_expect expect_stop = + { + .code = IOCTL_HID_WRITE_REPORT, + .todo = TRUE, + .report_id = 2, + .report_len = 4, + .report_buf = {0x02, 0x01, 0x03, 0x00}, + }; struct hid_expect expect_unload[] = { { @@ -5131,6 +5171,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) .report_len = 4, .report_buf = {0x02,0x01,0x03,0x00}, }, + /* device reset, when unloaded from Unacquire */ { .code = IOCTL_HID_WRITE_REPORT, .report_id = 1, @@ -5723,6 +5764,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine 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) ); hr = IDirectInputEffect_Download( effect ); todo_wine @@ -5733,6 +5781,40 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine 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) ); + hr = IDirectInputEffect_Start( effect, 1, DIES_SOLO ); + todo_wine + ok( hr == DI_OK, "Start returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_stop, sizeof(expect_stop) ); + hr = IDirectInputEffect_Stop( effect ); + todo_wine + ok( hr == DI_OK, "Stop returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_start, sizeof(expect_start) ); + hr = IDirectInputEffect_Start( effect, 1, 0 ); + todo_wine + ok( hr == DI_OK, "Start returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_start_4, sizeof(expect_start_4) ); + hr = IDirectInputEffect_Start( effect, 4, 0 ); + todo_wine + ok( hr == DI_OK, "Start returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_start_0, sizeof(expect_start_4) ); + hr = IDirectInputEffect_Start( effect, 0, 0 ); + todo_wine + ok( hr == DI_OK, "Start returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + set_hid_expect( file, expect_unload, sizeof(struct hid_expect) ); hr = IDirectInputEffect_Unload( effect ); todo_wine @@ -5762,6 +5844,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); 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) ); hr = IDirectInputDevice8_Acquire( device ); ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
Signed-off-by: Rémi Bernon rbernon@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) );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 162 ++++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 48 ----------- 2 files changed, 160 insertions(+), 50 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index e0fd2842feb..3014e76603b 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -150,6 +150,12 @@ struct hid_joystick_effect struct list entry; struct hid_joystick *joystick;
+ DWORD axes[6]; + LONG directions[6]; + DIENVELOPE envelope; + DIPERIODIC periodic; + DIEFFECT params; + char *effect_control_buf; char *effect_update_buf; }; @@ -2120,10 +2126,155 @@ static HRESULT WINAPI hid_joystick_effect_GetEffectGuid( IDirectInputEffect *ifa return DI_OK; }
+static BOOL get_parameters_object_id( struct hid_joystick *impl, struct hid_value_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + *(DWORD *)data = instance->dwType; + return DIENUM_STOP; +} + +static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_value_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + DIDATAFORMAT *format = impl->base.data_format.wine_df; + int *offsets = impl->base.data_format.offsets; + ULONG i; + + if (!offsets) return DIENUM_CONTINUE; + for (i = 0; i < format->dwNumObjs; ++i) + if (format->rgodf[i].dwOfs == instance->dwOfs) break; + if (i == format->dwNumObjs) return DIENUM_CONTINUE; + *(DWORD *)data = offsets[i]; + + return DIENUM_STOP; +} + static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags ) { - FIXME( "iface %p, params %p, flags %#x stub!\n", iface, params, flags ); - return DIERR_UNSUPPORTED; + DIPROPHEADER filter = + { + .dwSize = sizeof(DIPROPHEADER), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_BYUSAGE, + }; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + ULONG i, j, count, capacity, object_flags, direction_flags; + LONG tmp, directions[6] = {0}; + BOOL ret; + + TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags ); + + if (!params) return DI_OK; + if (params->dwSize != sizeof(DIEFFECT)) return DIERR_INVALIDPARAM; + capacity = params->cAxes; + object_flags = params->dwFlags & (DIEFF_OBJECTIDS | DIEFF_OBJECTOFFSETS); + direction_flags = params->dwFlags & (DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + if (flags & DIEP_AXES) + { + if (!object_flags) return DIERR_INVALIDPARAM; + params->cAxes = impl->params.cAxes; + if (capacity < impl->params.cAxes) return DIERR_MOREDATA; + + for (i = 0; i < impl->params.cAxes; ++i) + { + if (!params->rgdwAxes) return DIERR_INVALIDPARAM; + filter.dwObj = impl->params.rgdwAxes[i]; + if (object_flags & DIEFF_OBJECTIDS) + ret = enum_objects( impl->joystick, &filter, DIDFT_AXIS, get_parameters_object_id, + ¶ms->rgdwAxes[i] ); + else + ret = enum_objects( impl->joystick, &filter, DIDFT_AXIS, get_parameters_object_ofs, + ¶ms->rgdwAxes[i] ); + if (ret != DIENUM_STOP) params->rgdwAxes[i] = 0; + } + } + + if (flags & DIEP_DIRECTION) + { + if (!direction_flags) return DIERR_INVALIDPARAM; + params->dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + count = params->cAxes = impl->params.cAxes; + if (capacity < params->cAxes) return DIERR_MOREDATA; + if (!count) params->dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + if (direction_flags & DIEFF_SPHERICAL) + memcpy( directions, impl->params.rglDirection, count * sizeof(LONG) ); + else if (direction_flags & DIEFF_POLAR) + { + if (count != 2) return DIERR_INVALIDPARAM; + directions[0] = (impl->params.rglDirection[0] + 9000) % 36000; + if (directions[0] < 0) directions[0] += 36000; + } + else if (direction_flags & DIEFF_CARTESIAN) + { + directions[0] = 10000; + for (i = 1; i <= count; ++i) + { + tmp = cos( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000; + for (j = 0; j < i; ++j) directions[j] = round( directions[j] * tmp / 10000.0 ); + directions[i] = sin( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000; + } + } + + if (!params->rglDirection) return DIERR_INVALIDPARAM; + else memcpy( params->rglDirection, directions, count * sizeof(LONG) ); + } + + if (flags & DIEP_TYPESPECIFICPARAMS) + { + switch (impl->type) + { + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + if (!params->lpvTypeSpecificParams) return E_POINTER; + if (params->cbTypeSpecificParams != sizeof(DIPERIODIC)) return DIERR_INVALIDPARAM; + memcpy( params->lpvTypeSpecificParams, &impl->periodic, sizeof(DIPERIODIC) ); + break; + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + case PID_USAGE_ET_CONSTANT_FORCE: + case PID_USAGE_ET_RAMP: + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + FIXME( "DIEP_TYPESPECIFICPARAMS not implemented!\n" ); + return DIERR_UNSUPPORTED; + } + } + + if (flags & DIEP_ENVELOPE) + { + if (!params->lpEnvelope) return E_POINTER; + if (params->lpEnvelope->dwSize != sizeof(DIENVELOPE)) return DIERR_INVALIDPARAM; + memcpy( params->lpEnvelope, &impl->envelope, sizeof(DIENVELOPE) ); + } + + if (flags & DIEP_DURATION) params->dwDuration = impl->params.dwDuration; + if (flags & DIEP_GAIN) params->dwGain = impl->params.dwGain; + if (flags & DIEP_SAMPLEPERIOD) params->dwSamplePeriod = impl->params.dwSamplePeriod; + if (flags & DIEP_STARTDELAY) params->dwStartDelay = impl->params.dwStartDelay; + if (flags & DIEP_TRIGGERREPEATINTERVAL) params->dwTriggerRepeatInterval = impl->params.dwTriggerRepeatInterval; + + if (flags & DIEP_TRIGGERBUTTON) + { + if (!object_flags) return DIERR_INVALIDPARAM; + + filter.dwObj = impl->params.dwTriggerButton; + if (object_flags & DIEFF_OBJECTIDS) + ret = enum_objects( impl->joystick, &filter, DIDFT_BUTTON, get_parameters_object_id, + ¶ms->dwTriggerButton ); + else + ret = enum_objects( impl->joystick, &filter, DIDFT_BUTTON, get_parameters_object_ofs, + ¶ms->dwTriggerButton ); + if (ret != DIENUM_STOP) params->dwTriggerButton = -1; + } + + return DI_OK; }
static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *iface, @@ -2296,6 +2447,13 @@ static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirec if (!(impl->effect_control_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed; if (!(impl->effect_update_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
+ impl->envelope.dwSize = sizeof(DIENVELOPE); + impl->params.dwSize = sizeof(DIEFFECT); + impl->params.lpEnvelope = &impl->envelope; + impl->params.rgdwAxes = impl->axes; + impl->params.rglDirection = impl->directions; + impl->params.dwTriggerButton = -1; + *out = &impl->IDirectInputEffect_iface; return DI_OK;
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index a53502ca8d4..fc6a235617c 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5289,17 +5289,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) debugstr_guid( &GUID_Square ) );
hr = IDirectInputEffect_GetParameters( effect, NULL, 0 ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, NULL, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); desc.dwSize = sizeof(DIEFFECT); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); @@ -5307,7 +5303,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); set_hid_expect( file, NULL, 0 ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Acquire( device ); @@ -5316,24 +5311,17 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwDuration = 0xdeadbeef; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwDuration ); memset( &desc, 0xcd, sizeof(desc) ); desc.dwSize = sizeof(DIEFFECT); desc.dwFlags = 0; flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); - todo_wine check_member( desc, expect_desc_init, "%u", dwGain ); - todo_wine check_member( desc, expect_desc_init, "%u", dwStartDelay ); - todo_wine check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
memset( &desc, 0xcd, sizeof(desc) ); @@ -5341,15 +5329,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwFlags = 0; desc.lpEnvelope = NULL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == E_POINTER, "GetParameters returned %#x\n", hr ); desc.lpEnvelope = &envelope; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); envelope.dwSize = sizeof(DIENVELOPE); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
desc.dwFlags = 0; @@ -5360,58 +5345,43 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = NULL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); desc.dwFlags = DIEFF_OBJECTOFFSETS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); desc.dwFlags = DIEFF_OBJECTIDS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); desc.dwFlags |= DIEFF_CARTESIAN; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_POLAR; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_SPHERICAL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
desc.dwFlags |= DIEFF_SPHERICAL; @@ -5419,15 +5389,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.rgdwAxes = axes; desc.rglDirection = directions; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); todo_wine check_member( desc, expect_desc_init, "%p", rglDirection ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
desc.dwFlags |= DIEFF_SPHERICAL; @@ -5435,19 +5402,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = sizeof(periodic); desc.lpvTypeSpecificParams = &periodic; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwDuration ); - todo_wine check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); - todo_wine check_member( desc, expect_desc_init, "%u", dwGain ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); - todo_wine check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval ); - todo_wine check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); @@ -5457,7 +5417,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%p", lpEnvelope ); todo_wine check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams ); - todo_wine check_member( desc, expect_desc_init, "%u", dwStartDelay );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); @@ -5509,7 +5468,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwTriggerButton = -1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%u", dwDuration ); @@ -5538,7 +5496,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwDuration = 0; flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%u", dwDuration ); @@ -5580,7 +5537,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.lpEnvelope = &envelope; envelope.dwSize = sizeof(DIENVELOPE); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( envelope, expect_envelope, "%u", dwAttackLevel ); @@ -5639,7 +5595,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( desc, expect_desc, "%u", cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%#x", dwTriggerButton ); @@ -5654,7 +5609,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwFlags = DIEFF_OBJECTOFFSETS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine ok( desc.dwTriggerButton == 0x30, "got %#x expected %#x\n", desc.dwTriggerButton, 0x30 ); @@ -5729,7 +5683,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwFlags = DIEFF_POLAR; desc.cAxes = 3; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
hr = IDirectInputEffect_Download( effect ); @@ -5753,7 +5706,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( periodic, expect_periodic, "%u", dwMagnitude );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 176 ++++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 85 ++---------------- 2 files changed, 177 insertions(+), 84 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 3014e76603b..87fe27afadd 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -155,6 +155,8 @@ struct hid_joystick_effect DIENVELOPE envelope; DIPERIODIC periodic; DIEFFECT params; + BOOL modified; + DWORD flags;
char *effect_control_buf; char *effect_update_buf; @@ -2193,7 +2195,6 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa if (flags & DIEP_DIRECTION) { if (!direction_flags) return DIERR_INVALIDPARAM; - params->dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL);
count = params->cAxes = impl->params.cAxes; if (capacity < params->cAxes) return DIERR_MOREDATA; @@ -2218,7 +2219,8 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa } }
- if (!params->rglDirection) return DIERR_INVALIDPARAM; + if (!count) params->rglDirection = NULL; + else if (!params->rglDirection) return DIERR_INVALIDPARAM; else memcpy( params->rglDirection, directions, count * sizeof(LONG) ); }
@@ -2277,11 +2279,177 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa return DI_OK; }
+static BOOL set_parameters_object( struct hid_joystick *impl, struct hid_value_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + DWORD usages = MAKELONG( instance->wUsage, instance->wUsagePage ); + *(DWORD *)data = usages; + return DIENUM_STOP; +} + static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *iface, const DIEFFECT *params, DWORD flags ) { - FIXME( "iface %p, params %p, flags %#x stub!\n", iface, params, flags ); - return DIERR_UNSUPPORTED; + DIPROPHEADER filter = + { + .dwSize = sizeof(DIPROPHEADER), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_BYUSAGE, + }; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + ULONG i, count, old_value, object_flags, direction_flags; + LONG directions[6] = {0}; + HRESULT hr; + BOOL ret; + + TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags ); + + if (!params) return E_POINTER; + if (params->dwSize != sizeof(DIEFFECT)) return DIERR_INVALIDPARAM; + object_flags = params->dwFlags & (DIEFF_OBJECTIDS | DIEFF_OBJECTOFFSETS); + direction_flags = params->dwFlags & (DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + if (object_flags & DIEFF_OBJECTIDS) filter.dwHow = DIPH_BYID; + else filter.dwHow = DIPH_BYOFFSET; + + if (flags & DIEP_AXES) + { + if (!object_flags) return DIERR_INVALIDPARAM; + if (!params->rgdwAxes) return DIERR_INVALIDPARAM; + if (impl->params.cAxes) return DIERR_ALREADYINITIALIZED; + count = impl->joystick->pid_effect_update.axis_count; + if (params->cAxes > count) return DIERR_INVALIDPARAM; + + impl->params.cAxes = params->cAxes; + for (i = 0; i < params->cAxes; ++i) + { + filter.dwObj = params->rgdwAxes[i]; + ret = enum_objects( impl->joystick, &filter, DIDFT_AXIS, set_parameters_object, + &impl->params.rgdwAxes[i] ); + if (ret != DIENUM_STOP) impl->params.rgdwAxes[i] = 0; + } + + impl->modified = TRUE; + } + + if (flags & DIEP_DIRECTION) + { + if (!direction_flags) return DIERR_INVALIDPARAM; + if (!params->rglDirection) return DIERR_INVALIDPARAM; + + count = impl->params.cAxes; + if (params->cAxes < count) return DIERR_INVALIDPARAM; + if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM; + if ((direction_flags & DIEFF_CARTESIAN) && count < 2) return DIERR_INVALIDPARAM; + + if (!count) memset( directions, 0, sizeof(directions) ); + else if (direction_flags & DIEFF_POLAR) + { + directions[0] = (params->rglDirection[0] % 36000) - 9000; + if (directions[0] < 0) directions[0] += 36000; + for (i = 1; i < count; ++i) directions[i] = 0; + } + else if (direction_flags & DIEFF_CARTESIAN) + { + for (i = 1; i < count; ++i) + directions[i - 1] = atan2( params->rglDirection[i], params->rglDirection[0] ); + directions[count - 1] = 0; + } + else + { + for (i = 0; i < count; ++i) + { + directions[i] = params->rglDirection[i] % 36000; + if (directions[i] < 0) directions[i] += 36000; + } + } + + if (memcmp( impl->params.rglDirection, directions, count * sizeof(LONG) )) + impl->modified = TRUE; + memcpy( impl->params.rglDirection, directions, count * sizeof(LONG) ); + } + + if (flags & DIEP_TYPESPECIFICPARAMS) + { + switch (impl->type) + { + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + if (!params->lpvTypeSpecificParams) return E_POINTER; + if (params->cbTypeSpecificParams != sizeof(DIPERIODIC)) return DIERR_INVALIDPARAM; + if (memcmp( &impl->periodic, params->lpvTypeSpecificParams, sizeof(DIPERIODIC) )) + impl->modified = TRUE; + memcpy( &impl->periodic, params->lpvTypeSpecificParams, sizeof(DIPERIODIC) ); + break; + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + case PID_USAGE_ET_CONSTANT_FORCE: + case PID_USAGE_ET_RAMP: + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + FIXME( "DIEP_TYPESPECIFICPARAMS not implemented!\n" ); + return DIERR_UNSUPPORTED; + } + } + + if ((flags & DIEP_ENVELOPE) && params->lpEnvelope) + { + if (params->lpEnvelope->dwSize != sizeof(DIENVELOPE)) return DIERR_INVALIDPARAM; + if (memcmp( &impl->envelope, params->lpEnvelope, sizeof(DIENVELOPE) )) + impl->modified = TRUE; + memcpy( &impl->envelope, params->lpEnvelope, sizeof(DIENVELOPE) ); + } + + if (flags & DIEP_DURATION) + { + if (impl->params.dwDuration != params->dwDuration) impl->modified = TRUE; + impl->params.dwDuration = params->dwDuration; + } + if (flags & DIEP_GAIN) + { + if (impl->params.dwGain != params->dwGain) impl->modified = TRUE; + impl->params.dwGain = params->dwGain; + } + if (flags & DIEP_SAMPLEPERIOD) + { + if (impl->params.dwSamplePeriod != params->dwSamplePeriod) impl->modified = TRUE; + impl->params.dwSamplePeriod = params->dwSamplePeriod; + } + if (flags & DIEP_STARTDELAY) + { + if (impl->params.dwStartDelay != params->dwStartDelay) impl->modified = TRUE; + impl->params.dwStartDelay = params->dwStartDelay; + } + if (flags & DIEP_TRIGGERREPEATINTERVAL) + { + if (impl->params.dwTriggerRepeatInterval != params->dwTriggerRepeatInterval) + impl->modified = TRUE; + impl->params.dwTriggerRepeatInterval = params->dwTriggerRepeatInterval; + } + + if (flags & DIEP_TRIGGERBUTTON) + { + if (!object_flags) return DIERR_INVALIDPARAM; + + filter.dwObj = params->dwTriggerButton; + old_value = impl->params.dwTriggerButton; + ret = enum_objects( impl->joystick, &filter, DIDFT_BUTTON, set_parameters_object, + &impl->params.dwTriggerButton ); + if (ret != DIENUM_STOP) impl->params.dwTriggerButton = -1; + if (impl->params.dwTriggerButton != old_value) impl->modified = TRUE; + } + + impl->flags |= flags; + + if (flags & DIEP_NODOWNLOAD) return DI_DOWNLOADSKIPPED; + if (flags & DIEP_START) return IDirectInputEffect_Start( iface, 1, 0 ); + if (FAILED(hr = IDirectInputEffect_Download( iface ))) return hr; + if (hr == DI_NOEFFECT) return DI_DOWNLOADSKIPPED; + return DI_OK; }
static HRESULT WINAPI hid_joystick_effect_Start( IDirectInputEffect *iface, DWORD iterations, DWORD flags ) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index fc6a235617c..70c55136602 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5370,7 +5370,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%u", cAxes ); desc.dwFlags |= DIEFF_CARTESIAN; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_POLAR; @@ -5379,7 +5378,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_SPHERICAL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); @@ -5393,7 +5391,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); - todo_wine check_member( desc, expect_desc_init, "%p", rglDirection ); ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
@@ -5411,7 +5408,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); - todo_wine check_member( desc, expect_desc_init, "%p", rglDirection ); todo_wine check_member( desc, expect_desc_init, "%p", lpEnvelope ); @@ -5439,15 +5435,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
hr = IDirectInputEffect_SetParameters( effect, NULL, DIEP_NODOWNLOAD ); - todo_wine ok( hr == E_POINTER, "SetParameters returned %#x\n", hr ); memset( &desc, 0, sizeof(desc) ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); desc.dwSize = sizeof(DIEFFECT); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); @@ -5455,7 +5448,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); set_hid_expect( file, NULL, 0 ); hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Acquire( device ); @@ -5463,13 +5455,11 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
desc.dwTriggerButton = -1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%u", dwDuration ); check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); check_member( desc, expect_desc_init, "%u", dwGain ); @@ -5491,26 +5481,20 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); desc.dwDuration = 0; flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%u", dwDuration ); - todo_wine check_member( desc, expect_desc, "%u", dwSamplePeriod ); - todo_wine check_member( desc, expect_desc, "%u", dwGain ); check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); - todo_wine check_member( desc, expect_desc, "%u", dwTriggerRepeatInterval ); check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%p", rglDirection ); check_member( desc, expect_desc_init, "%p", lpEnvelope ); check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams ); - todo_wine check_member( desc, expect_desc, "%u", dwStartDelay );
hr = IDirectInputEffect_Download( effect ); @@ -5522,29 +5506,22 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.lpEnvelope = NULL; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); desc.lpEnvelope = &envelope; envelope.dwSize = 0; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
desc.lpEnvelope = &envelope; envelope.dwSize = sizeof(DIENVELOPE); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( envelope, expect_envelope, "%u", dwAttackLevel ); - todo_wine check_member( envelope, expect_envelope, "%u", dwAttackTime ); - todo_wine check_member( envelope, expect_envelope, "%u", dwFadeLevel ); - todo_wine check_member( envelope, expect_envelope, "%u", dwFadeTime );
hr = IDirectInputEffect_Download( effect ); @@ -5562,13 +5539,10 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = NULL; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ALLPARAMS | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
desc.dwFlags = DIEFF_OBJECTOFFSETS; @@ -5577,45 +5551,32 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.rgdwAxes[0] = DIJOFS_X; desc.dwTriggerButton = DIJOFS_BUTTON( 1 ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_ALREADYINITIALIZED, "SetParameters returned %#x\n", hr );
desc.cAxes = 0; desc.dwFlags = DIEFF_OBJECTIDS; desc.rgdwAxes = axes; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%u", cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%#x", dwTriggerButton ); - todo_wine check_member( desc, expect_desc, "%u", cAxes ); - todo_wine check_member( desc, expect_desc, "%u", rgdwAxes[0] ); - todo_wine check_member( desc, expect_desc, "%u", rgdwAxes[1] ); - todo_wine check_member( desc, expect_desc, "%u", rgdwAxes[2] );
desc.dwFlags = DIEFF_OBJECTOFFSETS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.dwTriggerButton == 0x30, "got %#x expected %#x\n", desc.dwTriggerButton, 0x30 ); - todo_wine ok( desc.rgdwAxes[0] == 8, "got %#x expected %#x\n", desc.rgdwAxes[0], 8 ); ok( desc.rgdwAxes[1] == 0, "got %#x expected %#x\n", desc.rgdwAxes[1], 0 ); - todo_wine ok( desc.rgdwAxes[2] == 4, "got %#x expected %#x\n", desc.rgdwAxes[2], 4 );
hr = IDirectInputEffect_Download( effect ); @@ -5629,56 +5590,41 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cAxes = 0; desc.rglDirection = directions; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); desc.cAxes = 3; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); desc.dwFlags = DIEFF_POLAR; desc.cAxes = 3; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
desc.dwFlags = DIEFF_SPHERICAL; desc.cAxes = 1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine + ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL ); check_member( desc, expect_desc, "%u", cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%u", cAxes ); - todo_wine ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 3000 ); - todo_wine ok( desc.rglDirection[1] == 30000, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 30000 ); ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 ); desc.dwFlags = DIEFF_CARTESIAN; desc.cAxes = 2; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine + ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN ); check_member( desc, expect_desc, "%u", cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc, "%u", cAxes ); - todo_wine ok( desc.rglDirection[0] == 4330, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 4330 ); - todo_wine ok( desc.rglDirection[1] == 2500, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 2500 ); - todo_wine ok( desc.rglDirection[2] == -8660, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], -8660 ); desc.dwFlags = DIEFF_POLAR; desc.cAxes = 3; @@ -5695,25 +5641,18 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = &periodic; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); desc.cbTypeSpecificParams = sizeof(DIPERIODIC); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( periodic, expect_periodic, "%u", dwMagnitude ); - todo_wine check_member( periodic, expect_periodic, "%d", lOffset ); - todo_wine check_member( periodic, expect_periodic, "%u", dwPhase ); - todo_wine check_member( periodic, expect_periodic, "%u", dwPeriod );
hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD ); @@ -5821,23 +5760,18 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.rglDirection[1] = 0; desc.rglDirection[2] = 0; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); desc.rglDirection[0] = 0;
desc.dwFlags = DIEFF_SPHERICAL; desc.cAxes = 1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine + ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL ); ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); - todo_wine ok( desc.rglDirection[0] == 30000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 30000 ); ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 ); ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 ); @@ -5845,34 +5779,25 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwFlags = DIEFF_CARTESIAN; desc.cAxes = 1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine + ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN ); ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); - todo_wine ok( desc.rglDirection[0] == 5000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 5000 ); - todo_wine ok( desc.rglDirection[1] == -8660, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], -8660 ); ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
desc.dwFlags = DIEFF_POLAR; desc.cAxes = 1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); - todo_wine + ok( desc.dwFlags == DIEFF_POLAR, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_POLAR ); ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes ); - todo_wine ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 3000 ); ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 ); ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 87fe27afadd..c11b3500e52 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -92,7 +92,10 @@ struct pid_effect_update ULONG type_coll; ULONG axes_coll; ULONG axis_count; + ULONG direction_coll; + ULONG direction_count; struct hid_value_caps *axis_caps[6]; + struct hid_value_caps *direction_caps[6]; struct hid_value_caps *duration_caps; struct hid_value_caps *gain_caps; struct hid_value_caps *sample_period_caps; @@ -1138,6 +1141,7 @@ static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, D } if (effect_update->trigger_button_caps) info->dwDynamicParams |= DIEP_TRIGGERBUTTON; if (effect_update->trigger_repeat_interval_caps) info->dwDynamicParams |= DIEP_TRIGGERREPEATINTERVAL; + if (effect_update->direction_coll) info->dwDynamicParams |= DIEP_DIRECTION; if (effect_update->axes_coll) info->dwDynamicParams |= DIEP_AXES;
if (!(collection = effect_update->type_coll)) return DIERR_DEVICENOTREG; @@ -1831,6 +1835,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * SET_SUB_COLLECTION( effect_update, type_coll ); break; case PID_USAGE_AXES_ENABLE: SET_SUB_COLLECTION( effect_update, axes_coll ); break; + case PID_USAGE_DIRECTION: SET_SUB_COLLECTION( effect_update, direction_coll ); break; } }
@@ -1887,6 +1892,13 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap else effect_update->axis_caps[effect_update->axis_count] = caps; effect_update->axis_count++; } + if (instance->wCollectionNumber == effect_update->direction_coll) + { + SET_REPORT_ID( effect_update ); + if (effect_update->direction_count >= 6) FIXME( "more than 6 PID directions detected\n" ); + else effect_update->direction_caps[effect_update->direction_count] = caps; + effect_update->direction_count++; + }
#undef SET_REPORT_ID
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 157 ++++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 33 -------- 2 files changed, 153 insertions(+), 37 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index c11b3500e52..b727ab16976 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -131,6 +131,7 @@ struct hid_joystick BYTE device_state_report_id; BYTE device_state[DEVICE_STATE_MAX_SIZE];
+ BYTE effect_inuse[255]; struct list effect_list; struct pid_control_report pid_device_control; struct pid_control_report pid_effect_control; @@ -260,6 +261,19 @@ static const WCHAR *effect_guid_to_string( const GUID *guid ) return NULL; }
+static HRESULT find_next_effect_id( struct hid_joystick *impl, ULONG *index ) +{ + ULONG i; + + for (i = 0; i < ARRAY_SIZE(impl->effect_inuse); ++i) + if (!impl->effect_inuse[i]) break; + if (i == ARRAY_SIZE(impl->effect_inuse)) return DIERR_DEVICEFULL; + impl->effect_inuse[i] = TRUE; + *index = i + 1; + + return DI_OK; +} + typedef BOOL (*enum_object_callback)( struct hid_joystick *impl, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data );
@@ -1179,6 +1193,12 @@ static HRESULT WINAPI hid_joystick_GetForceFeedbackState( IDirectInputDevice8W * return DIERR_UNSUPPORTED; }
+static BOOL CALLBACK unload_effect_object( IDirectInputEffect *effect, void *context ) +{ + IDirectInputEffect_Unload( effect ); + return DIENUM_CONTINUE; +} + static HRESULT WINAPI hid_joystick_SendForceFeedbackCommand( IDirectInputDevice8W *iface, DWORD command ) { struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); @@ -1210,6 +1230,8 @@ static HRESULT WINAPI hid_joystick_SendForceFeedbackCommand( IDirectInputDevice8 hr = DIERR_NOTEXCLUSIVEACQUIRED; else { + if (command == DISFFC_RESET) IDirectInputDevice8_EnumCreatedEffectObjects( iface, unload_effect_object, NULL, 0 ); + count = 1; status = HidP_InitializeReportForID( HidP_Output, report->id, impl->preparsed, report_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) hr = status; @@ -1875,7 +1897,11 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap if (instance->wUsage == PID_USAGE_DURATION) effect_update->duration_caps = caps; if (instance->wUsage == PID_USAGE_GAIN) + { + caps->physical_min = 0; + caps->physical_max = 10000; effect_update->gain_caps = caps; + } if (instance->wUsage == PID_USAGE_SAMPLE_PERIOD) effect_update->sample_period_caps = caps; if (instance->wUsage == PID_USAGE_START_DELAY) @@ -1895,6 +1921,8 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap if (instance->wCollectionNumber == effect_update->direction_coll) { SET_REPORT_ID( effect_update ); + caps->physical_min = 0; + caps->physical_max = 36000 - 36000 / (caps->logical_max - caps->logical_min); if (effect_update->direction_count >= 6) FIXME( "more than 6 PID directions detected\n" ); else effect_update->direction_caps[effect_update->direction_count] = caps; effect_update->direction_count++; @@ -2089,6 +2117,7 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) TRACE( "iface %p, ref %u.\n", iface, ref ); if (!ref) { + IDirectInputEffect_Unload( iface ); EnterCriticalSection( &impl->joystick->base.crit ); list_remove( &impl->entry ); LeaveCriticalSection( &impl->joystick->base.crit ); @@ -2568,16 +2597,136 @@ 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 ) +{ + ULONG report_len = impl->joystick->caps.OutputReportByteLength; + PHIDP_PREPARSED_DATA preparsed = impl->joystick->preparsed; + LONG log_min, log_max, phy_min, phy_max; + NTSTATUS status; + + if (!caps) return; + + log_min = caps->logical_min; + log_max = caps->logical_max; + phy_min = caps->physical_min; + phy_max = caps->physical_max; + + if (value > phy_max || value < phy_min) value = -1; + else value = log_min + (value - phy_min) * (log_max - log_min) / (phy_max - phy_min); + status = HidP_SetUsageValue( HidP_Output, caps->usage_page, caps->link_collection, + caps->usage_min, value, preparsed, report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsageValue %04x:%04x returned %#x\n", + caps->usage_page, caps->usage_min, status ); +} + +static void set_parameter_value_us( struct hid_joystick_effect *impl, char *report_buf, + struct hid_value_caps *caps, LONG value ) +{ + LONG exp; + if (!caps) return; + exp = caps->units_exp; + if (caps->units != 0x1003) WARN( "unknown time unit caps %x\n", caps->units ); + else if (exp < -6) while (exp++ < -6) value *= 10; + else if (exp > -6) while (exp-- > -6) value /= 10; + set_parameter_value( impl, report_buf, caps, value ); +} + static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) { - FIXME( "iface %p stub!\n", iface ); - return DIERR_UNSUPPORTED; + static const DWORD complete_mask = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + struct pid_effect_update *effect_update = &impl->joystick->pid_effect_update; + ULONG report_len = impl->joystick->caps.OutputReportByteLength; + HANDLE device = impl->joystick->device; + struct hid_value_caps *caps; + DWORD i, tmp, count; + NTSTATUS status; + USAGE usage; + HRESULT hr; + + TRACE( "iface %p\n", iface ); + + EnterCriticalSection( &impl->joystick->base.crit ); + if (impl->modified) hr = DI_OK; + else hr = DI_NOEFFECT; + + if (!impl->joystick->base.acquired || !(impl->joystick->base.dwCoopLevel & DISCL_EXCLUSIVE)) + hr = DIERR_NOTEXCLUSIVEACQUIRED; + else if ((impl->flags & complete_mask) != complete_mask) + hr = DIERR_INCOMPLETEEFFECT; + else if (!impl->index && !FAILED(hr = find_next_effect_id( impl->joystick, &impl->index ))) + { + status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX, + impl->index, impl->joystick->preparsed, impl->effect_update_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) hr = status; + else hr = DI_OK; + } + + if (hr == DI_OK) + { + set_parameter_value_us( impl, impl->effect_update_buf, effect_update->duration_caps, + impl->params.dwDuration ); + set_parameter_value( impl, impl->effect_update_buf, effect_update->gain_caps, + impl->params.dwGain ); + set_parameter_value_us( impl, impl->effect_update_buf, effect_update->sample_period_caps, + impl->params.dwSamplePeriod ); + set_parameter_value_us( impl, impl->effect_update_buf, effect_update->start_delay_caps, + impl->params.dwStartDelay ); + set_parameter_value_us( impl, impl->effect_update_buf, effect_update->trigger_repeat_interval_caps, + impl->params.dwTriggerRepeatInterval ); + + if (impl->flags & DIEP_DIRECTION) + { + count = 1; + usage = PID_USAGE_DIRECTION_ENABLE; + status = HidP_SetUsages( HidP_Output, HID_USAGE_PAGE_PID, 0, &usage, &count, + impl->joystick->preparsed, impl->effect_update_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsages returned %#x\n", status ); + + if (!effect_update->direction_count) WARN( "no PID effect direction caps found\n" ); + else for (i = 0; i < impl->params.cAxes - 1; ++i) + { + tmp = impl->directions[i] + (i == 0 ? 9000 : 0); + caps = effect_update->direction_caps[effect_update->direction_count - i - 1]; + set_parameter_value( impl, impl->effect_update_buf, caps, tmp % 36000 ); + } + } + + status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_TRIGGER_BUTTON, + impl->params.dwTriggerButton, impl->joystick->preparsed, + impl->effect_update_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsageValue returned %#x\n", status ); + + if (WriteFile( device, impl->effect_update_buf, report_len, NULL, NULL )) hr = DI_OK; + else hr = DIERR_INPUTLOST; + + impl->modified = FALSE; + } + LeaveCriticalSection( &impl->joystick->base.crit ); + + return hr; }
static HRESULT WINAPI hid_joystick_effect_Unload( IDirectInputEffect *iface ) { - FIXME( "iface %p stub!\n", iface ); - return DIERR_UNSUPPORTED; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + struct hid_joystick *joystick = impl->joystick; + HRESULT hr = DI_OK; + + TRACE( "iface %p\n", iface ); + + EnterCriticalSection( &joystick->base.crit ); + if (!impl->index) + hr = DI_NOEFFECT; + else if (!FAILED(hr = IDirectInputEffect_Stop( iface ))) + { + impl->joystick->effect_inuse[impl->index - 1] = FALSE; + impl->index = 0; + } + LeaveCriticalSection( &joystick->base.crit ); + + return hr; }
static HRESULT WINAPI hid_joystick_effect_Escape( IDirectInputEffect *iface, DIEFFESCAPE *escape ) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 70c55136602..9030d9cf157 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5108,7 +5108,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 3, .report_len = 9, .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,0x06,0x00,0x01}, @@ -5116,7 +5115,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) /* start command when DIEP_START is set */ { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02,0x01,0x01,0x01}, @@ -5125,7 +5123,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) struct hid_expect expect_start = { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02, 0x01, 0x01, 0x01}, @@ -5133,7 +5130,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) struct hid_expect expect_start_solo = { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02, 0x01, 0x02, 0x01}, @@ -5141,7 +5137,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) struct hid_expect expect_start_0 = { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02, 0x01, 0x01, 0x00}, @@ -5149,7 +5144,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) struct hid_expect expect_start_4 = { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02, 0x01, 0x01, 0x04}, @@ -5157,7 +5151,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) struct hid_expect expect_stop = { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02, 0x01, 0x03, 0x00}, @@ -5166,7 +5159,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) { { .code = IOCTL_HID_WRITE_REPORT, - .todo = TRUE, .report_id = 2, .report_len = 4, .report_buf = {0x02,0x01,0x03,0x00}, @@ -5420,7 +5412,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); set_hid_expect( file, NULL, 0 ); hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Download returned %#x\n", hr ); set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Acquire( device ); @@ -5428,10 +5419,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
hr = IDirectInputEffect_SetParameters( effect, NULL, DIEP_NODOWNLOAD ); @@ -5472,10 +5461,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%u", dwStartDelay );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, @@ -5498,10 +5485,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc, "%u", dwStartDelay );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
desc.lpEnvelope = NULL; @@ -5525,10 +5510,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( envelope, expect_envelope, "%u", dwFadeTime );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
desc.dwFlags = 0; @@ -5580,10 +5563,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( desc.rgdwAxes[2] == 4, "got %#x expected %#x\n", desc.rgdwAxes[2], 4 );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
desc.dwFlags = DIEFF_CARTESIAN; @@ -5632,10 +5613,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
desc.cbTypeSpecificParams = 0; @@ -5662,12 +5641,10 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) ); hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DI_OK, "Download returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Download returned %#x\n", hr );
hr = IDirectInputEffect_Start( effect, 1, 0xdeadbeef ); @@ -5675,55 +5652,46 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
set_hid_expect( file, &expect_start_solo, sizeof(expect_start_solo) ); hr = IDirectInputEffect_Start( effect, 1, DIES_SOLO ); - todo_wine ok( hr == DI_OK, "Start returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, &expect_stop, sizeof(expect_stop) ); hr = IDirectInputEffect_Stop( effect ); - todo_wine ok( hr == DI_OK, "Stop returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, &expect_start, sizeof(expect_start) ); hr = IDirectInputEffect_Start( effect, 1, 0 ); - todo_wine ok( hr == DI_OK, "Start returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, &expect_start_4, sizeof(expect_start_4) ); hr = IDirectInputEffect_Start( effect, 4, 0 ); - todo_wine ok( hr == DI_OK, "Start returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, &expect_start_0, sizeof(expect_start_4) ); hr = IDirectInputEffect_Start( effect, 0, 0 ); - todo_wine ok( hr == DI_OK, "Start returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, expect_unload, sizeof(struct hid_expect) ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_OK, "Unload returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, expect_download, 4 * sizeof(struct hid_expect) ); hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_START ); - todo_wine ok( hr == DI_OK, "SetParameters returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, expect_unload, sizeof(struct hid_expect) ); hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_OK, "Unload returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) ); hr = IDirectInputEffect_Download( effect ); - todo_wine ok( hr == DI_OK, "Download returned %#x\n", hr ); set_hid_expect( file, NULL, 0 );
@@ -5743,7 +5711,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_Unload( effect ); - todo_wine ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
ref = IDirectInputEffect_Release( effect );