Using a notification event to wait for input, addressing spurious failures or timeouts.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/device.c | 101 ++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 34 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 3cad4ce256c..5ae9e225dc9 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -90,67 +90,100 @@ static void flush_events(void) } }
-static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWORD event, UINT_PTR expected) +static void test_device_input( IDirectInputDevice8A *device, DWORD type, DWORD code, UINT_PTR expected ) { HRESULT hr; DIDEVICEOBJECTDATA obj_data; - DWORD data_size = 1; + DWORD res, data_size = 1; + HANDLE event; int i;
- hr = IDirectInputDevice8_Acquire(lpdid); - ok (SUCCEEDED(hr), "Failed to acquire device hr=%08x\n", hr); + event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( event != NULL, "CreateEventW failed, error %u\n", GetLastError() );
- if (event_type == INPUT_KEYBOARD) - keybd_event(0, event, KEYEVENTF_SCANCODE, 0); + IDirectInputDevice_Unacquire( device );
- if (event_type == INPUT_MOUSE) - mouse_event( event, 0, 0, 0, 0); + hr = IDirectInputDevice8_SetEventNotification( device, event ); + ok( hr == DI_OK, "SetEventNotification returned %#x\n", hr );
- flush_events(); - IDirectInputDevice8_Poll(lpdid); - hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); + hr = IDirectInputDevice8_Acquire( device ); + ok( hr == DI_OK, "Acquire returned %#x\n", hr );
- if (data_size != 1) + if (type == INPUT_KEYBOARD) { - win_skip("We're not able to inject input into Windows dinput8 with events\n"); - IDirectInputDevice_Unacquire(lpdid); - return; + keybd_event( 0, code, KEYEVENTF_SCANCODE, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + + keybd_event( 0, code, KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + } + if (type == INPUT_MOUSE) + { + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); }
- ok (obj_data.uAppData == expected, "Retrieval of action failed uAppData=%lu expected=%lu\n", obj_data.uAppData, expected); + hr = IDirectInputDevice8_GetDeviceData( device, sizeof(obj_data), &obj_data, &data_size, 0 ); + ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr ); + ok( data_size == 1, "got data size %u, expected 1\n", data_size ); + ok( obj_data.uAppData == expected, "got action uAppData %p, expected %p\n", + (void *)obj_data.uAppData, (void *)expected );
/* Check for buffer overflow */ for (i = 0; i < 17; i++) - if (event_type == INPUT_KEYBOARD) + { + if (type == INPUT_KEYBOARD) { - keybd_event( VK_SPACE, DIK_SPACE, 0, 0); - keybd_event( VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0); - } - else if (event_type == INPUT_MOUSE) - { - mouse_event(MOUSEEVENTF_LEFTDOWN, 1, 1, 0, 0); - mouse_event(MOUSEEVENTF_LEFTUP, 1, 1, 0, 0); - } + keybd_event( VK_SPACE, DIK_SPACE, 0, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res );
- flush_events(); - IDirectInputDevice8_Poll(lpdid); + keybd_event( VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + } + if (type == INPUT_MOUSE) + { + mouse_event( MOUSEEVENTF_LEFTDOWN, 1, 1, 0, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + + mouse_event( MOUSEEVENTF_LEFTUP, 1, 1, 0, 0 ); + res = WaitForSingleObject( event, 100 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res ); + } + }
data_size = 1; - hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); - ok(hr == DI_BUFFEROVERFLOW, "GetDeviceData() failed: %08x\n", hr); + hr = IDirectInputDevice8_GetDeviceData( device, sizeof(obj_data), &obj_data, &data_size, 0 ); + ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#x\n", hr ); data_size = 1; - hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); - ok(hr == DI_OK && data_size == 1, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size); + hr = IDirectInputDevice8_GetDeviceData( device, sizeof(obj_data), &obj_data, &data_size, 0 ); + ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr ); + ok( data_size == 1, "got data_size %u, expected 1\n", data_size );
/* drain device's queue */ while (data_size == 1) { - hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); - ok(hr == DI_OK, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size); + hr = IDirectInputDevice8_GetDeviceData( device, sizeof(obj_data), &obj_data, &data_size, 0 ); + ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr ); if (hr != DI_OK) break; }
- IDirectInputDevice_Unacquire(lpdid); + hr = IDirectInputDevice_Unacquire( device ); + ok( hr == DI_OK, "Unacquire returned %#x\n", hr ); + + hr = IDirectInputDevice8_SetEventNotification( device, NULL ); + ok( hr == DI_OK, "SetEventNotification returned %#x\n", hr ); + + CloseHandle( event ); }
static void test_build_action_map(IDirectInputDevice8A *lpdid, DIACTIONFORMATA *lpdiaf,
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/Makefile.in | 2 +- dlls/dinput8/tests/hid.c | 360 ++++++++++++++++++++++++--------- 2 files changed, 262 insertions(+), 100 deletions(-)
diff --git a/dlls/dinput8/tests/Makefile.in b/dlls/dinput8/tests/Makefile.in index 579cf3d2f4b..18624b9d523 100644 --- a/dlls/dinput8/tests/Makefile.in +++ b/dlls/dinput8/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = dinput8.dll -IMPORTS = dinput8 ole32 user32 hid advapi32 uuid crypt32 newdev setupapi wintrust +IMPORTS = dinput8 dinput ole32 user32 hid advapi32 uuid crypt32 newdev setupapi wintrust
driver_hid_IMPORTS = winecrt0 ntoskrnl hal hidclass driver_hid_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 57fc7272369..59111db7f3a 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3321,18 +3321,37 @@ static BOOL CALLBACK find_test_device( const DIDEVICEINSTANCEW *devinst, void *c return DIENUM_CONTINUE; }
+struct check_objects_todos +{ + BOOL type; + BOOL guid; + BOOL usage; +}; + struct check_objects_params { + DWORD version; UINT index; UINT expect_count; const DIDEVICEOBJECTINSTANCEW *expect_objs; + const struct check_objects_todos *todo_objs; + BOOL todo_extra; };
static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *args ) { static const DIDEVICEOBJECTINSTANCEW unexpected_obj = {0}; + static const struct check_objects_todos todo_none = {0}; struct check_objects_params *params = args; const DIDEVICEOBJECTINSTANCEW *exp = params->expect_objs + params->index; + const struct check_objects_todos *todo; + + if (!params->todo_objs) todo = &todo_none; + else todo = params->todo_objs + params->index; + + todo_wine_if( params->todo_extra && params->index >= params->expect_count ) + ok( params->index < params->expect_count, "unexpected extra object\n" ); + if (params->index >= params->expect_count) return DIENUM_STOP;
winetest_push_context( "obj[%d]", params->index );
@@ -3340,8 +3359,11 @@ static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *ar if (params->index >= params->expect_count) exp = &unexpected_obj;
check_member( *obj, *exp, "%u", dwSize ); + todo_wine_if( todo->guid ) check_member_guid( *obj, *exp, guidType ); + todo_wine_if( params->version < 0x700 && (obj->dwType & DIDFT_BUTTON) ) check_member( *obj, *exp, "%#x", dwOfs ); + todo_wine_if( todo->type ) check_member( *obj, *exp, "%#x", dwType ); check_member( *obj, *exp, "%#x", dwFlags ); if (!localized) todo_wine check_member_wstr( *obj, *exp, tszName ); @@ -3350,6 +3372,7 @@ static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *ar check_member( *obj, *exp, "%u", wCollectionNumber ); check_member( *obj, *exp, "%u", wDesignatorIndex ); check_member( *obj, *exp, "%#04x", wUsagePage ); + todo_wine_if( todo->usage ) check_member( *obj, *exp, "%#04x", wUsage ); check_member( *obj, *exp, "%#04x", dwDimension ); check_member( *obj, *exp, "%#04x", wExponent ); @@ -3709,6 +3732,7 @@ static void test_simple_joystick(void)
struct check_objects_params check_objects_params = { + .version = DIRECTINPUT_VERSION, .expect_count = ARRAY_SIZE(expect_objects), .expect_objs = expect_objects, }; @@ -5303,7 +5327,7 @@ static BOOL test_device_types(void) return success; }
-static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) +static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version ) { struct hid_expect expect_download[] = { @@ -5326,7 +5350,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 11, - .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0xd5}, + .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5}, }, /* start command when DIEP_START is set */ { @@ -5395,9 +5419,9 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) .report_buf = {1, 0x01}, }; static const DWORD expect_axes_init[2] = {0}; - static const DIEFFECT expect_desc_init = + const DIEFFECT expect_desc_init = { - .dwSize = sizeof(DIEFFECT), + .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5), .dwTriggerButton = -1, .rgdwAxes = (void *)expect_axes_init, }; @@ -5428,9 +5452,9 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) .dwPhase = 3000, .dwPeriod = 4000, }; - static const DIEFFECT expect_desc = + const DIEFFECT expect_desc = { - .dwSize = sizeof(DIEFFECT), + .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5), .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS, .dwDuration = 1000, .dwSamplePeriod = 2000, @@ -5474,19 +5498,30 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#x\n", hr ); ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count );
- hr = IDirectInputEffect_Initialize( effect, NULL, DIRECTINPUT_VERSION, &GUID_Sine ); + hr = IDirectInputEffect_Initialize( effect, NULL, version, &GUID_Sine ); ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#x\n", hr ); + hr = IDirectInputEffect_Initialize( effect, instance, 0x800 - (version - 0x700), &GUID_Sine ); + if (version == 0x800) + { + todo_wine + ok( hr == DIERR_BETADIRECTINPUTVERSION, "Initialize returned %#x\n", hr ); + } + else + { + todo_wine + ok( hr == DIERR_OLDDIRECTINPUTVERSION, "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 ); + hr = IDirectInputEffect_Initialize( effect, instance, version, NULL ); ok( hr == E_POINTER, "Initialize returned %#x\n", hr );
- hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, &GUID_NULL ); + hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_NULL ); ok( hr == DIERR_DEVICENOTREG, "Initialize returned %#x\n", hr ); - hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, &GUID_Sine ); + hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Sine ); ok( hr == DI_OK, "Initialize returned %#x\n", hr ); - hr = IDirectInputEffect_Initialize( effect, instance, DIRECTINPUT_VERSION, &GUID_Square ); + hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Square ); ok( hr == DI_OK, "Initialize returned %#x\n", hr );
hr = IDirectInputEffect_GetEffectGuid( effect, NULL ); @@ -5502,7 +5537,15 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); - desc.dwSize = sizeof(DIEFFECT); + desc.dwSize = sizeof(DIEFFECT_DX5) + 2; + hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); + ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); + desc.dwSize = sizeof(DIEFFECT_DX5); + hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_STARTDELAY ); + ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); + desc.dwSize = sizeof(DIEFFECT_DX6); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
@@ -5522,18 +5565,21 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", dwDuration ); memset( &desc, 0xcd, sizeof(desc) ); - desc.dwSize = sizeof(DIEFFECT); + desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5); desc.dwFlags = 0; - flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; + desc.dwStartDelay = 0xdeadbeef; + flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL | + (version >= 0x700 ? DIEP_STARTDELAY : 0); hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); check_member( desc, expect_desc_init, "%u", dwGain ); - check_member( desc, expect_desc_init, "%u", dwStartDelay ); + if (version >= 0x700) check_member( desc, expect_desc_init, "%u", dwStartDelay ); + else ok( desc.dwStartDelay == 0xdeadbeef, "got dwStartDelay %#x\n", desc.dwStartDelay ); check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
memset( &desc, 0xcd, sizeof(desc) ); - desc.dwSize = sizeof(DIEFFECT); + desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5); desc.dwFlags = 0; desc.lpEnvelope = NULL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); @@ -5552,7 +5598,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.lpEnvelope = NULL; desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = NULL; - hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); + hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 ); ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); @@ -5606,7 +5652,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.lpEnvelope = &envelope; desc.cbTypeSpecificParams = sizeof(periodic); desc.lpvTypeSpecificParams = &periodic; - hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); + hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", dwDuration ); check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); @@ -5621,7 +5667,8 @@ 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 ); - check_member( desc, expect_desc_init, "%u", dwStartDelay ); + if (version >= 0x700) check_member( desc, expect_desc_init, "%u", dwStartDelay ); + else ok( desc.dwStartDelay == 0xcdcdcdcd, "got dwStartDelay %#x\n", desc.dwStartDelay );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Unacquire( device ); @@ -5644,7 +5691,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) memset( &desc, 0, sizeof(desc) ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD ); ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); - desc.dwSize = sizeof(DIEFFECT); + desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD ); ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
@@ -5681,12 +5728,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) hr = IDirectInputEffect_Unload( effect ); 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 ); + flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL | DIEP_NODOWNLOAD; + if (version >= 0x700) flags |= DIEP_STARTDELAY; + hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags ); ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); desc.dwDuration = 0; - flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; + flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL; + if (version >= 0x700) flags |= DIEP_STARTDELAY; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc, "%u", dwDuration ); @@ -5698,7 +5746,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%p", rglDirection ); check_member( desc, expect_desc_init, "%p", lpEnvelope ); check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams ); - check_member( desc, expect_desc, "%u", dwStartDelay ); + if (version >= 0x700) check_member( desc, expect_desc, "%u", dwStartDelay ); + else ok( desc.dwStartDelay == 0, "got dwStartDelay %#x\n", desc.dwStartDelay );
hr = IDirectInputEffect_Download( effect ); ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr ); @@ -5737,7 +5786,8 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.lpEnvelope = NULL; desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = NULL; - hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ALLPARAMS | DIEP_NODOWNLOAD ); + flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5; + hr = IDirectInputEffect_SetParameters( effect, &desc, flags | DIEP_NODOWNLOAD ); ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD ); ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); @@ -5989,7 +6039,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( ref == 0, "Release returned %d\n", ref ); }
-static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) +static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version ) { struct hid_expect expect_create[] = { @@ -6012,7 +6062,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 11, - .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0x00}, + .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00}, }, }; struct hid_expect expect_create_1[] = @@ -6029,7 +6079,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 11, - .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x00,0x00}, + .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x00,0x00}, }, }; struct hid_expect expect_create_2[] = @@ -6046,7 +6096,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 11, - .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0x00}, + .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00}, }, }; struct hid_expect expect_destroy = @@ -6101,9 +6151,9 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) .lDeadBand = -12000, }, }; - static const DIEFFECT expect_desc = + const DIEFFECT expect_desc = { - .dwSize = sizeof(DIEFFECT), + .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5), .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS, .dwDuration = 1000, .dwSamplePeriod = 2000, @@ -6127,7 +6177,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) DWORD axes[4] = {0}; DIEFFECT desc = { - .dwSize = sizeof(DIEFFECT), + .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5), .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS, .cAxes = 4, .rgdwAxes = axes, @@ -6155,7 +6205,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) ok( IsEqualGUID( &guid, &GUID_Spring ), "got guid %s, expected %s\n", debugstr_guid( &guid ), debugstr_guid( &GUID_Spring ) );
- hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); + hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc, "%u", dwDuration ); check_member( desc, expect_desc, "%u", dwSamplePeriod ); @@ -6168,7 +6218,8 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc, "%d", rglDirection[0] ); check_member( desc, expect_desc, "%d", rglDirection[1] ); check_member( desc, expect_desc, "%u", cbTypeSpecificParams ); - check_member( desc, expect_desc, "%u", dwStartDelay ); + if (version >= 0x700) check_member( desc, expect_desc, "%u", dwStartDelay ); + else ok( desc.dwStartDelay == 0, "got dwStartDelay %#x\n", desc.dwStartDelay ); check_member( envelope, expect_envelope, "%u", dwAttackLevel ); check_member( envelope, expect_envelope, "%u", dwAttackTime ); check_member( envelope, expect_envelope, "%u", dwFadeLevel ); @@ -6222,7 +6273,7 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file ) set_hid_expect( file, NULL, 0 ); }
-static void test_force_feedback_joystick( void ) +static void test_force_feedback_joystick( DWORD version ) { #include "psh_hid_macros.h" const unsigned char report_descriptor[] = { @@ -6550,12 +6601,13 @@ static void test_force_feedback_joystick( void ) { .InputReportByteLength = 5, }; - static const DIDEVCAPS expect_caps = + const DIDEVCAPS expect_caps = { .dwSize = sizeof(DIDEVCAPS), .dwFlags = DIDC_FORCEFEEDBACK | DIDC_ATTACHED | DIDC_EMULATED | DIDC_STARTDELAY | DIDC_FFFADE | DIDC_FFATTACK | DIDC_DEADBAND | DIDC_SATURATION, - .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK, + .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK + : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK, .dwAxes = 3, .dwButtons = 2, .dwFFSamplePeriod = 1000000, @@ -6576,13 +6628,76 @@ static void test_force_feedback_joystick( void ) .dwSize = sizeof(DIDEVICEINSTANCEW), .guidInstance = expect_guid_product, .guidProduct = expect_guid_product, - .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK, + .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK + : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK, .tszInstanceName = L"Wine test root driver", .tszProductName = L"Wine test root driver", .guidFFDriver = IID_IDirectInputPIDDriver, .wUsagePage = HID_USAGE_PAGE_GENERIC, .wUsage = HID_USAGE_GENERIC_JOYSTICK, }; + const DIDEVICEOBJECTINSTANCEW expect_objects_5[] = + { + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_XAxis, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0)|DIDFT_FFACTUATOR, + .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR, + .tszName = L"X Axis", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_GENERIC, + .wUsage = HID_USAGE_GENERIC_X, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_YAxis, + .dwOfs = 0x4, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1)|DIDFT_FFACTUATOR, + .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR, + .tszName = L"Y Axis", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_GENERIC, + .wUsage = HID_USAGE_GENERIC_Y, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_ZAxis, + .dwOfs = 0x8, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2)|DIDFT_FFACTUATOR, + .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR, + .tszName = L"Z Axis", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_GENERIC, + .wUsage = HID_USAGE_GENERIC_Z, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = 0x30, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER, + .dwFlags = DIDOI_FFEFFECTTRIGGER, + .tszName = L"Button 0", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_BUTTON, + .wUsage = 0x1, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Button, + .dwOfs = 0x31, + .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER, + .dwFlags = DIDOI_FFEFFECTTRIGGER, + .tszName = L"Button 1", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_BUTTON, + .wUsage = 0x2, + .wReportId = 1, + }, + }; const DIDEVICEOBJECTINSTANCEW expect_objects[] = { { @@ -6623,7 +6738,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Button, - .dwOfs = 0x64, + .dwOfs = version >= 0x800 ? 0x64 : 0x10, .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER, .dwFlags = DIDOI_FFEFFECTTRIGGER, .tszName = L"Button 0", @@ -6635,7 +6750,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Button, - .dwOfs = 0x65, + .dwOfs = version >= 0x800 ? 0x65 : 0x11, .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER, .dwFlags = DIDOI_FFEFFECTTRIGGER, .tszName = L"Button 1", @@ -6647,7 +6762,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x6c, + .dwOfs = version >= 0x800 ? 0x6c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(12)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"DC Device Reset", @@ -6659,7 +6774,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x10, + .dwOfs = version >= 0x800 ? 0x10 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(13)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Effect Block Index", @@ -6671,7 +6786,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x6d, + .dwOfs = version >= 0x800 ? 0x6d : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(14)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Op Effect Start", @@ -6683,7 +6798,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x6e, + .dwOfs = version >= 0x800 ? 0x6e : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(15)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Op Effect Start Solo", @@ -6695,7 +6810,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x6f, + .dwOfs = version >= 0x800 ? 0x6f : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(16)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Op Effect Stop", @@ -6707,7 +6822,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x14, + .dwOfs = version >= 0x800 ? 0x14 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(17)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Loop Count", @@ -6719,7 +6834,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x18, + .dwOfs = version >= 0x800 ? 0x18 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(18)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Effect Block Index", @@ -6731,7 +6846,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x70, + .dwOfs = version >= 0x800 ? 0x70 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(19)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"ET Square", @@ -6743,7 +6858,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x71, + .dwOfs = version >= 0x800 ? 0x71 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(20)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"ET Sine", @@ -6755,7 +6870,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x72, + .dwOfs = version >= 0x800 ? 0x72 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(21)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"ET Spring", @@ -6767,7 +6882,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x73, + .dwOfs = version >= 0x800 ? 0x73 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(22)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Z Axis", @@ -6779,7 +6894,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x74, + .dwOfs = version >= 0x800 ? 0x74 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(23)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Y Axis", @@ -6791,7 +6906,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x75, + .dwOfs = version >= 0x800 ? 0x75 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(24)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"X Axis", @@ -6803,7 +6918,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x76, + .dwOfs = version >= 0x800 ? 0x76 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(25)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Direction Enable", @@ -6815,7 +6930,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x1c, + .dwOfs = version >= 0x800 ? 0x1c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(26)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Start Delay", @@ -6829,7 +6944,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x20, + .dwOfs = version >= 0x800 ? 0x20 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(27)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Duration", @@ -6843,7 +6958,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x24, + .dwOfs = version >= 0x800 ? 0x24 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(28)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Trigger Button", @@ -6855,7 +6970,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x28, + .dwOfs = version >= 0x800 ? 0x28 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(29)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Unknown 29", @@ -6868,7 +6983,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x2c, + .dwOfs = version >= 0x800 ? 0x2c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(30)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Unknown 30", @@ -6881,7 +6996,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x30, + .dwOfs = version >= 0x800 ? 0x30 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(31)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Magnitude", @@ -6893,7 +7008,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x34, + .dwOfs = version >= 0x800 ? 0x34 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(32)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Fade Level", @@ -6905,7 +7020,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x38, + .dwOfs = version >= 0x800 ? 0x38 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(33)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Attack Level", @@ -6917,7 +7032,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x3c, + .dwOfs = version >= 0x800 ? 0x3c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(34)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Fade Time", @@ -6931,7 +7046,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x40, + .dwOfs = version >= 0x800 ? 0x40 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(35)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Attack Time", @@ -6945,7 +7060,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x44, + .dwOfs = version >= 0x800 ? 0x44 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(36)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Unknown 36", @@ -6957,7 +7072,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x48, + .dwOfs = version >= 0x800 ? 0x48 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(37)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Unknown 37", @@ -6969,7 +7084,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x4c, + .dwOfs = version >= 0x800 ? 0x4c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(38)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"CP Offset", @@ -6981,7 +7096,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x50, + .dwOfs = version >= 0x800 ? 0x50 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(39)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Negative Coefficient", @@ -6993,7 +7108,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x54, + .dwOfs = version >= 0x800 ? 0x54 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(40)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Positive Coefficient", @@ -7005,7 +7120,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x58, + .dwOfs = version >= 0x800 ? 0x58 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(41)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Negative Saturation", @@ -7017,7 +7132,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x5c, + .dwOfs = version >= 0x800 ? 0x5c : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(42)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Positive Saturation", @@ -7029,7 +7144,7 @@ static void test_force_feedback_joystick( void ) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Unknown, - .dwOfs = 0x60, + .dwOfs = version >= 0x800 ? 0x60 : 0, .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(43)|DIDFT_OUTPUT, .dwFlags = 0x80008000, .tszName = L"Dead Band", @@ -7199,10 +7314,19 @@ static void test_force_feedback_joystick( void ) } };
+ struct check_objects_todos todo_objects_5[ARRAY_SIZE(expect_objects_5)] = + { + {.guid = TRUE, .type = TRUE, .usage = TRUE}, + {0}, + {.guid = TRUE, .type = TRUE, .usage = TRUE}, + }; struct check_objects_params check_objects_params = { - .expect_count = ARRAY_SIZE(expect_objects), - .expect_objs = expect_objects, + .version = version, + .expect_count = version < 0x700 ? ARRAY_SIZE(expect_objects_5) : ARRAY_SIZE(expect_objects), + .expect_objs = version < 0x700 ? expect_objects_5 : expect_objects, + .todo_objs = version < 0x700 ? todo_objects_5 : NULL, + .todo_extra = version < 0x700 ? TRUE : FALSE, }; struct check_effects_params check_effects_params = { @@ -7234,13 +7358,16 @@ static void test_force_feedback_joystick( void ) IDirectInputDevice8W *device; DIEFFESCAPE escape = {0}; DIDEVCAPS caps = {0}; - IDirectInput8W *di; - char buffer[1024]; + IDirectInput8W *di8; + IDirectInputW *di; ULONG res, ref; + char buffer[1024]; HANDLE file; HRESULT hr; HWND hwnd;
+ winetest_push_context( "version %#x", version ); + GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd ); GetTempPathW( ARRAY_SIZE(tempdir), tempdir ); SetCurrentDirectoryW( tempdir ); @@ -7248,24 +7375,59 @@ static void test_force_feedback_joystick( void ) cleanup_registry_keys(); if (!dinput_driver_start( report_descriptor, sizeof(report_descriptor), &hid_caps )) goto done;
- hr = DirectInput8Create( instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W, (void **)&di, NULL ); - if (FAILED(hr)) + if (version >= 0x800) { - win_skip( "DirectInput8Create returned %#x\n", hr ); - goto done; - } + hr = DirectInput8Create( instance, version, &IID_IDirectInput8W, (void **)&di8, NULL ); + if (FAILED(hr)) + { + win_skip( "DirectInput8Create returned %#x\n", hr ); + goto done; + }
- hr = IDirectInput8_EnumDevices( di, DI8DEVCLASS_ALL, find_test_device, &devinst, DIEDFL_ALLDEVICES ); - ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr ); - if (!IsEqualGUID( &devinst.guidProduct, &expect_guid_product )) + hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, find_test_device, &devinst, DIEDFL_ALLDEVICES ); + ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr ); + if (!IsEqualGUID( &devinst.guidProduct, &expect_guid_product )) + { + win_skip( "device not found, skipping tests\n" ); + ref = IDirectInput8_Release( di8 ); + ok( ref == 0, "Release returned %d\n", ref ); + goto done; + } + + hr = IDirectInput8_CreateDevice( di8, &expect_guid_product, &device, NULL ); + ok( hr == DI_OK, "CreateDevice returned %#x\n", hr ); + + ref = IDirectInput8_Release( di8 ); + todo_wine + ok( ref == 0, "Release returned %d\n", ref ); + } + else { - win_skip( "device not found, skipping tests\n" ); - IDirectInput8_Release( di ); - goto done; - } + hr = DirectInputCreateEx( instance, version, &IID_IDirectInput2W, (void **)&di, NULL ); + if (FAILED(hr)) + { + win_skip( "DirectInputCreateEx returned %#x\n", hr ); + goto done; + }
- hr = IDirectInput8_CreateDevice( di, &expect_guid_product, &device, NULL ); - ok( hr == DI_OK, "CreateDevice returned %#x\n", hr ); + hr = IDirectInput_EnumDevices( di, 0, find_test_device, &devinst, DIEDFL_ALLDEVICES ); + ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr ); + if (!IsEqualGUID( &devinst.guidProduct, &expect_guid_product )) + { + win_skip( "device not found, skipping tests\n" ); + + ref = IDirectInput_Release( di ); + ok( ref == 0, "Release returned %d\n", ref ); + goto done; + } + + hr = IDirectInput_CreateDevice( di, &expect_guid_product, (IDirectInputDeviceW **)&device, NULL ); + ok( hr == DI_OK, "CreateDevice returned %#x\n", hr ); + + ref = IDirectInput_Release( di ); + todo_wine + ok( ref == 0, "Release returned %d\n", ref ); + }
hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst ); ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr ); @@ -7435,11 +7597,11 @@ static void test_force_feedback_joystick( void ) objdata.dwData = 0x80; res = 1; hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), &objdata, &res, 0 ); - todo_wine - ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr ); + if (version < 0x800) ok( hr == DI_OK, "SendDeviceData returned %#x\n", hr ); + else todo_wine ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr );
- test_periodic_effect( device, file ); - test_condition_effect( device, file ); + test_periodic_effect( device, file, version ); + test_condition_effect( device, file, version );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Unacquire( device ); @@ -7452,13 +7614,11 @@ static void test_force_feedback_joystick( void ) DestroyWindow( hwnd ); CloseHandle( file );
- ref = IDirectInput8_Release( di ); - ok( ref == 0, "Release returned %d\n", ref ); - done: pnp_driver_stop(); cleanup_registry_keys(); SetCurrentDirectoryW( cwd ); + winetest_pop_context(); }
START_TEST( hid ) @@ -7504,7 +7664,9 @@ START_TEST( hid ) if (test_device_types()) { test_simple_joystick(); - test_force_feedback_joystick(); + test_force_feedback_joystick( 0x500 ); + test_force_feedback_joystick( 0x700 ); + test_force_feedback_joystick( 0x800 ); } CoUninitialize();
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51922 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 131 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 59111db7f3a..4c1d73112cd 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5476,7 +5476,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO LONG directions[4] = {0}; DIEFFECT desc = {0}; DWORD axes[4] = {0}; - ULONG ref, flags; + ULONG i, ref, flags; HRESULT hr; GUID guid;
@@ -6037,6 +6037,135 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
ref = IDirectInputEffect_Release( effect ); ok( ref == 0, "Release returned %d\n", ref ); + + for (i = 1; i < 4; i++) + { + winetest_push_context( "%u axes", i ); + hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL ); + ok( hr == DI_OK, "CreateEffect returned %#x\n", hr ); + + desc.dwFlags = DIEFF_OBJECTIDS; + desc.cAxes = i; + desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR; + desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR; + desc.rgdwAxes[2] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR; + desc.rglDirection[0] = 0; + desc.rglDirection[1] = 0; + desc.rglDirection[2] = 0; + hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD ); + ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); + + desc.dwFlags = DIEFF_CARTESIAN; + desc.cAxes = i == 3 ? 2 : 3; + desc.rglDirection[0] = 1000; + desc.rglDirection[1] = 2000; + desc.rglDirection[2] = 3000; + hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); + todo_wine_if( i == 2 ) + ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); + desc.cAxes = i; + hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); + todo_wine_if( i == 1 ) + ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr ); + + desc.dwFlags = DIEFF_SPHERICAL; + desc.cAxes = i; + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + desc.cAxes = 3; + memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) ); + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes ); + if (i == 1) + { + ok( desc.rglDirection[0] == 0, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 0 ); + ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n", + desc.rglDirection[1], 0xcdcdcdcd ); + ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 0xcdcdcdcd ); + } + else + { + todo_wine + ok( desc.rglDirection[0] == 6343, "got rglDirection[0] %d expected %d\n", + desc.rglDirection[0], 6343 ); + if (i == 2) + { + ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", + desc.rglDirection[1], 0 ); + ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 0xcdcdcdcd ); + } + else + { + todo_wine + ok( desc.rglDirection[1] == 5330, "got rglDirection[1] %d expected %d\n", + desc.rglDirection[1], 5330 ); + ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 0 ); + } + } + + desc.dwFlags = DIEFF_CARTESIAN; + desc.cAxes = i; + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + desc.cAxes = 3; + memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) ); + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes ); + todo_wine + ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 1000 ); + if (i == 1) + ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n", + desc.rglDirection[1], 0xcdcdcdcd ); + else + { + todo_wine + ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %d expected %d\n", + desc.rglDirection[1], 2000 ); + } + if (i <= 2) + ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 0xcdcdcdcd ); + else + { + todo_wine + ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 3000 ); + } + + desc.dwFlags = DIEFF_POLAR; + desc.cAxes = 1; + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + if (i != 2) + { + todo_wine_if( i == 3 ) + ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); + } + else ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); + desc.cAxes = 3; + memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) ); + hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); + if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); + else + { + ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); + ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes ); + todo_wine + ok( desc.rglDirection[0] == 15343, "got rglDirection[0] %d expected %d\n", + desc.rglDirection[0], 15343 ); + ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 ); + ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n", + desc.rglDirection[2], 0xcdcdcdcd ); + } + + ref = IDirectInputEffect_Release( effect ); + ok( ref == 0, "Release returned %d\n", ref ); + winetest_pop_context(); + } }
static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51922 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 2 +- dlls/dinput8/tests/hid.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index dfaf6ae83ff..dd77f557e3e 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2224,7 +2224,7 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa 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 ((direction_flags & DIEFF_CARTESIAN) && params->cAxes != count) return DIERR_INVALIDPARAM;
if (!count) memset( directions, 0, sizeof(directions) ); else if (direction_flags & DIEFF_POLAR) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 4c1d73112cd..54109593a18 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -6061,11 +6061,9 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO desc.rglDirection[1] = 2000; desc.rglDirection[2] = 3000; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine_if( i == 2 ) ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr ); desc.cAxes = i; hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD ); - todo_wine_if( i == 1 ) ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
desc.dwFlags = DIEFF_SPHERICAL;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51922 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 4 ++-- dlls/dinput8/tests/hid.c | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index dd77f557e3e..cec02ccd74a 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2063,14 +2063,14 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa if (!direction_flags) return DIERR_INVALIDPARAM;
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_POLAR) && count != 2) return DIERR_INVALIDPARAM; + if (capacity < params->cAxes) return DIERR_MOREDATA;
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; } diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 54109593a18..5b01ea3a68a 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -6138,11 +6138,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO desc.dwFlags = DIEFF_POLAR; desc.cAxes = 1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - if (i != 2) - { - todo_wine_if( i == 3 ) - ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); - } + if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); else ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr ); desc.cAxes = 3; memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 182 +++++++++++++++++++++++++++---------- dlls/dinput8/tests/hid.c | 7 -- 2 files changed, 134 insertions(+), 55 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index cec02ccd74a..a9716b20ab5 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2017,6 +2017,127 @@ static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_val return DIENUM_STOP; }
+static void convert_directions_to_spherical( const DIEFFECT *in, DIEFFECT *out ) +{ + DWORD i, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL; + + switch (in->dwFlags & direction_flags) + { + case DIEFF_CARTESIAN: + for (i = 1; i < in->cAxes; ++i) + out->rglDirection[i - 1] = atan2( in->rglDirection[i], in->rglDirection[0] ); + out->rglDirection[in->cAxes - 1] = 0; + out->cAxes = in->cAxes; + break; + case DIEFF_POLAR: + out->rglDirection[0] = (in->rglDirection[0] % 36000) - 9000; + if (out->rglDirection[0] < 0) out->rglDirection[0] += 36000; + for (i = 1; i < in->cAxes; ++i) out->rglDirection[i] = 0; + out->cAxes = in->cAxes; + break; + case DIEFF_SPHERICAL: + for (i = 0; i < in->cAxes; ++i) + { + out->rglDirection[i] = in->rglDirection[i] % 36000; + if (out->rglDirection[i] < 0) out->rglDirection[i] += 36000; + } + out->cAxes = in->cAxes; + break; + } +} + +static void convert_directions_from_spherical( const DIEFFECT *in, DIEFFECT *out ) +{ + DWORD i, j, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL; + LONG tmp; + + switch (out->dwFlags & direction_flags) + { + case DIEFF_CARTESIAN: + out->rglDirection[0] = 10000; + for (i = 1; i <= in->cAxes; ++i) + { + tmp = cos( in->rglDirection[i - 1] * M_PI / 18000 ) * 10000; + for (j = 0; j < i; ++j) + out->rglDirection[j] = round( out->rglDirection[j] * tmp / 10000.0 ); + out->rglDirection[i] = sin( in->rglDirection[i - 1] * M_PI / 18000 ) * 10000; + } + out->cAxes = in->cAxes; + break; + case DIEFF_POLAR: + out->rglDirection[0] = (in->rglDirection[0] + 9000) % 36000; + if (out->rglDirection[0] < 0) out->rglDirection[0] += 36000; + out->rglDirection[1] = 0; + out->cAxes = 2; + break; + case DIEFF_SPHERICAL: + for (i = 0; i < in->cAxes; ++i) + { + out->rglDirection[i] = in->rglDirection[i] % 36000; + if (out->rglDirection[i] < 0) out->rglDirection[i] += 36000; + } + out->cAxes = in->cAxes; + break; + } +} + +static void convert_directions( const DIEFFECT *in, DIEFFECT *out ) +{ + DWORD direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL; + LONG directions[6] = {0}; + DIEFFECT spherical = {.rglDirection = directions}; + + switch (in->dwFlags & direction_flags) + { + case DIEFF_CARTESIAN: + switch (out->dwFlags & direction_flags) + { + case DIEFF_CARTESIAN: + memcpy( out->rglDirection, in->rglDirection, in->cAxes * sizeof(LONG) ); + out->cAxes = in->cAxes; + break; + case DIEFF_POLAR: + convert_directions_to_spherical( in, &spherical ); + convert_directions_from_spherical( &spherical, out ); + break; + case DIEFF_SPHERICAL: + convert_directions_to_spherical( in, out ); + break; + } + break; + + case DIEFF_POLAR: + switch (out->dwFlags & direction_flags) + { + case DIEFF_POLAR: + memcpy( out->rglDirection, in->rglDirection, in->cAxes * sizeof(LONG) ); + out->cAxes = in->cAxes; + break; + case DIEFF_CARTESIAN: + convert_directions_to_spherical( in, &spherical ); + convert_directions_from_spherical( &spherical, out ); + break; + case DIEFF_SPHERICAL: + convert_directions_to_spherical( in, out ); + break; + } + break; + + case DIEFF_SPHERICAL: + switch (out->dwFlags & direction_flags) + { + case DIEFF_POLAR: + case DIEFF_CARTESIAN: + convert_directions_from_spherical( in, out ); + break; + case DIEFF_SPHERICAL: + convert_directions_to_spherical( in, out ); + break; + } + break; + } +} + static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags ) { DIPROPHEADER filter = @@ -2026,8 +2147,7 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa .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}; + ULONG i, count, capacity, object_flags, direction_flags; BOOL ret;
TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags ); @@ -2067,27 +2187,9 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM; if (capacity < params->cAxes) return DIERR_MOREDATA;
- if (direction_flags & DIEFF_SPHERICAL) - memcpy( directions, impl->params.rglDirection, count * sizeof(LONG) ); - else if (direction_flags & DIEFF_POLAR) - { - 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 (!count) params->rglDirection = NULL; else if (!params->rglDirection) return DIERR_INVALIDPARAM; - else memcpy( params->rglDirection, directions, count * sizeof(LONG) ); + else convert_directions( &impl->params, params ); }
if (flags & DIEP_TYPESPECIFICPARAMS) @@ -2182,7 +2284,6 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa }; 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;
@@ -2226,31 +2327,11 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM; if ((direction_flags & DIEFF_CARTESIAN) && params->cAxes != count) 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->params.dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + impl->params.dwFlags |= direction_flags; + if (memcmp( impl->params.rglDirection, params->rglDirection, count * sizeof(LONG) )) impl->modified = TRUE; - memcpy( impl->params.rglDirection, directions, count * sizeof(LONG) ); + memcpy( impl->params.rglDirection, params->rglDirection, count * sizeof(LONG) ); }
if (flags & DIEP_TYPESPECIFICPARAMS) @@ -2514,7 +2595,9 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) ULONG report_len = impl->joystick->caps.OutputReportByteLength; HANDLE device = impl->joystick->device; struct hid_value_caps *caps; + LONG directions[4] = {0}; DWORD i, tmp, count; + DIEFFECT spherical; NTSTATUS status; USAGE usage; HRESULT hr; @@ -2659,10 +2742,13 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) impl->joystick->preparsed, impl->effect_update_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsages returned %#x\n", status );
+ spherical.rglDirection = directions; + convert_directions_to_spherical( &impl->params, &spherical ); + if (!effect_update->direction_count) WARN( "no PID effect direction caps found\n" ); - else for (i = 0; i < impl->params.cAxes - 1; ++i) + else for (i = 0; i < spherical.cAxes - 1; ++i) { - tmp = impl->directions[i] + (i == 0 ? 9000 : 0); + tmp = 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 ); } diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 5b01ea3a68a..5f89f13146a 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -6114,26 +6114,19 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes ); - todo_wine ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 1000 ); if (i == 1) ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0xcdcdcdcd ); else - { - todo_wine ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 2000 ); - } if (i <= 2) ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0xcdcdcdcd ); else - { - todo_wine ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 3000 ); - }
desc.dwFlags = DIEFF_POLAR; desc.cAxes = 1;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 10 ++++++++-- dlls/dinput8/tests/hid.c | 3 --- 2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index a9716b20ab5..5a3c46e2d9a 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2019,13 +2019,19 @@ static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_val
static void convert_directions_to_spherical( const DIEFFECT *in, DIEFFECT *out ) { - DWORD i, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL; + DWORD i, j, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL; + double tmp;
switch (in->dwFlags & direction_flags) { case DIEFF_CARTESIAN: for (i = 1; i < in->cAxes; ++i) - out->rglDirection[i - 1] = atan2( in->rglDirection[i], in->rglDirection[0] ); + { + tmp = in->rglDirection[0]; + for (j = 1; j < i; ++j) tmp = sqrt( tmp * tmp + in->rglDirection[j] * in->rglDirection[j] ); + tmp = atan2( in->rglDirection[i], tmp ); + out->rglDirection[i - 1] = tmp * 18000 / M_PI; + } out->rglDirection[in->cAxes - 1] = 0; out->cAxes = in->cAxes; break; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 5f89f13146a..66e8c7c0b0d 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -6085,7 +6085,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO } else { - todo_wine ok( desc.rglDirection[0] == 6343, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 6343 ); if (i == 2) @@ -6097,7 +6096,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO } else { - todo_wine ok( desc.rglDirection[1] == 5330, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 5330 ); ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", @@ -6141,7 +6139,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO { ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes ); - todo_wine ok( desc.rglDirection[0] == 15343, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 15343 ); ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 );