From ea71b9f81b527496fd1027eaa724e0b62281b037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 12 May 2022 11:25:54 +0200 Subject: [PATCH] dinput/tests: Add some Windows.Gaming.Input.ForceFeedback.ConditionForceEffect tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/dinput/tests/force_feedback.c | 172 +++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 12 deletions(-) diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index af1d7b8430e..111f250f7f6 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -4985,21 +4985,21 @@ static void test_windows_gaming_input(void) END_COLLECTION, USAGE(1, PID_USAGE_CP_OFFSET), - LOGICAL_MINIMUM(1, 0x80), - LOGICAL_MAXIMUM(1, 0x7f), - PHYSICAL_MINIMUM(2, 0xd8f0), - PHYSICAL_MAXIMUM(2, 0x2710), - REPORT_SIZE(1, 8), + LOGICAL_MINIMUM(2, -10000), + LOGICAL_MAXIMUM(2, +10000), + PHYSICAL_MINIMUM(2, -10000), + PHYSICAL_MAXIMUM(2, +10000), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT), USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT), - LOGICAL_MINIMUM(1, 0x80), - LOGICAL_MAXIMUM(1, 0x7f), - PHYSICAL_MINIMUM(2, 0xd8f0), - PHYSICAL_MAXIMUM(2, 0x2710), - REPORT_SIZE(1, 8), + LOGICAL_MINIMUM(2, -10000), + LOGICAL_MAXIMUM(2, +10000), + PHYSICAL_MINIMUM(2, -10000), + PHYSICAL_MAXIMUM(2, +10000), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), @@ -5008,7 +5008,7 @@ static void test_windows_gaming_input(void) LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, 0x00ff), PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x2710), + PHYSICAL_MAXIMUM(2, 10000), REPORT_SIZE(1, 8), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), @@ -5017,7 +5017,7 @@ static void test_windows_gaming_input(void) LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, 0x00ff), PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x2710), + PHYSICAL_MAXIMUM(2, 10000), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -5494,6 +5494,47 @@ static void test_windows_gaming_input(void) .todo = TRUE, }, }; + struct hid_expect expect_create_condition[] = + { + /* create new effect */ + { + .code = IOCTL_HID_SET_FEATURE, + .report_id = 2, + .report_len = 3, + .report_buf = {2,0x03,0x00}, + }, + /* block load */ + { + .code = IOCTL_HID_GET_FEATURE, + .report_id = 3, + .report_len = 5, + .report_buf = {3,0x01,0x01,0x00,0x00}, + }, + /* set condition */ + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 4, + .report_len = 12, + .report_buf = {4,0x01,0x00,0x70,0x17,0x7b,0x02,0xe9,0x04,0x4c,0x66,0x7f}, + .todo = TRUE, + }, + /* update effect */ + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 3, + .report_len = 18, + .report_buf = {3,0x01,0x03,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00}, + .wine_only = TRUE, + .todo = TRUE, + }, + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 3, + .report_len = 18, + .report_buf = {3,0x01,0x03,0x08,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x00,0x00,0x00}, + .todo = TRUE, + }, + }; struct hid_expect expect_create_constant[] = { /* create new effect */ @@ -5625,6 +5666,7 @@ static void test_windows_gaming_input(void) .report_buf = {5,0x01}, }, }; + static const WCHAR *condition_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConditionForceEffect; static const WCHAR *periodic_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_PeriodicForceEffect; static const WCHAR *constant_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConstantForceEffect; static const WCHAR *force_feedback_motor = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ForceFeedbackMotor; @@ -5647,11 +5689,14 @@ static void test_windows_gaming_input(void) IAsyncOperationCompletedHandler_boolean *tmp_handler; struct result_async_handler result_async_handler; IVectorView_RawGameController *controllers_view; + IConditionForceEffectFactory *condition_factory; IRawGameControllerStatics *controller_statics; EventRegistrationToken controller_added_token; IPeriodicForceEffectFactory *periodic_factory; struct bool_async_handler bool_async_handler; IVectorView_ForceFeedbackMotor *motors_view; + IConditionForceEffect *condition_effect; + ConditionForceEffectKind condition_kind; ForceFeedbackEffectAxes supported_axes; IActivationFactory *activation_factory; IPeriodicForceEffect *periodic_effect; @@ -6152,6 +6197,109 @@ static void test_windows_gaming_input(void) skip_periodic: + hr = pWindowsCreateString( condition_effect_class_name, wcslen( condition_effect_class_name ), &str ); + ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr ); + hr = pRoGetActivationFactory( str, &IID_IConditionForceEffectFactory, (void **)&condition_factory ); + todo_wine + ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr ); + pWindowsDeleteString( str ); + if (hr != S_OK) goto skip_condition; + + check_interface( condition_factory, &IID_IUnknown, TRUE ); + check_interface( condition_factory, &IID_IInspectable, TRUE ); + check_interface( condition_factory, &IID_IAgileObject, TRUE ); + check_interface( condition_factory, &IID_IActivationFactory, TRUE ); + check_interface( condition_factory, &IID_IConditionForceEffectFactory, TRUE ); + check_interface( condition_factory, &IID_IPeriodicForceEffectFactory, FALSE ); + + hr = IConditionForceEffectFactory_QueryInterface( condition_factory, &IID_IActivationFactory, (void **)&activation_factory ); + ok( hr == S_OK, "QueryInterface returned %#lx\n", hr ); + hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable ); + ok( hr == E_NOTIMPL, "ActivateInstance returned %#lx\n", hr ); + IActivationFactory_Release( activation_factory ); + + + hr = IConditionForceEffectFactory_CreateInstance( condition_factory, ConditionForceEffectKind_Spring, &effect ); + ok( hr == S_OK, "CreateInstance returned %#lx\n", hr ); + + check_interface( effect, &IID_IUnknown, TRUE ); + check_interface( effect, &IID_IInspectable, TRUE ); + check_interface( effect, &IID_IAgileObject, TRUE ); + check_interface( effect, &IID_IForceFeedbackEffect, TRUE ); + check_interface( effect, &IID_IConditionForceEffect, TRUE ); + check_interface( effect, &IID_IPeriodicForceEffect, FALSE ); + check_runtimeclass( effect, condition_effect_class_name ); + + hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IConditionForceEffect, (void **)&condition_effect ); + ok( hr == S_OK, "QueryInterface returned %#lx\n", hr ); + + hr = IConditionForceEffect_get_Kind( condition_effect, &condition_kind ); + ok( hr == S_OK, "get_Kind returned %#lx\n", hr ); + ok( condition_kind == ConditionForceEffectKind_Spring, "got kind %u\n", condition_kind ); + hr = IConditionForceEffect_SetParameters( condition_effect, direction, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 ); + todo_wine + ok( hr == S_OK, "SetParameters returned %#lx\n", hr ); + IConditionForceEffect_Release( condition_effect ); + + set_hid_expect( file, expect_create_condition, sizeof(expect_create_condition) ); + hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async ); + ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr ); + result_async_handler = default_result_async_handler; + result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() ); + hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface ); + ok( hr == S_OK, "put_Completed returned %#lx\n", hr ); + ret = WaitForSingleObject( result_async_handler.event, 5000 ); + ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + ret = CloseHandle( result_async_handler.event ); + ok( ret, "CloseHandle failed, error %lu\n", GetLastError() ); + check_result_async( result_async, 1, Completed, S_OK, ForceFeedbackLoadEffectResult_Succeeded ); + ref = IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async ); + ok( ref == 0, "Release returned %lu\n", ref ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); + hr = IForceFeedbackEffect_Start( effect ); + todo_wine + ok( hr == S_OK, "Start returned %#lx\n", hr ); + set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); + hr = IForceFeedbackEffect_Start( effect ); + todo_wine + ok( hr == S_OK, "Start returned %#lx\n", hr ); + + set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); + hr = IForceFeedbackEffect_Stop( effect ); + todo_wine + ok( hr == S_OK, "Stop returned %#lx\n", hr ); + set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); + hr = IForceFeedbackEffect_Stop( effect ); + todo_wine + ok( hr == S_OK, "Stop returned %#lx\n", hr ); + + set_hid_expect( file, expect_unload, sizeof(expect_unload) ); + hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async ); + ok( hr == S_OK, "TryUnloadEffectAsync returned %#lx\n", hr ); + bool_async_handler = default_bool_async_handler; + bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() ); + hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface ); + ok( hr == S_OK, "put_Completed returned %#lx\n", hr ); + ret = WaitForSingleObject( bool_async_handler.event, 5000 ); + ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + ret = CloseHandle( bool_async_handler.event ); + ok( ret, "CloseHandle failed, error %lu\n", GetLastError() ); + check_bool_async( bool_async, 1, Completed, S_OK, TRUE ); + ref = IAsyncOperation_boolean_Release( bool_async ); + ok( ref == 0, "Release returned %lu\n", ref ); + set_hid_expect( file, NULL, 0 ); + + ref = IForceFeedbackEffect_Release( effect ); + ok( ref == 0, "Release returned %lu\n", ref ); + + IConditionForceEffectFactory_Release( condition_factory ); + + +skip_condition: hr = pWindowsCreateString( constant_effect_class_name, wcslen( constant_effect_class_name ), &str ); ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr ); hr = pRoGetActivationFactory( str, &IID_IActivationFactory, (void **)&activation_factory );