dinput: Make sure converted direction values are always positive.
[wine.git] / dlls / dinput / tests / force_feedback.c
blobc471a80de00e14e1e242aff9aee4d7f3402d9191
1 /*
2 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define DIRECTINPUT_VERSION 0x0800
21 #include <stdarg.h>
22 #include <stddef.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
29 #define COBJMACROS
30 #include "dinput.h"
31 #include "dinputd.h"
32 #include "roapi.h"
33 #include "unknwn.h"
34 #include "winstring.h"
36 #include "wine/hid.h"
38 #include "dinput_test.h"
40 #define WIDL_using_Windows_Foundation
41 #define WIDL_using_Windows_Foundation_Collections
42 #define WIDL_using_Windows_Foundation_Numerics
43 #include "windows.foundation.h"
44 #define WIDL_using_Windows_Devices_Haptics
45 #define WIDL_using_Windows_Gaming_Input
46 #define WIDL_using_Windows_Gaming_Input_ForceFeedback
47 #include "windows.gaming.input.h"
48 #include "windows.gaming.input.forcefeedback.h"
49 #undef Size
51 #define MAKE_FUNC(f) static typeof(f) *p ## f
52 MAKE_FUNC( RoGetActivationFactory );
53 MAKE_FUNC( RoInitialize );
54 MAKE_FUNC( WindowsCreateString );
55 MAKE_FUNC( WindowsDeleteString );
56 MAKE_FUNC( WindowsGetStringRawBuffer );
57 #undef MAKE_FUNC
59 static BOOL load_combase_functions(void)
61 HMODULE combase = GetModuleHandleW( L"combase.dll" );
63 #define LOAD_FUNC(m, f) if (!(p ## f = (void *)GetProcAddress( m, #f ))) goto failed;
64 LOAD_FUNC( combase, RoGetActivationFactory );
65 LOAD_FUNC( combase, RoInitialize );
66 LOAD_FUNC( combase, WindowsCreateString );
67 LOAD_FUNC( combase, WindowsDeleteString );
68 LOAD_FUNC( combase, WindowsGetStringRawBuffer );
69 #undef LOAD_FUNC
71 return TRUE;
73 failed:
74 win_skip("Failed to load combase.dll functions, skipping tests\n");
75 return FALSE;
78 struct check_objects_todos
80 BOOL type;
81 BOOL guid;
82 BOOL usage;
83 BOOL name;
86 struct check_objects_params
88 DWORD version;
89 UINT index;
90 UINT expect_count;
91 const DIDEVICEOBJECTINSTANCEW *expect_objs;
92 const struct check_objects_todos *todo_objs;
93 BOOL todo_extra;
96 static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
98 static const DIDEVICEOBJECTINSTANCEW unexpected_obj = {0};
99 static const struct check_objects_todos todo_none = {0};
100 struct check_objects_params *params = args;
101 const DIDEVICEOBJECTINSTANCEW *exp = params->expect_objs + params->index;
102 const struct check_objects_todos *todo;
104 if (!params->todo_objs) todo = &todo_none;
105 else todo = params->todo_objs + params->index;
107 todo_wine_if( params->todo_extra && params->index >= params->expect_count )
108 ok( params->index < params->expect_count, "unexpected extra object\n" );
109 if (params->index >= params->expect_count) return DIENUM_STOP;
111 winetest_push_context( "obj[%d]", params->index );
113 ok( params->index < params->expect_count, "unexpected extra object\n" );
114 if (params->index >= params->expect_count) exp = &unexpected_obj;
116 check_member( *obj, *exp, "%lu", dwSize );
117 todo_wine_if( todo->guid )
118 check_member_guid( *obj, *exp, guidType );
119 todo_wine_if( params->version < 0x700 && (obj->dwType & DIDFT_BUTTON) )
120 check_member( *obj, *exp, "%#lx", dwOfs );
121 todo_wine_if( todo->type )
122 check_member( *obj, *exp, "%#lx", dwType );
123 check_member( *obj, *exp, "%#lx", dwFlags );
124 if (!localized) todo_wine_if( todo->name ) check_member_wstr( *obj, *exp, tszName );
125 check_member( *obj, *exp, "%lu", dwFFMaxForce );
126 check_member( *obj, *exp, "%lu", dwFFForceResolution );
127 check_member( *obj, *exp, "%u", wCollectionNumber );
128 check_member( *obj, *exp, "%u", wDesignatorIndex );
129 check_member( *obj, *exp, "%#04x", wUsagePage );
130 todo_wine_if( todo->usage )
131 check_member( *obj, *exp, "%#04x", wUsage );
132 check_member( *obj, *exp, "%#lx", dwDimension );
133 check_member( *obj, *exp, "%#04x", wExponent );
134 check_member( *obj, *exp, "%u", wReportId );
136 winetest_pop_context();
138 params->index++;
139 return DIENUM_CONTINUE;
142 struct check_effects_params
144 UINT index;
145 UINT expect_count;
146 const DIEFFECTINFOW *expect_effects;
149 static BOOL CALLBACK check_effects( const DIEFFECTINFOW *effect, void *args )
151 static const DIEFFECTINFOW unexpected_effect = {0};
152 struct check_effects_params *params = args;
153 const DIEFFECTINFOW *exp = params->expect_effects + params->index;
155 winetest_push_context( "effect[%d]", params->index );
157 ok( params->index < params->expect_count, "unexpected extra object\n" );
158 if (params->index >= params->expect_count) exp = &unexpected_effect;
160 check_member( *effect, *exp, "%lu", dwSize );
161 check_member_guid( *effect, *exp, guid );
162 check_member( *effect, *exp, "%#lx", dwEffType );
163 check_member( *effect, *exp, "%#lx", dwStaticParams );
164 check_member( *effect, *exp, "%#lx", dwDynamicParams );
165 check_member_wstr( *effect, *exp, tszName );
167 winetest_pop_context();
168 params->index++;
170 return DIENUM_CONTINUE;
173 static BOOL CALLBACK check_effect_count( const DIEFFECTINFOW *effect, void *args )
175 DWORD *count = args;
176 *count = *count + 1;
177 return DIENUM_CONTINUE;
180 static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect, void *context )
182 ok( 0, "unexpected effect %p\n", effect );
183 return DIENUM_CONTINUE;
186 struct check_created_effect_params
188 IDirectInputEffect *expect_effect;
189 DWORD count;
192 static BOOL CALLBACK check_created_effect_objects( IDirectInputEffect *effect, void *context )
194 struct check_created_effect_params *params = context;
195 ULONG ref;
197 ok( effect == params->expect_effect, "got effect %p, expected %p\n", effect, params->expect_effect );
198 params->count++;
200 IDirectInputEffect_AddRef( effect );
201 ref = IDirectInputEffect_Release( effect );
202 ok( ref == 1, "got ref %lu, expected 1\n", ref );
203 return DIENUM_CONTINUE;
206 static BOOL CALLBACK enum_device_count( const DIDEVICEINSTANCEW *devinst, void *context )
208 DWORD *count = context;
209 *count = *count + 1;
210 return DIENUM_CONTINUE;
213 static void check_dinput_devices( DWORD version, DIDEVICEINSTANCEW *devinst )
215 IDirectInput8W *di8;
216 IDirectInputW *di;
217 ULONG count;
218 HRESULT hr;
220 if (version >= 0x800)
222 hr = DirectInput8Create( instance, version, &IID_IDirectInput8W, (void **)&di8, NULL );
223 ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr );
225 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, NULL, NULL, DIEDFL_ALLDEVICES );
226 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
227 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, 0xdeadbeef );
228 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
229 hr = IDirectInput8_EnumDevices( di8, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
230 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
232 count = 0;
233 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, DIEDFL_ALLDEVICES );
234 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
235 ok( count == 3, "got count %lu, expected 0\n", count );
236 count = 0;
237 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
238 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
239 ok( count == 0, "got count %lu, expected 0\n", count );
240 count = 0;
241 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_POINTER, enum_device_count, &count,
242 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
243 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
244 todo_wine
245 ok( count == 3, "got count %lu, expected 3\n", count );
246 count = 0;
247 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_KEYBOARD, enum_device_count, &count,
248 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
249 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
250 todo_wine
251 ok( count == 3, "got count %lu, expected 3\n", count );
252 count = 0;
253 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_GAMECTRL, enum_device_count, &count,
254 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
255 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
256 ok( count == 1, "got count %lu, expected 1\n", count );
258 count = 0;
259 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
260 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
261 ok( count == 1, "got count %lu, expected 1\n", count );
263 count = 0;
264 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
265 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
266 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %lu, expected 0\n", count );
267 else ok( count == 1, "got count %lu, expected 1\n", count );
269 count = 0;
270 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff) + 1, enum_device_count, &count, DIEDFL_ALLDEVICES );
271 if ((devinst->dwDevType & 0xff) != DI8DEVTYPE_SUPPLEMENTAL) ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
272 else ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
273 ok( count == 0, "got count %lu, expected 0\n", count );
275 else
277 hr = DirectInputCreateEx( instance, version, &IID_IDirectInput2W, (void **)&di, NULL );
278 ok( hr == DI_OK, "DirectInputCreateEx returned %#lx\n", hr );
280 hr = IDirectInput_EnumDevices( di, 0, NULL, NULL, DIEDFL_ALLDEVICES );
281 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
282 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, 0xdeadbeef );
283 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
284 hr = IDirectInput_EnumDevices( di, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
285 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
286 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_INCLUDEHIDDEN );
287 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
289 count = 0;
290 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_ALLDEVICES );
291 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
292 ok( count == 3, "got count %lu, expected 0\n", count );
293 count = 0;
294 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
295 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
296 ok( count == 0, "got count %lu, expected 0\n", count );
297 count = 0;
298 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_MOUSE, enum_device_count, &count,
299 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
300 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
301 todo_wine
302 ok( count == 3, "got count %lu, expected 3\n", count );
303 count = 0;
304 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_KEYBOARD, enum_device_count, &count,
305 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
306 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
307 todo_wine
308 ok( count == 3, "got count %lu, expected 3\n", count );
309 count = 0;
310 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_JOYSTICK, enum_device_count, &count,
311 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
312 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
313 ok( count == 1, "got count %lu, expected 1\n", count );
315 count = 0;
316 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
317 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
318 ok( count == 1, "got count %lu, expected 1\n", count );
320 count = 0;
321 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
322 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
323 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %lu, expected 0\n", count );
324 else ok( count == 1, "got count %lu, expected 1\n", count );
326 hr = IDirectInput_EnumDevices( di, 0x14, enum_device_count, &count, DIEDFL_ALLDEVICES );
327 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
331 static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
333 struct hid_expect expect_download[] =
335 /* set periodic */
337 .code = IOCTL_HID_WRITE_REPORT,
338 .report_id = 5,
339 .report_len = 2,
340 .report_buf = {0x05,0x19},
342 /* set envelope */
344 .code = IOCTL_HID_WRITE_REPORT,
345 .report_id = 6,
346 .report_len = 7,
347 .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
349 /* update effect */
351 .code = IOCTL_HID_WRITE_REPORT,
352 .report_id = 3,
353 .report_len = 11,
354 .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5},
356 /* start command when DIEP_START is set */
358 .code = IOCTL_HID_WRITE_REPORT,
359 .report_id = 2,
360 .report_len = 4,
361 .report_buf = {0x02,0x01,0x01,0x01},
364 struct hid_expect expect_download_2[] =
366 /* set periodic */
368 .code = IOCTL_HID_WRITE_REPORT,
369 .report_id = 5,
370 .report_len = 2,
371 .report_buf = {0x05,0x19},
373 /* set envelope */
375 .code = IOCTL_HID_WRITE_REPORT,
376 .report_id = 6,
377 .report_len = 7,
378 .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
380 /* update effect */
382 .code = IOCTL_HID_WRITE_REPORT,
383 .report_id = 3,
384 .report_len = 11,
385 .report_buf = {0x03,0x01,0x02,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5},
388 struct hid_expect expect_update[] =
390 /* update effect */
392 .code = IOCTL_HID_WRITE_REPORT,
393 .report_id = 3,
394 .report_len = 11,
395 .report_buf = {0x03, 0x01, 0x02, 0x08, 0xff, 0xff, version >= 0x700 ? 0x06 : 0x00, 0x00, 0x01, 0x55, 0xd5},
398 struct hid_expect expect_set_envelope[] =
400 /* set envelope */
402 .code = IOCTL_HID_WRITE_REPORT,
403 .report_id = 6,
404 .report_len = 7,
405 .report_buf = {0x06, 0x19, 0x4c, 0x01, 0x00, 0x04, 0x00},
408 struct hid_expect expect_start =
410 .code = IOCTL_HID_WRITE_REPORT,
411 .report_id = 2,
412 .report_len = 4,
413 .report_buf = {0x02, 0x01, 0x01, 0x01},
415 struct hid_expect expect_start_solo =
417 .code = IOCTL_HID_WRITE_REPORT,
418 .report_id = 2,
419 .report_len = 4,
420 .report_buf = {0x02, 0x01, 0x02, 0x01},
422 struct hid_expect expect_start_0 =
424 .code = IOCTL_HID_WRITE_REPORT,
425 .report_id = 2,
426 .report_len = 4,
427 .report_buf = {0x02, 0x01, 0x01, 0x00},
429 struct hid_expect expect_start_4 =
431 .code = IOCTL_HID_WRITE_REPORT,
432 .report_id = 2,
433 .report_len = 4,
434 .report_buf = {0x02, 0x01, 0x01, 0x04},
436 struct hid_expect expect_stop =
438 .code = IOCTL_HID_WRITE_REPORT,
439 .report_id = 2,
440 .report_len = 4,
441 .report_buf = {0x02, 0x01, 0x03, 0x00},
443 struct hid_expect expect_unload[] =
446 .code = IOCTL_HID_WRITE_REPORT,
447 .report_id = 2,
448 .report_len = 4,
449 .report_buf = {0x02,0x01,0x03,0x00},
451 /* device reset, when unloaded from Unacquire */
453 .code = IOCTL_HID_WRITE_REPORT,
454 .report_id = 1,
455 .report_len = 2,
456 .report_buf = {1,0x01},
459 struct hid_expect expect_acquire[] =
462 .code = IOCTL_HID_WRITE_REPORT,
463 .report_id = 1,
464 .report_len = 2,
465 .report_buf = {1, 0x01},
468 .code = IOCTL_HID_WRITE_REPORT,
469 .report_id = 8,
470 .report_len = 2,
471 .report_buf = {8, 0x19},
474 struct hid_expect expect_reset[] =
477 .code = IOCTL_HID_WRITE_REPORT,
478 .report_id = 1,
479 .report_len = 2,
480 .report_buf = {1, 0x01},
483 static const DWORD expect_axes_init[2] = {0};
484 const DIEFFECT expect_desc_init =
486 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
487 .dwTriggerButton = -1,
488 .rgdwAxes = (void *)expect_axes_init,
490 static const DWORD expect_axes[3] =
492 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
493 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
494 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
496 static const LONG expect_directions[3] =
498 +3000,
499 -6000,
502 static const DIENVELOPE expect_envelope =
504 .dwSize = sizeof(DIENVELOPE),
505 .dwAttackLevel = 1000,
506 .dwAttackTime = 2000,
507 .dwFadeLevel = 3000,
508 .dwFadeTime = 4000,
510 static const DIPERIODIC expect_periodic =
512 .dwMagnitude = 1000,
513 .lOffset = 2000,
514 .dwPhase = 3000,
515 .dwPeriod = 4000,
517 const DIEFFECT expect_desc =
519 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
520 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
521 .dwDuration = 1000,
522 .dwSamplePeriod = 2000,
523 .dwGain = 3000,
524 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
525 .dwTriggerRepeatInterval = 5000,
526 .cAxes = 3,
527 .rgdwAxes = (void *)expect_axes,
528 .rglDirection = (void *)expect_directions,
529 .lpEnvelope = (void *)&expect_envelope,
530 .cbTypeSpecificParams = sizeof(DIPERIODIC),
531 .lpvTypeSpecificParams = (void *)&expect_periodic,
532 .dwStartDelay = 6000,
534 struct check_created_effect_params check_params = {0};
535 IDirectInputEffect *effect;
536 DIPERIODIC periodic = {0};
537 DIENVELOPE envelope = {0};
538 LONG directions[4] = {0};
539 DIEFFECT desc = {0};
540 DWORD axes[4] = {0};
541 ULONG i, ref, flags;
542 HRESULT hr;
543 GUID guid;
545 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, NULL, NULL );
546 ok( hr == E_POINTER, "CreateEffect returned %#lx\n", hr );
547 hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL );
548 ok( hr == E_POINTER, "CreateEffect returned %#lx\n", hr );
549 hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL );
550 ok( hr == DIERR_DEVICENOTREG, "CreateEffect returned %#lx\n", hr );
552 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
553 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
554 if (hr != DI_OK) return;
556 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef );
557 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#lx\n", hr );
558 check_params.expect_effect = effect;
559 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 );
560 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#lx\n", hr );
561 ok( check_params.count == 1, "got count %lu, expected 1\n", check_params.count );
563 hr = IDirectInputEffect_Initialize( effect, NULL, version, &GUID_Sine );
564 ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#lx\n", hr );
565 hr = IDirectInputEffect_Initialize( effect, instance, 0x800 - (version - 0x700), &GUID_Sine );
566 if (version == 0x800)
568 todo_wine
569 ok( hr == DIERR_BETADIRECTINPUTVERSION, "Initialize returned %#lx\n", hr );
571 else
573 todo_wine
574 ok( hr == DIERR_OLDDIRECTINPUTVERSION, "Initialize returned %#lx\n", hr );
576 hr = IDirectInputEffect_Initialize( effect, instance, 0, &GUID_Sine );
577 todo_wine
578 ok( hr == DIERR_NOTINITIALIZED, "Initialize returned %#lx\n", hr );
579 hr = IDirectInputEffect_Initialize( effect, instance, version, NULL );
580 ok( hr == E_POINTER, "Initialize returned %#lx\n", hr );
582 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_NULL );
583 ok( hr == DIERR_DEVICENOTREG, "Initialize returned %#lx\n", hr );
584 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Sine );
585 ok( hr == DI_OK, "Initialize returned %#lx\n", hr );
586 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Square );
587 ok( hr == DI_OK, "Initialize returned %#lx\n", hr );
589 hr = IDirectInputEffect_GetEffectGuid( effect, NULL );
590 ok( hr == E_POINTER, "GetEffectGuid returned %#lx\n", hr );
591 hr = IDirectInputEffect_GetEffectGuid( effect, &guid );
592 ok( hr == DI_OK, "GetEffectGuid returned %#lx\n", hr );
593 ok( IsEqualGUID( &guid, &GUID_Square ), "got guid %s, expected %s\n", debugstr_guid( &guid ),
594 debugstr_guid( &GUID_Square ) );
596 hr = IDirectInputEffect_GetParameters( effect, NULL, 0 );
597 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
598 hr = IDirectInputEffect_GetParameters( effect, NULL, DIEP_DURATION );
599 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
600 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
601 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
602 desc.dwSize = sizeof(DIEFFECT_DX5) + 2;
603 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
604 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
605 desc.dwSize = sizeof(DIEFFECT_DX5);
606 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
607 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
608 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_STARTDELAY );
609 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
610 desc.dwSize = sizeof(DIEFFECT_DX6);
611 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
612 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
614 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
615 hr = IDirectInputDevice8_Unacquire( device );
616 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
617 set_hid_expect( file, NULL, 0 );
618 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
619 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
620 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
621 hr = IDirectInputDevice8_Acquire( device );
622 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
623 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
625 desc.dwDuration = 0xdeadbeef;
626 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
627 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
628 check_member( desc, expect_desc_init, "%lu", dwDuration );
629 memset( &desc, 0xcd, sizeof(desc) );
630 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
631 desc.dwFlags = 0;
632 desc.dwStartDelay = 0xdeadbeef;
633 flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL |
634 (version >= 0x700 ? DIEP_STARTDELAY : 0);
635 hr = IDirectInputEffect_GetParameters( effect, &desc, flags );
636 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
637 check_member( desc, expect_desc_init, "%lu", dwSamplePeriod );
638 check_member( desc, expect_desc_init, "%lu", dwGain );
639 if (version >= 0x700) check_member( desc, expect_desc_init, "%lu", dwStartDelay );
640 else ok( desc.dwStartDelay == 0xdeadbeef, "got dwStartDelay %#lx\n", desc.dwStartDelay );
641 check_member( desc, expect_desc_init, "%lu", dwTriggerRepeatInterval );
643 memset( &desc, 0xcd, sizeof(desc) );
644 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
645 desc.dwFlags = 0;
646 desc.lpEnvelope = NULL;
647 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
648 ok( hr == E_POINTER, "GetParameters returned %#lx\n", hr );
649 desc.lpEnvelope = &envelope;
650 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
651 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
652 envelope.dwSize = sizeof(DIENVELOPE);
653 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
654 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
656 desc.dwFlags = 0;
657 desc.cAxes = 0;
658 desc.rgdwAxes = NULL;
659 desc.rglDirection = NULL;
660 desc.lpEnvelope = NULL;
661 desc.cbTypeSpecificParams = 0;
662 desc.lpvTypeSpecificParams = NULL;
663 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
664 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
665 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
666 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
667 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
668 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
669 desc.dwFlags = DIEFF_OBJECTOFFSETS;
670 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
671 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
672 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
673 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
674 check_member( desc, expect_desc_init, "%#lx", dwTriggerButton );
675 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
676 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
677 check_member( desc, expect_desc_init, "%lu", cAxes );
678 desc.dwFlags = DIEFF_OBJECTIDS;
679 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
680 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
681 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
682 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
683 check_member( desc, expect_desc_init, "%#lx", dwTriggerButton );
684 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
685 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
686 check_member( desc, expect_desc_init, "%lu", cAxes );
687 desc.dwFlags |= DIEFF_CARTESIAN;
688 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
689 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
690 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
691 desc.dwFlags |= DIEFF_POLAR;
692 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
693 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
694 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
695 desc.dwFlags |= DIEFF_SPHERICAL;
696 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
697 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
698 check_member( desc, expect_desc_init, "%lu", cAxes );
699 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
701 desc.dwFlags |= DIEFF_SPHERICAL;
702 desc.cAxes = 2;
703 desc.rgdwAxes = axes;
704 desc.rglDirection = directions;
705 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION );
706 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
707 check_member( desc, expect_desc_init, "%lu", cAxes );
708 check_member( desc, expect_desc_init, "%lu", rgdwAxes[0] );
709 check_member( desc, expect_desc_init, "%lu", rgdwAxes[1] );
710 check_member( desc, expect_desc_init, "%p", rglDirection );
711 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
713 desc.dwFlags |= DIEFF_SPHERICAL;
714 desc.lpEnvelope = &envelope;
715 desc.cbTypeSpecificParams = sizeof(periodic);
716 desc.lpvTypeSpecificParams = &periodic;
717 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
718 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
719 check_member( desc, expect_desc_init, "%lu", dwDuration );
720 check_member( desc, expect_desc_init, "%lu", dwSamplePeriod );
721 check_member( desc, expect_desc_init, "%lu", dwGain );
722 check_member( desc, expect_desc_init, "%#lx", dwTriggerButton );
723 check_member( desc, expect_desc_init, "%lu", dwTriggerRepeatInterval );
724 check_member( desc, expect_desc_init, "%lu", cAxes );
725 check_member( desc, expect_desc_init, "%lu", rgdwAxes[0] );
726 check_member( desc, expect_desc_init, "%lu", rgdwAxes[1] );
727 check_member( desc, expect_desc_init, "%p", rglDirection );
728 check_member( desc, expect_desc_init, "%p", lpEnvelope );
729 check_member( desc, expect_desc_init, "%lu", cbTypeSpecificParams );
730 if (version >= 0x700) check_member( desc, expect_desc_init, "%lu", dwStartDelay );
731 else ok( desc.dwStartDelay == 0xcdcdcdcd, "got dwStartDelay %#lx\n", desc.dwStartDelay );
733 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
734 hr = IDirectInputDevice8_Unacquire( device );
735 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
736 set_hid_expect( file, NULL, 0 );
737 hr = IDirectInputEffect_Download( effect );
738 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Download returned %#lx\n", hr );
739 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
740 hr = IDirectInputDevice8_Acquire( device );
741 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
742 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
744 hr = IDirectInputEffect_Download( effect );
745 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
746 hr = IDirectInputEffect_Unload( effect );
747 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
749 hr = IDirectInputEffect_SetParameters( effect, NULL, DIEP_NODOWNLOAD );
750 ok( hr == E_POINTER, "SetParameters returned %#lx\n", hr );
751 memset( &desc, 0, sizeof(desc) );
752 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD );
753 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
754 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
755 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD );
756 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
758 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
759 hr = IDirectInputDevice8_Unacquire( device );
760 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
761 set_hid_expect( file, NULL, 0 );
762 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION );
763 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
764 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
765 hr = IDirectInputDevice8_Acquire( device );
766 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
767 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
769 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION | DIEP_NODOWNLOAD );
770 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
772 desc.dwTriggerButton = -1;
773 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
774 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
775 check_member( desc, expect_desc, "%lu", dwDuration );
776 check_member( desc, expect_desc_init, "%lu", dwSamplePeriod );
777 check_member( desc, expect_desc_init, "%lu", dwGain );
778 check_member( desc, expect_desc_init, "%#lx", dwTriggerButton );
779 check_member( desc, expect_desc_init, "%lu", dwTriggerRepeatInterval );
780 check_member( desc, expect_desc_init, "%lu", cAxes );
781 check_member( desc, expect_desc_init, "%p", rglDirection );
782 check_member( desc, expect_desc_init, "%p", lpEnvelope );
783 check_member( desc, expect_desc_init, "%lu", cbTypeSpecificParams );
784 check_member( desc, expect_desc_init, "%lu", dwStartDelay );
786 hr = IDirectInputEffect_Download( effect );
787 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
788 hr = IDirectInputEffect_Unload( effect );
789 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
791 flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL | DIEP_NODOWNLOAD;
792 if (version >= 0x700) flags |= DIEP_STARTDELAY;
793 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags );
794 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
795 desc.dwDuration = 0;
796 flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL;
797 if (version >= 0x700) flags |= DIEP_STARTDELAY;
798 hr = IDirectInputEffect_GetParameters( effect, &desc, flags );
799 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
800 check_member( desc, expect_desc, "%lu", dwDuration );
801 check_member( desc, expect_desc, "%lu", dwSamplePeriod );
802 check_member( desc, expect_desc, "%lu", dwGain );
803 check_member( desc, expect_desc_init, "%#lx", dwTriggerButton );
804 check_member( desc, expect_desc, "%lu", dwTriggerRepeatInterval );
805 check_member( desc, expect_desc_init, "%lu", cAxes );
806 check_member( desc, expect_desc_init, "%p", rglDirection );
807 check_member( desc, expect_desc_init, "%p", lpEnvelope );
808 check_member( desc, expect_desc_init, "%lu", cbTypeSpecificParams );
809 if (version >= 0x700) check_member( desc, expect_desc, "%lu", dwStartDelay );
810 else ok( desc.dwStartDelay == 0, "got dwStartDelay %#lx\n", desc.dwStartDelay );
812 hr = IDirectInputEffect_Download( effect );
813 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
814 hr = IDirectInputEffect_Unload( effect );
815 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
817 desc.lpEnvelope = NULL;
818 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
819 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
820 desc.lpEnvelope = &envelope;
821 envelope.dwSize = 0;
822 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
823 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
825 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
826 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
828 desc.lpEnvelope = &envelope;
829 envelope.dwSize = sizeof(DIENVELOPE);
830 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
831 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
832 check_member( envelope, expect_envelope, "%lu", dwAttackLevel );
833 check_member( envelope, expect_envelope, "%lu", dwAttackTime );
834 check_member( envelope, expect_envelope, "%lu", dwFadeLevel );
835 check_member( envelope, expect_envelope, "%lu", dwFadeTime );
837 hr = IDirectInputEffect_Download( effect );
838 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
839 hr = IDirectInputEffect_Unload( effect );
840 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
842 desc.dwFlags = 0;
843 desc.cAxes = 0;
844 desc.rgdwAxes = NULL;
845 desc.rglDirection = NULL;
846 desc.lpEnvelope = NULL;
847 desc.cbTypeSpecificParams = 0;
848 desc.lpvTypeSpecificParams = NULL;
849 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
850 hr = IDirectInputEffect_SetParameters( effect, &desc, flags | DIEP_NODOWNLOAD );
851 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
852 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
853 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
854 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD );
855 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
857 desc.dwFlags = DIEFF_OBJECTOFFSETS;
858 desc.cAxes = 1;
859 desc.rgdwAxes = axes;
860 desc.rgdwAxes[0] = DIJOFS_X;
861 desc.dwTriggerButton = DIJOFS_BUTTON( 1 );
862 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
863 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
864 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
865 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
866 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
867 ok( hr == DIERR_ALREADYINITIALIZED, "SetParameters returned %#lx\n", hr );
869 desc.cAxes = 0;
870 desc.dwFlags = DIEFF_OBJECTIDS;
871 desc.rgdwAxes = axes;
872 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
873 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
874 check_member( desc, expect_desc, "%lu", cAxes );
875 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
876 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
877 check_member( desc, expect_desc, "%#lx", dwTriggerButton );
878 check_member( desc, expect_desc, "%lu", cAxes );
879 check_member( desc, expect_desc, "%lu", rgdwAxes[0] );
880 check_member( desc, expect_desc, "%lu", rgdwAxes[1] );
881 check_member( desc, expect_desc, "%lu", rgdwAxes[2] );
883 desc.dwFlags = DIEFF_OBJECTOFFSETS;
884 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
885 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
886 ok( desc.dwTriggerButton == 0x30, "got %#lx expected %#x\n", desc.dwTriggerButton, 0x30 );
887 ok( desc.rgdwAxes[0] == 8, "got %#lx expected %#x\n", desc.rgdwAxes[0], 8 );
888 ok( desc.rgdwAxes[1] == 0, "got %#lx expected %#x\n", desc.rgdwAxes[1], 0 );
889 ok( desc.rgdwAxes[2] == 4, "got %#lx expected %#x\n", desc.rgdwAxes[2], 4 );
891 hr = IDirectInputEffect_Download( effect );
892 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
893 hr = IDirectInputEffect_Unload( effect );
894 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
896 desc.dwFlags = DIEFF_CARTESIAN;
897 desc.cAxes = 0;
898 desc.rglDirection = directions;
899 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
900 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
901 desc.cAxes = 3;
902 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
903 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
904 desc.dwFlags = DIEFF_POLAR;
905 desc.cAxes = 3;
906 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
907 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
909 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
910 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
912 desc.dwFlags = DIEFF_SPHERICAL;
913 desc.cAxes = 1;
914 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
915 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
916 ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL );
917 check_member( desc, expect_desc, "%lu", cAxes );
918 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
919 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
920 check_member( desc, expect_desc, "%lu", cAxes );
921 ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 3000 );
922 ok( desc.rglDirection[1] == 30000, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], 30000 );
923 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %ld expected %d\n", desc.rglDirection[2], 0 );
924 desc.dwFlags = DIEFF_CARTESIAN;
925 desc.cAxes = 2;
926 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
927 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
928 ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN );
929 check_member( desc, expect_desc, "%lu", cAxes );
930 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
931 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
932 check_member( desc, expect_desc, "%lu", cAxes );
933 ok( desc.rglDirection[0] == 4330, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 4330 );
934 ok( desc.rglDirection[1] == 2500, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], 2500 );
935 ok( desc.rglDirection[2] == -8660, "got rglDirection[2] %ld expected %d\n", desc.rglDirection[2], -8660 );
936 desc.dwFlags = DIEFF_POLAR;
937 desc.cAxes = 3;
938 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
939 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
941 hr = IDirectInputEffect_Download( effect );
942 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#lx\n", hr );
943 hr = IDirectInputEffect_Unload( effect );
944 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
946 desc.cbTypeSpecificParams = 0;
947 desc.lpvTypeSpecificParams = &periodic;
948 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
949 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
950 desc.cbTypeSpecificParams = sizeof(DIPERIODIC);
951 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
952 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
953 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
954 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
956 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS );
957 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
958 check_member( periodic, expect_periodic, "%lu", dwMagnitude );
959 check_member( periodic, expect_periodic, "%ld", lOffset );
960 check_member( periodic, expect_periodic, "%lu", dwPhase );
961 check_member( periodic, expect_periodic, "%lu", dwPeriod );
963 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
964 ok( hr == DIERR_NOTDOWNLOADED, "Start returned %#lx\n", hr );
965 hr = IDirectInputEffect_Stop( effect );
966 ok( hr == DIERR_NOTDOWNLOADED, "Stop returned %#lx\n", hr );
968 set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) );
969 hr = IDirectInputEffect_Download( effect );
970 ok( hr == DI_OK, "Download returned %#lx\n", hr );
971 set_hid_expect( file, NULL, 0 );
973 hr = IDirectInputEffect_Download( effect );
974 ok( hr == DI_NOEFFECT, "Download returned %#lx\n", hr );
976 hr = IDirectInputEffect_Start( effect, 1, 0xdeadbeef );
977 ok( hr == DIERR_INVALIDPARAM, "Start returned %#lx\n", hr );
979 set_hid_expect( file, &expect_start_solo, sizeof(expect_start_solo) );
980 hr = IDirectInputEffect_Start( effect, 1, DIES_SOLO );
981 ok( hr == DI_OK, "Start returned %#lx\n", hr );
982 set_hid_expect( file, NULL, 0 );
984 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
985 hr = IDirectInputEffect_Stop( effect );
986 ok( hr == DI_OK, "Stop returned %#lx\n", hr );
987 set_hid_expect( file, NULL, 0 );
989 set_hid_expect( file, &expect_start, sizeof(expect_start) );
990 hr = IDirectInputEffect_Start( effect, 1, 0 );
991 ok( hr == DI_OK, "Start returned %#lx\n", hr );
992 set_hid_expect( file, NULL, 0 );
994 set_hid_expect( file, &expect_start_4, sizeof(expect_start_4) );
995 hr = IDirectInputEffect_Start( effect, 4, 0 );
996 ok( hr == DI_OK, "Start returned %#lx\n", hr );
997 set_hid_expect( file, NULL, 0 );
999 set_hid_expect( file, &expect_start_0, sizeof(expect_start_4) );
1000 hr = IDirectInputEffect_Start( effect, 0, 0 );
1001 ok( hr == DI_OK, "Start returned %#lx\n", hr );
1002 set_hid_expect( file, NULL, 0 );
1004 set_hid_expect( file, expect_unload, sizeof(struct hid_expect) );
1005 hr = IDirectInputEffect_Unload( effect );
1006 ok( hr == DI_OK, "Unload returned %#lx\n", hr );
1007 set_hid_expect( file, NULL, 0 );
1009 set_hid_expect( file, expect_download, 4 * sizeof(struct hid_expect) );
1010 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_START );
1011 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1012 set_hid_expect( file, NULL, 0 );
1014 set_hid_expect( file, expect_unload, sizeof(struct hid_expect) );
1015 hr = IDirectInputEffect_Unload( effect );
1016 ok( hr == DI_OK, "Unload returned %#lx\n", hr );
1017 set_hid_expect( file, NULL, 0 );
1019 set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) );
1020 hr = IDirectInputEffect_Download( effect );
1021 ok( hr == DI_OK, "Download returned %#lx\n", hr );
1022 set_hid_expect( file, NULL, 0 );
1024 set_hid_expect( file, expect_unload, 2 * sizeof(struct hid_expect) );
1025 hr = IDirectInputDevice8_Unacquire( device );
1026 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
1027 set_hid_expect( file, NULL, 0 );
1029 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
1030 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Start returned %#lx\n", hr );
1031 hr = IDirectInputEffect_Stop( effect );
1032 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Stop returned %#lx\n", hr );
1034 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
1035 hr = IDirectInputDevice8_Acquire( device );
1036 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
1037 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
1039 hr = IDirectInputEffect_Unload( effect );
1040 ok( hr == DI_NOEFFECT, "Unload returned %#lx\n", hr );
1042 ref = IDirectInputEffect_Release( effect );
1043 ok( ref == 0, "Release returned %ld\n", ref );
1045 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
1046 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1048 desc.dwFlags = DIEFF_POLAR | DIEFF_OBJECTIDS;
1049 desc.cAxes = 2;
1050 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
1051 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR;
1052 desc.rglDirection[0] = 3000;
1053 desc.rglDirection[1] = 0;
1054 desc.rglDirection[2] = 0;
1055 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION | DIEP_NODOWNLOAD );
1056 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1057 desc.rglDirection[0] = 0;
1059 desc.dwFlags = DIEFF_SPHERICAL;
1060 desc.cAxes = 1;
1061 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1062 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
1063 ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL );
1064 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1065 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1066 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1067 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1068 ok( desc.rglDirection[0] == 30000, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 30000 );
1069 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], 0 );
1070 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %ld expected %d\n", desc.rglDirection[2], 0 );
1072 desc.dwFlags = DIEFF_CARTESIAN;
1073 desc.cAxes = 1;
1074 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1075 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
1076 ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN );
1077 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1078 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1079 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1080 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1081 ok( desc.rglDirection[0] == 5000, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 5000 );
1082 ok( desc.rglDirection[1] == -8660, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], -8660 );
1083 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %ld expected %d\n", desc.rglDirection[2], 0 );
1085 desc.dwFlags = DIEFF_POLAR;
1086 desc.cAxes = 1;
1087 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1088 ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
1089 ok( desc.dwFlags == DIEFF_POLAR, "got flags %#lx, expected %#x\n", desc.dwFlags, DIEFF_POLAR );
1090 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1091 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1092 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1093 ok( desc.cAxes == 2, "got cAxes %lu expected 2\n", desc.cAxes );
1094 ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 3000 );
1095 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], 0 );
1096 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %ld expected %d\n", desc.rglDirection[2], 0 );
1098 ref = IDirectInputEffect_Release( effect );
1099 ok( ref == 0, "Release returned %ld\n", ref );
1101 for (i = 1; i < 4; i++)
1103 struct hid_expect expect_directions[] =
1105 /* set periodic */
1107 .code = IOCTL_HID_WRITE_REPORT,
1108 .report_id = 5,
1109 .report_len = 2,
1110 .report_buf = {0x05,0x19},
1112 /* set envelope */
1114 .code = IOCTL_HID_WRITE_REPORT,
1115 .report_id = 6,
1116 .report_len = 7,
1117 .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
1119 /* update effect */
1120 {0},
1121 /* effect control */
1123 .code = IOCTL_HID_WRITE_REPORT,
1124 .report_id = 2,
1125 .report_len = 4,
1126 .report_buf = {0x02,0x01,0x03,0x00},
1129 struct hid_expect expect_spherical =
1131 .code = IOCTL_HID_WRITE_REPORT,
1132 .report_id = 3,
1133 .report_len = 11,
1134 .report_buf = { 0x03, 0x01, 0x02, 0x08, 0x01, 0x00, version >= 0x700 ? 0x06 : 0x00, 0x00, 0x01,
1135 i >= 2 ? 0x55 : 0, i >= 3 ? 0x1c : 0 },
1137 struct hid_expect expect_cartesian =
1139 .code = IOCTL_HID_WRITE_REPORT,
1140 .report_id = 3,
1141 .report_len = 11,
1142 .report_buf = {0x03, 0x01, 0x02, 0x08, 0x01, 0x00, version >= 0x700 ? 0x06 : 0x00, 0x00,
1143 0x01, i >= 2 ? 0x63 : 0, i >= 3 ? 0x1d : 0},
1145 struct hid_expect expect_polar =
1147 .code = IOCTL_HID_WRITE_REPORT,
1148 .report_id = 3,
1149 .report_len = 11,
1150 .report_buf = {0x03, 0x01, 0x02, 0x08, 0x01, 0x00, version >= 0x700 ? 0x06 : 0x00, 0x00,
1151 0x01, i >= 2 ? 0x3f : 0, i >= 3 ? 0x00 : 0},
1154 winetest_push_context( "%lu axes", i );
1155 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
1156 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1158 desc.dwFlags = DIEFF_OBJECTIDS;
1159 desc.cAxes = i;
1160 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
1161 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR;
1162 desc.rgdwAxes[2] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR;
1163 desc.rglDirection[0] = 0;
1164 desc.rglDirection[1] = 0;
1165 desc.rglDirection[2] = 0;
1166 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD );
1167 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1169 desc.dwFlags = DIEFF_CARTESIAN;
1170 desc.cAxes = i == 3 ? 2 : 3;
1171 desc.rglDirection[0] = 1000;
1172 desc.rglDirection[1] = 2000;
1173 desc.rglDirection[2] = 3000;
1174 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
1175 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#lx\n", hr );
1176 desc.cAxes = i;
1177 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
1178 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1180 desc.dwFlags = DIEFF_SPHERICAL;
1181 desc.cAxes = i;
1182 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1183 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1184 desc.cAxes = 3;
1185 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
1186 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1187 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1188 ok( desc.cAxes == i, "got cAxes %lu expected 2\n", desc.cAxes );
1189 if (i == 1)
1191 ok( desc.rglDirection[0] == 0, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 0 );
1192 ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %ld expected %d\n",
1193 desc.rglDirection[1], 0xcdcdcdcd );
1194 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %ld expected %d\n",
1195 desc.rglDirection[2], 0xcdcdcdcd );
1197 else
1199 ok( desc.rglDirection[0] == 6343, "got rglDirection[0] %ld expected %d\n",
1200 desc.rglDirection[0], 6343 );
1201 if (i == 2)
1203 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %ld expected %d\n",
1204 desc.rglDirection[1], 0 );
1205 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %ld expected %d\n",
1206 desc.rglDirection[2], 0xcdcdcdcd );
1208 else
1210 ok( desc.rglDirection[1] == 5330, "got rglDirection[1] %ld expected %d\n",
1211 desc.rglDirection[1], 5330 );
1212 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %ld expected %d\n",
1213 desc.rglDirection[2], 0 );
1217 desc.dwFlags = DIEFF_CARTESIAN;
1218 desc.cAxes = i;
1219 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1220 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1221 desc.cAxes = 3;
1222 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
1223 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1224 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1225 ok( desc.cAxes == i, "got cAxes %lu expected 2\n", desc.cAxes );
1226 ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %ld expected %d\n", desc.rglDirection[0], 1000 );
1227 if (i == 1)
1228 ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %ld expected %d\n",
1229 desc.rglDirection[1], 0xcdcdcdcd );
1230 else
1231 ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %ld expected %d\n",
1232 desc.rglDirection[1], 2000 );
1233 if (i <= 2)
1234 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %ld expected %d\n",
1235 desc.rglDirection[2], 0xcdcdcdcd );
1236 else
1237 ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %ld expected %d\n",
1238 desc.rglDirection[2], 3000 );
1240 desc.dwFlags = DIEFF_POLAR;
1241 desc.cAxes = 1;
1242 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1243 if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
1244 else ok( hr == DIERR_MOREDATA, "GetParameters returned %#lx\n", hr );
1245 desc.cAxes = 3;
1246 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
1247 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
1248 if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#lx\n", hr );
1249 else
1251 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1252 ok( desc.cAxes == i, "got cAxes %lu expected 2\n", desc.cAxes );
1253 ok( desc.rglDirection[0] == 15343, "got rglDirection[0] %ld expected %d\n",
1254 desc.rglDirection[0], 15343 );
1255 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %ld expected %d\n", desc.rglDirection[1], 0 );
1256 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %ld expected %d\n",
1257 desc.rglDirection[2], 0xcdcdcdcd );
1260 ref = IDirectInputEffect_Release( effect );
1261 ok( ref == 0, "Release returned %ld\n", ref );
1263 desc = expect_desc;
1264 desc.dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS;
1265 desc.cAxes = i;
1266 desc.rgdwAxes = axes;
1267 desc.rglDirection = directions;
1268 desc.rglDirection[0] = 3000;
1269 desc.rglDirection[1] = 4000;
1270 desc.rglDirection[2] = 5000;
1271 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
1272 expect_directions[2] = expect_spherical;
1273 set_hid_expect( file, expect_directions, sizeof(expect_directions) );
1274 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, &desc, &effect, NULL );
1275 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1276 ref = IDirectInputEffect_Release( effect );
1277 ok( ref == 0, "Release returned %ld\n", ref );
1278 set_hid_expect( file, NULL, 0 );
1280 desc = expect_desc;
1281 desc.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTIDS;
1282 desc.cAxes = i;
1283 desc.rgdwAxes = axes;
1284 desc.rglDirection = directions;
1285 desc.rglDirection[0] = 6000;
1286 desc.rglDirection[1] = 7000;
1287 desc.rglDirection[2] = 8000;
1288 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
1289 expect_directions[2] = expect_cartesian;
1290 set_hid_expect( file, expect_directions, sizeof(expect_directions) );
1291 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, &desc, &effect, NULL );
1292 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1293 ref = IDirectInputEffect_Release( effect );
1294 ok( ref == 0, "Release returned %ld\n", ref );
1295 set_hid_expect( file, NULL, 0 );
1297 if (i == 2)
1299 desc = expect_desc;
1300 desc.dwFlags = DIEFF_POLAR | DIEFF_OBJECTIDS;
1301 desc.cAxes = i;
1302 desc.rgdwAxes = axes;
1303 desc.rglDirection = directions;
1304 desc.rglDirection[0] = 9000;
1305 desc.rglDirection[1] = 10000;
1306 desc.rglDirection[2] = 11000;
1307 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
1308 expect_directions[2] = expect_polar;
1309 set_hid_expect( file, expect_directions, sizeof(expect_directions) );
1310 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, &desc, &effect, NULL );
1311 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1312 ref = IDirectInputEffect_Release( effect );
1313 ok( ref == 0, "Release returned %ld\n", ref );
1314 set_hid_expect( file, NULL, 0 );
1317 winetest_pop_context();
1320 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
1321 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1323 set_hid_expect( file, expect_download_2, sizeof(expect_download_2) );
1324 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
1325 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags );
1326 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1327 set_hid_expect( file, NULL, 0 );
1328 desc = expect_desc;
1329 desc.dwDuration = INFINITE;
1330 desc.dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
1331 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD | DIEP_DURATION | DIEP_TRIGGERBUTTON );
1332 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1333 set_hid_expect( file, expect_update, sizeof(expect_update) );
1334 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
1335 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1336 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
1337 desc = expect_desc;
1338 desc.dwDuration = INFINITE;
1339 desc.dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
1340 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD | DIEP_DURATION | DIEP_TRIGGERBUTTON );
1341 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1342 set_hid_expect( file, expect_update, sizeof(expect_update) );
1343 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
1344 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1345 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
1347 desc = expect_desc;
1348 desc.lpEnvelope = &envelope;
1349 desc.lpEnvelope->dwAttackTime = 1000;
1350 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD | DIEP_ENVELOPE );
1351 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1352 set_hid_expect( file, expect_set_envelope, sizeof(expect_set_envelope) );
1353 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
1354 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1355 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
1357 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
1358 ref = IDirectInputEffect_Release( effect );
1359 ok( ref == 0, "Release returned %ld\n", ref );
1360 set_hid_expect( file, NULL, 0 );
1362 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
1363 hr = IDirectInputDevice8_Unacquire( device );
1364 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
1365 set_hid_expect( file, NULL, 0 );
1366 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, &expect_desc, &effect, NULL );
1367 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1368 ref = IDirectInputEffect_Release( effect );
1369 ok( ref == 0, "Release returned %ld\n", ref );
1370 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
1371 hr = IDirectInputDevice8_Acquire( device );
1372 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
1373 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
1376 static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
1378 struct hid_expect expect_create[] =
1380 /* set condition */
1382 .code = IOCTL_HID_WRITE_REPORT,
1383 .report_id = 7,
1384 .report_len = 8,
1385 .report_buf = {0x07,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
1387 /* set condition */
1389 .code = IOCTL_HID_WRITE_REPORT,
1390 .report_id = 7,
1391 .report_len = 8,
1392 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
1394 /* update effect */
1396 .code = IOCTL_HID_WRITE_REPORT,
1397 .report_id = 3,
1398 .report_len = 11,
1399 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00},
1402 struct hid_expect expect_create_1[] =
1404 /* set condition */
1406 .code = IOCTL_HID_WRITE_REPORT,
1407 .report_id = 7,
1408 .report_len = 8,
1409 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
1411 /* update effect */
1413 .code = IOCTL_HID_WRITE_REPORT,
1414 .report_id = 3,
1415 .report_len = 11,
1416 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x3f,0x00},
1419 struct hid_expect expect_create_2[] =
1421 /* set condition */
1423 .code = IOCTL_HID_WRITE_REPORT,
1424 .report_id = 7,
1425 .report_len = 8,
1426 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
1428 /* update effect */
1430 .code = IOCTL_HID_WRITE_REPORT,
1431 .report_id = 3,
1432 .report_len = 11,
1433 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xf1},
1436 struct hid_expect expect_create_3[] =
1438 /* set condition */
1440 .code = IOCTL_HID_WRITE_REPORT,
1441 .report_id = 7,
1442 .report_len = 8,
1443 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
1445 /* update effect */
1447 .code = IOCTL_HID_WRITE_REPORT,
1448 .report_id = 3,
1449 .report_len = 11,
1450 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00},
1453 struct hid_expect expect_destroy =
1455 .code = IOCTL_HID_WRITE_REPORT,
1456 .report_id = 2,
1457 .report_len = 4,
1458 .report_buf = {0x02, 0x01, 0x03, 0x00},
1460 static const DWORD expect_axes[3] =
1462 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
1463 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
1464 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
1466 static const LONG expect_directions[3] = {
1467 +3000,
1471 static const DIENVELOPE expect_envelope =
1473 .dwSize = sizeof(DIENVELOPE),
1474 .dwAttackLevel = 1000,
1475 .dwAttackTime = 2000,
1476 .dwFadeLevel = 3000,
1477 .dwFadeTime = 4000,
1479 static const DICONDITION expect_condition[3] =
1482 .lOffset = -500,
1483 .lPositiveCoefficient = 2000,
1484 .lNegativeCoefficient = -3000,
1485 .dwPositiveSaturation = -4000,
1486 .dwNegativeSaturation = -5000,
1487 .lDeadBand = 6000,
1490 .lOffset = 6000,
1491 .lPositiveCoefficient = 5000,
1492 .lNegativeCoefficient = -4000,
1493 .dwPositiveSaturation = 3000,
1494 .dwNegativeSaturation = 2000,
1495 .lDeadBand = 1000,
1498 .lOffset = -7000,
1499 .lPositiveCoefficient = -8000,
1500 .lNegativeCoefficient = 9000,
1501 .dwPositiveSaturation = 10000,
1502 .dwNegativeSaturation = 11000,
1503 .lDeadBand = -12000,
1506 const DIEFFECT expect_desc =
1508 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
1509 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
1510 .dwDuration = 1000,
1511 .dwSamplePeriod = 2000,
1512 .dwGain = 3000,
1513 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
1514 .dwTriggerRepeatInterval = 5000,
1515 .cAxes = 2,
1516 .rgdwAxes = (void *)expect_axes,
1517 .rglDirection = (void *)expect_directions,
1518 .lpEnvelope = (void *)&expect_envelope,
1519 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
1520 .lpvTypeSpecificParams = (void *)expect_condition,
1521 .dwStartDelay = 6000,
1523 struct check_created_effect_params check_params = {0};
1524 DIENVELOPE envelope = {.dwSize = sizeof(DIENVELOPE)};
1525 DICONDITION condition[2] = {{0}};
1526 IDirectInputEffect *effect;
1527 LONG directions[4] = {0};
1528 DWORD axes[4] = {0};
1529 DIEFFECT desc =
1531 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
1532 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
1533 .cAxes = 4,
1534 .rgdwAxes = axes,
1535 .rglDirection = directions,
1536 .lpEnvelope = &envelope,
1537 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
1538 .lpvTypeSpecificParams = condition,
1540 HRESULT hr;
1541 ULONG ref;
1542 GUID guid;
1544 set_hid_expect( file, expect_create, sizeof(expect_create) );
1545 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &expect_desc, &effect, NULL );
1546 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1547 set_hid_expect( file, NULL, 0 );
1549 check_params.expect_effect = effect;
1550 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 );
1551 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#lx\n", hr );
1552 ok( check_params.count == 1, "got count %lu, expected 1\n", check_params.count );
1554 hr = IDirectInputEffect_GetEffectGuid( effect, &guid );
1555 ok( hr == DI_OK, "GetEffectGuid returned %#lx\n", hr );
1556 ok( IsEqualGUID( &guid, &GUID_Spring ), "got guid %s, expected %s\n", debugstr_guid( &guid ),
1557 debugstr_guid( &GUID_Spring ) );
1559 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
1560 ok( hr == DI_OK, "GetParameters returned %#lx\n", hr );
1561 check_member( desc, expect_desc, "%lu", dwDuration );
1562 check_member( desc, expect_desc, "%lu", dwSamplePeriod );
1563 check_member( desc, expect_desc, "%lu", dwGain );
1564 check_member( desc, expect_desc, "%#lx", dwTriggerButton );
1565 check_member( desc, expect_desc, "%lu", dwTriggerRepeatInterval );
1566 check_member( desc, expect_desc, "%lu", cAxes );
1567 check_member( desc, expect_desc, "%#lx", rgdwAxes[0] );
1568 check_member( desc, expect_desc, "%#lx", rgdwAxes[1] );
1569 check_member( desc, expect_desc, "%ld", rglDirection[0] );
1570 check_member( desc, expect_desc, "%ld", rglDirection[1] );
1571 check_member( desc, expect_desc, "%lu", cbTypeSpecificParams );
1572 if (version >= 0x700) check_member( desc, expect_desc, "%lu", dwStartDelay );
1573 else ok( desc.dwStartDelay == 0, "got dwStartDelay %#lx\n", desc.dwStartDelay );
1574 check_member( envelope, expect_envelope, "%lu", dwAttackLevel );
1575 check_member( envelope, expect_envelope, "%lu", dwAttackTime );
1576 check_member( envelope, expect_envelope, "%lu", dwFadeLevel );
1577 check_member( envelope, expect_envelope, "%lu", dwFadeTime );
1578 check_member( condition[0], expect_condition[0], "%ld", lOffset );
1579 check_member( condition[0], expect_condition[0], "%ld", lPositiveCoefficient );
1580 check_member( condition[0], expect_condition[0], "%ld", lNegativeCoefficient );
1581 check_member( condition[0], expect_condition[0], "%lu", dwPositiveSaturation );
1582 check_member( condition[0], expect_condition[0], "%lu", dwNegativeSaturation );
1583 check_member( condition[0], expect_condition[0], "%ld", lDeadBand );
1584 check_member( condition[1], expect_condition[1], "%ld", lOffset );
1585 check_member( condition[1], expect_condition[1], "%ld", lPositiveCoefficient );
1586 check_member( condition[1], expect_condition[1], "%ld", lNegativeCoefficient );
1587 check_member( condition[1], expect_condition[1], "%lu", dwPositiveSaturation );
1588 check_member( condition[1], expect_condition[1], "%lu", dwNegativeSaturation );
1589 check_member( condition[1], expect_condition[1], "%ld", lDeadBand );
1591 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
1592 ref = IDirectInputEffect_Release( effect );
1593 ok( ref == 0, "Release returned %ld\n", ref );
1594 set_hid_expect( file, NULL, 0 );
1596 desc = expect_desc;
1597 desc.cAxes = 1;
1598 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
1599 ok( hr == DIERR_INVALIDPARAM, "CreateEffect returned %#lx\n", hr );
1600 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
1601 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
1602 set_hid_expect( file, expect_create_1, sizeof(expect_create_1) );
1603 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
1604 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1605 set_hid_expect( file, NULL, 0 );
1607 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
1608 ref = IDirectInputEffect_Release( effect );
1609 ok( ref == 0, "Release returned %ld\n", ref );
1610 set_hid_expect( file, NULL, 0 );
1612 desc = expect_desc;
1613 desc.cAxes = 3;
1614 desc.rglDirection = directions;
1615 desc.rglDirection[0] = +3000;
1616 desc.rglDirection[1] = -2000;
1617 desc.rglDirection[2] = +1000;
1618 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
1619 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
1620 set_hid_expect( file, expect_create_2, sizeof(expect_create_2) );
1621 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
1622 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1623 set_hid_expect( file, NULL, 0 );
1625 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
1626 ref = IDirectInputEffect_Release( effect );
1627 ok( ref == 0, "Release returned %ld\n", ref );
1628 set_hid_expect( file, NULL, 0 );
1630 desc = expect_desc;
1631 desc.cAxes = 2;
1632 desc.rgdwAxes = axes;
1633 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR;
1634 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
1635 desc.rglDirection = directions;
1636 desc.rglDirection[0] = +3000;
1637 desc.rglDirection[1] = -2000;
1638 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
1639 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
1640 set_hid_expect( file, expect_create_3, sizeof(expect_create_3) );
1641 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
1642 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1643 set_hid_expect( file, NULL, 0 );
1645 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
1646 ref = IDirectInputEffect_Release( effect );
1647 ok( ref == 0, "Release returned %ld\n", ref );
1648 set_hid_expect( file, NULL, 0 );
1650 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, NULL, &effect, NULL );
1651 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
1652 desc = expect_desc;
1653 desc.cAxes = 0;
1654 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
1655 desc.lpvTypeSpecificParams = (void *)&expect_condition[0];
1656 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
1657 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1658 desc.cbTypeSpecificParams = 0 * sizeof(DICONDITION);
1659 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS );
1660 ok( hr == DIERR_MOREDATA, "SetParameters returned %#lx\n", hr );
1661 ok( desc.cbTypeSpecificParams == 1 * sizeof(DICONDITION), "got %lu\n", desc.cbTypeSpecificParams );
1662 desc.cbTypeSpecificParams = 0 * sizeof(DICONDITION);
1663 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
1664 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
1665 desc.cbTypeSpecificParams = 0 * sizeof(DICONDITION);
1666 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS );
1667 ok( hr == DI_OK, "SetParameters returned %#lx\n", hr );
1668 ok( desc.cbTypeSpecificParams == 0 * sizeof(DICONDITION), "got %lu\n", desc.cbTypeSpecificParams );
1669 ref = IDirectInputEffect_Release( effect );
1670 ok( ref == 0, "Release returned %ld\n", ref );
1673 static BOOL test_force_feedback_joystick( DWORD version )
1675 #include "psh_hid_macros.h"
1676 const unsigned char report_descriptor[] =
1678 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
1679 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
1680 COLLECTION(1, Application),
1681 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
1682 COLLECTION(1, Report),
1683 REPORT_ID(1, 1),
1685 USAGE(1, HID_USAGE_GENERIC_X),
1686 USAGE(1, HID_USAGE_GENERIC_Y),
1687 USAGE(1, HID_USAGE_GENERIC_Z),
1688 LOGICAL_MINIMUM(1, 0),
1689 LOGICAL_MAXIMUM(1, 0x7f),
1690 PHYSICAL_MINIMUM(1, 0),
1691 PHYSICAL_MAXIMUM(1, 0x7f),
1692 REPORT_SIZE(1, 8),
1693 REPORT_COUNT(1, 3),
1694 INPUT(1, Data|Var|Abs),
1696 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
1697 USAGE_MINIMUM(1, 1),
1698 USAGE_MAXIMUM(1, 2),
1699 LOGICAL_MINIMUM(1, 0),
1700 LOGICAL_MAXIMUM(1, 1),
1701 PHYSICAL_MINIMUM(1, 0),
1702 PHYSICAL_MAXIMUM(1, 1),
1703 REPORT_SIZE(1, 1),
1704 REPORT_COUNT(1, 2),
1705 INPUT(1, Data|Var|Abs),
1706 REPORT_COUNT(1, 6),
1707 INPUT(1, Cnst|Var|Abs),
1708 END_COLLECTION,
1710 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
1711 USAGE(1, PID_USAGE_STATE_REPORT),
1712 COLLECTION(1, Report),
1713 REPORT_ID(1, 2),
1715 USAGE(1, PID_USAGE_DEVICE_PAUSED),
1716 USAGE(1, PID_USAGE_ACTUATORS_ENABLED),
1717 USAGE(1, PID_USAGE_SAFETY_SWITCH),
1718 USAGE(1, PID_USAGE_ACTUATOR_OVERRIDE_SWITCH),
1719 USAGE(1, PID_USAGE_ACTUATOR_POWER),
1720 LOGICAL_MINIMUM(1, 0),
1721 LOGICAL_MAXIMUM(1, 1),
1722 PHYSICAL_MINIMUM(1, 0),
1723 PHYSICAL_MAXIMUM(1, 1),
1724 REPORT_SIZE(1, 1),
1725 REPORT_COUNT(1, 5),
1726 INPUT(1, Data|Var|Abs),
1727 REPORT_COUNT(1, 3),
1728 INPUT(1, Cnst|Var|Abs),
1730 USAGE(1, PID_USAGE_EFFECT_PLAYING),
1731 LOGICAL_MINIMUM(1, 0),
1732 LOGICAL_MAXIMUM(1, 1),
1733 PHYSICAL_MINIMUM(1, 0),
1734 PHYSICAL_MAXIMUM(1, 1),
1735 REPORT_SIZE(1, 1),
1736 REPORT_COUNT(1, 1),
1737 INPUT(1, Data|Var|Abs),
1739 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
1740 LOGICAL_MAXIMUM(1, 0x7f),
1741 LOGICAL_MINIMUM(1, 0x00),
1742 REPORT_SIZE(1, 7),
1743 REPORT_COUNT(1, 1),
1744 INPUT(1, Data|Var|Abs),
1745 END_COLLECTION,
1747 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
1748 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
1749 COLLECTION(1, Report),
1750 REPORT_ID(1, 1),
1752 USAGE(1, PID_USAGE_DEVICE_CONTROL),
1753 COLLECTION(1, Logical),
1754 USAGE(1, PID_USAGE_DC_DEVICE_RESET),
1755 LOGICAL_MINIMUM(1, 1),
1756 LOGICAL_MAXIMUM(1, 2),
1757 PHYSICAL_MINIMUM(1, 1),
1758 PHYSICAL_MAXIMUM(1, 2),
1759 REPORT_SIZE(1, 8),
1760 REPORT_COUNT(1, 1),
1761 OUTPUT(1, Data|Ary|Abs),
1762 END_COLLECTION,
1763 END_COLLECTION,
1765 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT),
1766 COLLECTION(1, Report),
1767 REPORT_ID(1, 2),
1769 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
1770 LOGICAL_MINIMUM(1, 0),
1771 LOGICAL_MAXIMUM(1, 0x7f),
1772 PHYSICAL_MINIMUM(1, 0),
1773 PHYSICAL_MAXIMUM(1, 0x7f),
1774 REPORT_SIZE(1, 8),
1775 REPORT_COUNT(1, 1),
1776 OUTPUT(1, Data|Var|Abs),
1778 USAGE(1, PID_USAGE_EFFECT_OPERATION),
1779 COLLECTION(1, NamedArray),
1780 USAGE(1, PID_USAGE_OP_EFFECT_START),
1781 USAGE(1, PID_USAGE_OP_EFFECT_START_SOLO),
1782 USAGE(1, PID_USAGE_OP_EFFECT_STOP),
1783 LOGICAL_MINIMUM(1, 1),
1784 LOGICAL_MAXIMUM(1, 3),
1785 PHYSICAL_MINIMUM(1, 1),
1786 PHYSICAL_MAXIMUM(1, 3),
1787 REPORT_SIZE(1, 8),
1788 REPORT_COUNT(1, 1),
1789 OUTPUT(1, Data|Ary|Abs),
1790 END_COLLECTION,
1792 USAGE(1, PID_USAGE_LOOP_COUNT),
1793 LOGICAL_MINIMUM(1, 0),
1794 LOGICAL_MAXIMUM(1, 0x7f),
1795 PHYSICAL_MINIMUM(1, 0),
1796 PHYSICAL_MAXIMUM(1, 0x7f),
1797 REPORT_SIZE(1, 8),
1798 REPORT_COUNT(1, 1),
1799 OUTPUT(1, Data|Var|Abs),
1800 END_COLLECTION,
1802 USAGE(1, PID_USAGE_SET_EFFECT_REPORT),
1803 COLLECTION(1, Report),
1804 REPORT_ID(1, 3),
1806 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
1807 LOGICAL_MINIMUM(1, 0),
1808 LOGICAL_MAXIMUM(1, 0x7f),
1809 PHYSICAL_MINIMUM(1, 0),
1810 PHYSICAL_MAXIMUM(1, 0x7f),
1811 REPORT_SIZE(1, 8),
1812 REPORT_COUNT(1, 1),
1813 OUTPUT(1, Data|Var|Abs),
1815 USAGE(1, PID_USAGE_EFFECT_TYPE),
1816 COLLECTION(1, NamedArray),
1817 USAGE(1, PID_USAGE_ET_SQUARE),
1818 USAGE(1, PID_USAGE_ET_SINE),
1819 USAGE(1, PID_USAGE_ET_SPRING),
1820 LOGICAL_MINIMUM(1, 1),
1821 LOGICAL_MAXIMUM(1, 3),
1822 PHYSICAL_MINIMUM(1, 1),
1823 PHYSICAL_MAXIMUM(1, 3),
1824 REPORT_SIZE(1, 8),
1825 REPORT_COUNT(1, 1),
1826 OUTPUT(1, Data|Ary|Abs),
1827 END_COLLECTION,
1829 USAGE(1, PID_USAGE_AXES_ENABLE),
1830 COLLECTION(1, Logical),
1831 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_X),
1832 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Y),
1833 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Z),
1834 LOGICAL_MINIMUM(1, 0),
1835 LOGICAL_MAXIMUM(1, 1),
1836 PHYSICAL_MINIMUM(1, 0),
1837 PHYSICAL_MAXIMUM(1, 1),
1838 REPORT_SIZE(1, 1),
1839 REPORT_COUNT(1, 3),
1840 OUTPUT(1, Data|Var|Abs),
1841 END_COLLECTION,
1842 USAGE(1, PID_USAGE_DIRECTION_ENABLE),
1843 REPORT_COUNT(1, 1),
1844 OUTPUT(1, Data|Var|Abs),
1845 REPORT_COUNT(1, 4),
1846 OUTPUT(1, Cnst|Var|Abs),
1848 USAGE(1, PID_USAGE_DURATION),
1849 USAGE(1, PID_USAGE_START_DELAY),
1850 UNIT(2, 0x1003), /* Eng Lin:Time */
1851 UNIT_EXPONENT(1, -3), /* 10^-3 */
1852 LOGICAL_MINIMUM(1, 0),
1853 LOGICAL_MAXIMUM(2, 0x7fff),
1854 PHYSICAL_MINIMUM(1, 0),
1855 PHYSICAL_MAXIMUM(2, 0x7fff),
1856 REPORT_SIZE(1, 16),
1857 REPORT_COUNT(1, 2),
1858 OUTPUT(1, Data|Var|Abs),
1859 UNIT(1, 0),
1860 UNIT_EXPONENT(1, 0),
1862 USAGE(1, PID_USAGE_TRIGGER_BUTTON),
1863 LOGICAL_MINIMUM(1, 1),
1864 LOGICAL_MAXIMUM(1, 0x08),
1865 PHYSICAL_MINIMUM(1, 1),
1866 PHYSICAL_MAXIMUM(1, 0x08),
1867 REPORT_SIZE(1, 8),
1868 REPORT_COUNT(1, 1),
1869 OUTPUT(1, Data|Var|Abs),
1871 USAGE(1, PID_USAGE_DIRECTION),
1872 COLLECTION(1, Logical),
1873 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
1874 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
1875 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
1876 UNIT_EXPONENT(1, -2), /* 10^-2 */
1877 LOGICAL_MINIMUM(1, 0),
1878 LOGICAL_MAXIMUM(2, 0x00ff),
1879 PHYSICAL_MINIMUM(1, 0),
1880 PHYSICAL_MAXIMUM(4, 0x00008ca0),
1881 UNIT(1, 0),
1882 REPORT_SIZE(1, 8),
1883 REPORT_COUNT(1, 2),
1884 OUTPUT(1, Data|Var|Abs),
1885 UNIT_EXPONENT(1, 0),
1886 UNIT(1, 0),
1887 END_COLLECTION,
1888 END_COLLECTION,
1890 USAGE(1, PID_USAGE_SET_PERIODIC_REPORT),
1891 COLLECTION(1, Logical),
1892 REPORT_ID(1, 5),
1894 USAGE(1, PID_USAGE_MAGNITUDE),
1895 LOGICAL_MINIMUM(1, 0),
1896 LOGICAL_MAXIMUM(2, 0x00ff),
1897 PHYSICAL_MINIMUM(1, 0),
1898 PHYSICAL_MAXIMUM(2, 0x2710),
1899 REPORT_SIZE(1, 8),
1900 REPORT_COUNT(1, 1),
1901 OUTPUT(1, Data|Var|Abs),
1902 END_COLLECTION,
1904 USAGE(1, PID_USAGE_SET_ENVELOPE_REPORT),
1905 COLLECTION(1, Logical),
1906 REPORT_ID(1, 6),
1908 USAGE(1, PID_USAGE_ATTACK_LEVEL),
1909 USAGE(1, PID_USAGE_FADE_LEVEL),
1910 LOGICAL_MINIMUM(1, 0),
1911 LOGICAL_MAXIMUM(2, 0x00ff),
1912 PHYSICAL_MINIMUM(1, 0),
1913 PHYSICAL_MAXIMUM(2, 0x2710),
1914 REPORT_SIZE(1, 8),
1915 REPORT_COUNT(1, 2),
1916 OUTPUT(1, Data|Var|Abs),
1918 USAGE(1, PID_USAGE_ATTACK_TIME),
1919 USAGE(1, PID_USAGE_FADE_TIME),
1920 UNIT(2, 0x1003), /* Eng Lin:Time */
1921 UNIT_EXPONENT(1, -3), /* 10^-3 */
1922 LOGICAL_MINIMUM(1, 0),
1923 LOGICAL_MAXIMUM(2, 0x7fff),
1924 PHYSICAL_MINIMUM(1, 0),
1925 PHYSICAL_MAXIMUM(2, 0x7fff),
1926 REPORT_SIZE(1, 16),
1927 REPORT_COUNT(1, 2),
1928 OUTPUT(1, Data|Var|Abs),
1929 PHYSICAL_MAXIMUM(1, 0),
1930 UNIT_EXPONENT(1, 0),
1931 UNIT(1, 0),
1932 END_COLLECTION,
1935 USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
1936 COLLECTION(1, Logical),
1937 REPORT_ID(1, 7),
1939 USAGE(1, PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET),
1940 COLLECTION(1, Logical),
1941 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
1942 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
1943 LOGICAL_MINIMUM(1, 0),
1944 LOGICAL_MAXIMUM(1, 1),
1945 PHYSICAL_MINIMUM(1, 0),
1946 PHYSICAL_MAXIMUM(1, 1),
1947 REPORT_SIZE(1, 2),
1948 REPORT_COUNT(1, 2),
1949 OUTPUT(1, Data|Var|Abs),
1950 END_COLLECTION,
1951 REPORT_SIZE(1, 4),
1952 REPORT_COUNT(1, 1),
1953 OUTPUT(1, Cnst|Var|Abs),
1955 USAGE(1, PID_USAGE_CP_OFFSET),
1956 LOGICAL_MINIMUM(1, 0x80),
1957 LOGICAL_MAXIMUM(1, 0x7f),
1958 PHYSICAL_MINIMUM(2, 0xd8f0),
1959 PHYSICAL_MAXIMUM(2, 0x2710),
1960 REPORT_SIZE(1, 8),
1961 REPORT_COUNT(1, 1),
1962 OUTPUT(1, Data|Var|Abs),
1964 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
1965 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
1966 LOGICAL_MINIMUM(1, 0x80),
1967 LOGICAL_MAXIMUM(1, 0x7f),
1968 PHYSICAL_MINIMUM(2, 0xd8f0),
1969 PHYSICAL_MAXIMUM(2, 0x2710),
1970 REPORT_SIZE(1, 8),
1971 REPORT_COUNT(1, 2),
1972 OUTPUT(1, Data|Var|Abs),
1974 USAGE(1, PID_USAGE_POSITIVE_SATURATION),
1975 USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
1976 LOGICAL_MINIMUM(1, 0),
1977 LOGICAL_MAXIMUM(2, 0x00ff),
1978 PHYSICAL_MINIMUM(1, 0),
1979 PHYSICAL_MAXIMUM(2, 0x2710),
1980 REPORT_SIZE(1, 8),
1981 REPORT_COUNT(1, 2),
1982 OUTPUT(1, Data|Var|Abs),
1984 USAGE(1, PID_USAGE_DEAD_BAND),
1985 LOGICAL_MINIMUM(1, 0),
1986 LOGICAL_MAXIMUM(2, 0x00ff),
1987 PHYSICAL_MINIMUM(1, 0),
1988 PHYSICAL_MAXIMUM(2, 0x2710),
1989 REPORT_SIZE(1, 8),
1990 REPORT_COUNT(1, 1),
1991 OUTPUT(1, Data|Var|Abs),
1992 END_COLLECTION,
1995 USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT),
1996 COLLECTION(1, Logical),
1997 REPORT_ID(1, 8),
1999 USAGE(1, PID_USAGE_DEVICE_GAIN),
2000 LOGICAL_MINIMUM(1, 0),
2001 LOGICAL_MAXIMUM(2, 0x00ff),
2002 PHYSICAL_MINIMUM(1, 0),
2003 PHYSICAL_MAXIMUM(2, 0x2710),
2004 REPORT_SIZE(1, 8),
2005 REPORT_COUNT(1, 1),
2006 OUTPUT(1, Data|Var|Abs),
2007 END_COLLECTION,
2008 END_COLLECTION,
2010 C_ASSERT(sizeof(report_descriptor) < MAX_HID_DESCRIPTOR_LEN);
2011 #include "pop_hid_macros.h"
2013 struct hid_device_desc desc =
2015 .use_report_id = TRUE,
2016 .caps =
2018 .InputReportByteLength = 5,
2019 .OutputReportByteLength = 11,
2021 .attributes = default_attributes,
2023 const DIDEVCAPS expect_caps =
2025 .dwSize = sizeof(DIDEVCAPS),
2026 .dwFlags = DIDC_FORCEFEEDBACK | DIDC_ATTACHED | DIDC_EMULATED | DIDC_STARTDELAY |
2027 DIDC_FFFADE | DIDC_FFATTACK | DIDC_DEADBAND | DIDC_SATURATION,
2028 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
2029 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK,
2030 .dwAxes = 3,
2031 .dwButtons = 2,
2032 .dwFFSamplePeriod = 1000000,
2033 .dwFFMinTimeResolution = 1000000,
2034 .dwHardwareRevision = 1,
2035 .dwFFDriverVersion = 1,
2037 struct hid_expect expect_acquire[] =
2040 .code = IOCTL_HID_WRITE_REPORT,
2041 .report_id = 1,
2042 .report_len = 2,
2043 .report_buf = {1, 0x01},
2046 .code = IOCTL_HID_WRITE_REPORT,
2047 .report_id = 8,
2048 .report_len = 2,
2049 .report_buf = {8, 0x19},
2052 struct hid_expect expect_reset[] =
2055 .code = IOCTL_HID_WRITE_REPORT,
2056 .report_id = 1,
2057 .report_len = 2,
2058 .report_buf = {1, 0x01},
2061 struct hid_expect expect_set_device_gain_1 =
2063 .code = IOCTL_HID_WRITE_REPORT,
2064 .report_id = 8,
2065 .report_len = 2,
2066 .report_buf = {8, 0x19},
2068 struct hid_expect expect_set_device_gain_2 =
2070 .code = IOCTL_HID_WRITE_REPORT,
2071 .report_id = 8,
2072 .report_len = 2,
2073 .report_buf = {8, 0x33},
2076 const DIDEVICEINSTANCEW expect_devinst =
2078 .dwSize = sizeof(DIDEVICEINSTANCEW),
2079 .guidInstance = expect_guid_product,
2080 .guidProduct = expect_guid_product,
2081 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
2082 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK,
2083 .tszInstanceName = L"Wine Test",
2084 .tszProductName = L"Wine Test",
2085 .guidFFDriver = IID_IDirectInputPIDDriver,
2086 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2087 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
2089 const DIDEVICEOBJECTINSTANCEW expect_objects_5[] =
2092 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2093 .guidType = GUID_XAxis,
2094 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0)|DIDFT_FFACTUATOR,
2095 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2096 .tszName = L"X Axis",
2097 .wCollectionNumber = 1,
2098 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2099 .wUsage = HID_USAGE_GENERIC_X,
2100 .wReportId = 1,
2103 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2104 .guidType = GUID_YAxis,
2105 .dwOfs = 0x4,
2106 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1)|DIDFT_FFACTUATOR,
2107 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2108 .tszName = L"Y Axis",
2109 .wCollectionNumber = 1,
2110 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2111 .wUsage = HID_USAGE_GENERIC_Y,
2112 .wReportId = 1,
2115 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2116 .guidType = GUID_ZAxis,
2117 .dwOfs = 0x8,
2118 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2)|DIDFT_FFACTUATOR,
2119 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2120 .tszName = L"Z Axis",
2121 .wCollectionNumber = 1,
2122 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2123 .wUsage = HID_USAGE_GENERIC_Z,
2124 .wReportId = 1,
2127 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2128 .guidType = GUID_Button,
2129 .dwOfs = 0x30,
2130 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER,
2131 .dwFlags = DIDOI_FFEFFECTTRIGGER,
2132 .tszName = L"Button 0",
2133 .wCollectionNumber = 1,
2134 .wUsagePage = HID_USAGE_PAGE_BUTTON,
2135 .wUsage = 0x1,
2136 .wReportId = 1,
2139 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2140 .guidType = GUID_Button,
2141 .dwOfs = 0x31,
2142 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER,
2143 .dwFlags = DIDOI_FFEFFECTTRIGGER,
2144 .tszName = L"Button 1",
2145 .wCollectionNumber = 1,
2146 .wUsagePage = HID_USAGE_PAGE_BUTTON,
2147 .wUsage = 0x2,
2148 .wReportId = 1,
2151 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
2154 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2155 .guidType = GUID_ZAxis,
2156 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2)|DIDFT_FFACTUATOR,
2157 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2158 .tszName = L"Z Axis",
2159 .wCollectionNumber = 1,
2160 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2161 .wUsage = HID_USAGE_GENERIC_Z,
2162 .wReportId = 1,
2165 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2166 .guidType = GUID_YAxis,
2167 .dwOfs = 0x4,
2168 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1)|DIDFT_FFACTUATOR,
2169 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2170 .tszName = L"Y Axis",
2171 .wCollectionNumber = 1,
2172 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2173 .wUsage = HID_USAGE_GENERIC_Y,
2174 .wReportId = 1,
2177 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2178 .guidType = GUID_XAxis,
2179 .dwOfs = 0x8,
2180 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0)|DIDFT_FFACTUATOR,
2181 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
2182 .tszName = L"X Axis",
2183 .wCollectionNumber = 1,
2184 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2185 .wUsage = HID_USAGE_GENERIC_X,
2186 .wReportId = 1,
2189 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2190 .guidType = GUID_Button,
2191 .dwOfs = version >= 0x800 ? 0x68 : 0x10,
2192 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER,
2193 .dwFlags = DIDOI_FFEFFECTTRIGGER,
2194 .tszName = L"Button 0",
2195 .wCollectionNumber = 1,
2196 .wUsagePage = HID_USAGE_PAGE_BUTTON,
2197 .wUsage = 0x1,
2198 .wReportId = 1,
2201 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2202 .guidType = GUID_Button,
2203 .dwOfs = version >= 0x800 ? 0x69 : 0x11,
2204 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER,
2205 .dwFlags = DIDOI_FFEFFECTTRIGGER,
2206 .tszName = L"Button 1",
2207 .wCollectionNumber = 1,
2208 .wUsagePage = HID_USAGE_PAGE_BUTTON,
2209 .wUsage = 0x2,
2210 .wReportId = 1,
2213 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2214 .guidType = GUID_Unknown,
2215 .dwOfs = version >= 0x800 ? 0x70 : 0,
2216 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(12)|DIDFT_OUTPUT,
2217 .dwFlags = 0x80008000,
2218 .tszName = L"DC Device Reset",
2219 .wCollectionNumber = 4,
2220 .wUsagePage = HID_USAGE_PAGE_PID,
2221 .wUsage = PID_USAGE_DC_DEVICE_RESET,
2222 .wReportId = 1,
2225 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2226 .guidType = GUID_Unknown,
2227 .dwOfs = version >= 0x800 ? 0x10 : 0,
2228 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(13)|DIDFT_OUTPUT,
2229 .dwFlags = 0x80008000,
2230 .tszName = L"Effect Block Index",
2231 .wCollectionNumber = 5,
2232 .wUsagePage = HID_USAGE_PAGE_PID,
2233 .wUsage = PID_USAGE_EFFECT_BLOCK_INDEX,
2234 .wReportId = 2,
2237 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2238 .guidType = GUID_Unknown,
2239 .dwOfs = version >= 0x800 ? 0x71 : 0,
2240 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(14)|DIDFT_OUTPUT,
2241 .dwFlags = 0x80008000,
2242 .tszName = L"Op Effect Start",
2243 .wCollectionNumber = 6,
2244 .wUsagePage = HID_USAGE_PAGE_PID,
2245 .wUsage = PID_USAGE_OP_EFFECT_START,
2246 .wReportId = 2,
2249 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2250 .guidType = GUID_Unknown,
2251 .dwOfs = version >= 0x800 ? 0x72 : 0,
2252 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(15)|DIDFT_OUTPUT,
2253 .dwFlags = 0x80008000,
2254 .tszName = L"Op Effect Start Solo",
2255 .wCollectionNumber = 6,
2256 .wUsagePage = HID_USAGE_PAGE_PID,
2257 .wUsage = PID_USAGE_OP_EFFECT_START_SOLO,
2258 .wReportId = 2,
2261 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2262 .guidType = GUID_Unknown,
2263 .dwOfs = version >= 0x800 ? 0x73 : 0,
2264 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(16)|DIDFT_OUTPUT,
2265 .dwFlags = 0x80008000,
2266 .tszName = L"Op Effect Stop",
2267 .wCollectionNumber = 6,
2268 .wUsagePage = HID_USAGE_PAGE_PID,
2269 .wUsage = PID_USAGE_OP_EFFECT_STOP,
2270 .wReportId = 2,
2273 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2274 .guidType = GUID_Unknown,
2275 .dwOfs = version >= 0x800 ? 0x14 : 0,
2276 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(17)|DIDFT_OUTPUT,
2277 .dwFlags = 0x80008000,
2278 .tszName = L"Loop Count",
2279 .wCollectionNumber = 5,
2280 .wUsagePage = HID_USAGE_PAGE_PID,
2281 .wUsage = PID_USAGE_LOOP_COUNT,
2282 .wReportId = 2,
2285 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2286 .guidType = GUID_Unknown,
2287 .dwOfs = version >= 0x800 ? 0x18 : 0,
2288 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(18)|DIDFT_OUTPUT,
2289 .dwFlags = 0x80008000,
2290 .tszName = L"Effect Block Index",
2291 .wCollectionNumber = 7,
2292 .wUsagePage = HID_USAGE_PAGE_PID,
2293 .wUsage = PID_USAGE_EFFECT_BLOCK_INDEX,
2294 .wReportId = 3,
2297 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2298 .guidType = GUID_Unknown,
2299 .dwOfs = version >= 0x800 ? 0x74 : 0,
2300 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(19)|DIDFT_OUTPUT,
2301 .dwFlags = 0x80008000,
2302 .tszName = L"ET Square",
2303 .wCollectionNumber = 8,
2304 .wUsagePage = HID_USAGE_PAGE_PID,
2305 .wUsage = PID_USAGE_ET_SQUARE,
2306 .wReportId = 3,
2309 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2310 .guidType = GUID_Unknown,
2311 .dwOfs = version >= 0x800 ? 0x75 : 0,
2312 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(20)|DIDFT_OUTPUT,
2313 .dwFlags = 0x80008000,
2314 .tszName = L"ET Sine",
2315 .wCollectionNumber = 8,
2316 .wUsagePage = HID_USAGE_PAGE_PID,
2317 .wUsage = PID_USAGE_ET_SINE,
2318 .wReportId = 3,
2321 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2322 .guidType = GUID_Unknown,
2323 .dwOfs = version >= 0x800 ? 0x76 : 0,
2324 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(21)|DIDFT_OUTPUT,
2325 .dwFlags = 0x80008000,
2326 .tszName = L"ET Spring",
2327 .wCollectionNumber = 8,
2328 .wUsagePage = HID_USAGE_PAGE_PID,
2329 .wUsage = PID_USAGE_ET_SPRING,
2330 .wReportId = 3,
2333 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2334 .guidType = GUID_Unknown,
2335 .dwOfs = version >= 0x800 ? 0x77 : 0,
2336 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(22)|DIDFT_OUTPUT,
2337 .dwFlags = 0x80008000,
2338 .tszName = L"Z Axis",
2339 .wCollectionNumber = 9,
2340 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2341 .wUsage = HID_USAGE_GENERIC_Z,
2342 .wReportId = 3,
2345 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2346 .guidType = GUID_Unknown,
2347 .dwOfs = version >= 0x800 ? 0x78 : 0,
2348 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(23)|DIDFT_OUTPUT,
2349 .dwFlags = 0x80008000,
2350 .tszName = L"Y Axis",
2351 .wCollectionNumber = 9,
2352 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2353 .wUsage = HID_USAGE_GENERIC_Y,
2354 .wReportId = 3,
2357 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2358 .guidType = GUID_Unknown,
2359 .dwOfs = version >= 0x800 ? 0x79 : 0,
2360 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(24)|DIDFT_OUTPUT,
2361 .dwFlags = 0x80008000,
2362 .tszName = L"X Axis",
2363 .wCollectionNumber = 9,
2364 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2365 .wUsage = HID_USAGE_GENERIC_X,
2366 .wReportId = 3,
2369 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2370 .guidType = GUID_Unknown,
2371 .dwOfs = version >= 0x800 ? 0x7a : 0,
2372 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(25)|DIDFT_OUTPUT,
2373 .dwFlags = 0x80008000,
2374 .tszName = L"Direction Enable",
2375 .wCollectionNumber = 7,
2376 .wUsagePage = HID_USAGE_PAGE_PID,
2377 .wUsage = PID_USAGE_DIRECTION_ENABLE,
2378 .wReportId = 3,
2381 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2382 .guidType = GUID_Unknown,
2383 .dwOfs = version >= 0x800 ? 0x1c : 0,
2384 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(26)|DIDFT_OUTPUT,
2385 .dwFlags = 0x80008000,
2386 .tszName = L"Start Delay",
2387 .wCollectionNumber = 7,
2388 .wUsagePage = HID_USAGE_PAGE_PID,
2389 .wUsage = PID_USAGE_START_DELAY,
2390 .wReportId = 3,
2391 .dwDimension = 0x1003,
2392 .wExponent = -3,
2395 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2396 .guidType = GUID_Unknown,
2397 .dwOfs = version >= 0x800 ? 0x20 : 0,
2398 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(27)|DIDFT_OUTPUT,
2399 .dwFlags = 0x80008000,
2400 .tszName = L"Duration",
2401 .wCollectionNumber = 7,
2402 .wUsagePage = HID_USAGE_PAGE_PID,
2403 .wUsage = PID_USAGE_DURATION,
2404 .wReportId = 3,
2405 .dwDimension = 0x1003,
2406 .wExponent = -3,
2409 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2410 .guidType = GUID_Unknown,
2411 .dwOfs = version >= 0x800 ? 0x24 : 0,
2412 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(28)|DIDFT_OUTPUT,
2413 .dwFlags = 0x80008000,
2414 .tszName = L"Trigger Button",
2415 .wCollectionNumber = 7,
2416 .wUsagePage = HID_USAGE_PAGE_PID,
2417 .wUsage = PID_USAGE_TRIGGER_BUTTON,
2418 .wReportId = 3,
2421 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2422 .guidType = GUID_Unknown,
2423 .dwOfs = version >= 0x800 ? 0x28 : 0,
2424 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(29)|DIDFT_OUTPUT,
2425 .dwFlags = 0x80008000,
2426 .tszName = L"Unknown 29",
2427 .wCollectionNumber = 10,
2428 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
2429 .wUsage = 2,
2430 .wReportId = 3,
2431 .wExponent = -2,
2434 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2435 .guidType = GUID_Unknown,
2436 .dwOfs = version >= 0x800 ? 0x2c : 0,
2437 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(30)|DIDFT_OUTPUT,
2438 .dwFlags = 0x80008000,
2439 .tszName = L"Unknown 30",
2440 .wCollectionNumber = 10,
2441 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
2442 .wUsage = 1,
2443 .wReportId = 3,
2444 .wExponent = -2,
2447 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2448 .guidType = GUID_Unknown,
2449 .dwOfs = version >= 0x800 ? 0x30 : 0,
2450 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(31)|DIDFT_OUTPUT,
2451 .dwFlags = 0x80008000,
2452 .tszName = L"Magnitude",
2453 .wCollectionNumber = 11,
2454 .wUsagePage = HID_USAGE_PAGE_PID,
2455 .wUsage = PID_USAGE_MAGNITUDE,
2456 .wReportId = 5,
2459 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2460 .guidType = GUID_Unknown,
2461 .dwOfs = version >= 0x800 ? 0x34 : 0,
2462 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(32)|DIDFT_OUTPUT,
2463 .dwFlags = 0x80008000,
2464 .tszName = L"Fade Level",
2465 .wCollectionNumber = 12,
2466 .wUsagePage = HID_USAGE_PAGE_PID,
2467 .wUsage = PID_USAGE_FADE_LEVEL,
2468 .wReportId = 6,
2471 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2472 .guidType = GUID_Unknown,
2473 .dwOfs = version >= 0x800 ? 0x38 : 0,
2474 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(33)|DIDFT_OUTPUT,
2475 .dwFlags = 0x80008000,
2476 .tszName = L"Attack Level",
2477 .wCollectionNumber = 12,
2478 .wUsagePage = HID_USAGE_PAGE_PID,
2479 .wUsage = PID_USAGE_ATTACK_LEVEL,
2480 .wReportId = 6,
2483 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2484 .guidType = GUID_Unknown,
2485 .dwOfs = version >= 0x800 ? 0x3c : 0,
2486 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(34)|DIDFT_OUTPUT,
2487 .dwFlags = 0x80008000,
2488 .tszName = L"Fade Time",
2489 .wCollectionNumber = 12,
2490 .wUsagePage = HID_USAGE_PAGE_PID,
2491 .wUsage = PID_USAGE_FADE_TIME,
2492 .wReportId = 6,
2493 .dwDimension = 0x1003,
2494 .wExponent = -3,
2497 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2498 .guidType = GUID_Unknown,
2499 .dwOfs = version >= 0x800 ? 0x40 : 0,
2500 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(35)|DIDFT_OUTPUT,
2501 .dwFlags = 0x80008000,
2502 .tszName = L"Attack Time",
2503 .wCollectionNumber = 12,
2504 .wUsagePage = HID_USAGE_PAGE_PID,
2505 .wUsage = PID_USAGE_ATTACK_TIME,
2506 .wReportId = 6,
2507 .dwDimension = 0x1003,
2508 .wExponent = -3,
2511 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2512 .guidType = GUID_Unknown,
2513 .dwOfs = version >= 0x800 ? 0x44 : 0,
2514 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(36)|DIDFT_OUTPUT,
2515 .dwFlags = 0x80008000,
2516 .tszName = L"Unknown 36",
2517 .wCollectionNumber = 14,
2518 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
2519 .wUsage = 2,
2520 .wReportId = 7,
2523 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2524 .guidType = GUID_Unknown,
2525 .dwOfs = version >= 0x800 ? 0x48 : 0,
2526 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(37)|DIDFT_OUTPUT,
2527 .dwFlags = 0x80008000,
2528 .tszName = L"Unknown 37",
2529 .wCollectionNumber = 14,
2530 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
2531 .wUsage = 1,
2532 .wReportId = 7,
2535 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2536 .guidType = GUID_Unknown,
2537 .dwOfs = version >= 0x800 ? 0x4c : 0,
2538 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(38)|DIDFT_OUTPUT,
2539 .dwFlags = 0x80008000,
2540 .tszName = L"CP Offset",
2541 .wCollectionNumber = 13,
2542 .wUsagePage = HID_USAGE_PAGE_PID,
2543 .wUsage = PID_USAGE_CP_OFFSET,
2544 .wReportId = 7,
2547 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2548 .guidType = GUID_Unknown,
2549 .dwOfs = version >= 0x800 ? 0x50 : 0,
2550 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(39)|DIDFT_OUTPUT,
2551 .dwFlags = 0x80008000,
2552 .tszName = L"Negative Coefficient",
2553 .wCollectionNumber = 13,
2554 .wUsagePage = HID_USAGE_PAGE_PID,
2555 .wUsage = PID_USAGE_NEGATIVE_COEFFICIENT,
2556 .wReportId = 7,
2559 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2560 .guidType = GUID_Unknown,
2561 .dwOfs = version >= 0x800 ? 0x54 : 0,
2562 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(40)|DIDFT_OUTPUT,
2563 .dwFlags = 0x80008000,
2564 .tszName = L"Positive Coefficient",
2565 .wCollectionNumber = 13,
2566 .wUsagePage = HID_USAGE_PAGE_PID,
2567 .wUsage = PID_USAGE_POSITIVE_COEFFICIENT,
2568 .wReportId = 7,
2571 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2572 .guidType = GUID_Unknown,
2573 .dwOfs = version >= 0x800 ? 0x58 : 0,
2574 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(41)|DIDFT_OUTPUT,
2575 .dwFlags = 0x80008000,
2576 .tszName = L"Negative Saturation",
2577 .wCollectionNumber = 13,
2578 .wUsagePage = HID_USAGE_PAGE_PID,
2579 .wUsage = PID_USAGE_NEGATIVE_SATURATION,
2580 .wReportId = 7,
2583 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2584 .guidType = GUID_Unknown,
2585 .dwOfs = version >= 0x800 ? 0x5c : 0,
2586 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(42)|DIDFT_OUTPUT,
2587 .dwFlags = 0x80008000,
2588 .tszName = L"Positive Saturation",
2589 .wCollectionNumber = 13,
2590 .wUsagePage = HID_USAGE_PAGE_PID,
2591 .wUsage = PID_USAGE_POSITIVE_SATURATION,
2592 .wReportId = 7,
2595 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2596 .guidType = GUID_Unknown,
2597 .dwOfs = version >= 0x800 ? 0x60 : 0,
2598 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(43)|DIDFT_OUTPUT,
2599 .dwFlags = 0x80008000,
2600 .tszName = L"Dead Band",
2601 .wCollectionNumber = 13,
2602 .wUsagePage = HID_USAGE_PAGE_PID,
2603 .wUsage = PID_USAGE_DEAD_BAND,
2604 .wReportId = 7,
2607 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2608 .guidType = GUID_Unknown,
2609 .dwOfs = version >= 0x800 ? 0x64 : 0,
2610 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(44)|DIDFT_OUTPUT,
2611 .dwFlags = 0x80008000,
2612 .tszName = L"Device Gain",
2613 .wCollectionNumber = 15,
2614 .wUsagePage = HID_USAGE_PAGE_PID,
2615 .wUsage = PID_USAGE_DEVICE_GAIN,
2616 .wReportId = 8,
2619 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2620 .guidType = GUID_Unknown,
2621 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
2622 .tszName = L"Collection 0 - Joystick",
2623 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2624 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
2627 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2628 .guidType = GUID_Unknown,
2629 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
2630 .tszName = L"Collection 1 - Joystick",
2631 .wUsagePage = HID_USAGE_PAGE_GENERIC,
2632 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
2635 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2636 .guidType = GUID_Unknown,
2637 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(2),
2638 .tszName = L"Collection 2 - PID State Report",
2639 .wUsagePage = HID_USAGE_PAGE_PID,
2640 .wUsage = PID_USAGE_STATE_REPORT,
2643 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2644 .guidType = GUID_Unknown,
2645 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(3),
2646 .tszName = L"Collection 3 - PID Device Control Report",
2647 .wUsagePage = HID_USAGE_PAGE_PID,
2648 .wUsage = PID_USAGE_DEVICE_CONTROL_REPORT,
2651 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2652 .guidType = GUID_Unknown,
2653 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(4),
2654 .tszName = L"Collection 4 - PID Device Control",
2655 .wCollectionNumber = 3,
2656 .wUsagePage = HID_USAGE_PAGE_PID,
2657 .wUsage = PID_USAGE_DEVICE_CONTROL,
2660 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2661 .guidType = GUID_Unknown,
2662 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(5),
2663 .tszName = L"Collection 5 - Effect Operation Report",
2664 .wUsagePage = HID_USAGE_PAGE_PID,
2665 .wUsage = PID_USAGE_EFFECT_OPERATION_REPORT,
2668 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2669 .guidType = GUID_Unknown,
2670 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(6),
2671 .tszName = L"Collection 6 - Effect Operation",
2672 .wCollectionNumber = 5,
2673 .wUsagePage = HID_USAGE_PAGE_PID,
2674 .wUsage = PID_USAGE_EFFECT_OPERATION,
2677 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2678 .guidType = GUID_Unknown,
2679 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(7),
2680 .tszName = L"Collection 7 - Set Effect Report",
2681 .wUsagePage = HID_USAGE_PAGE_PID,
2682 .wUsage = PID_USAGE_SET_EFFECT_REPORT,
2685 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2686 .guidType = GUID_Unknown,
2687 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(8),
2688 .tszName = L"Collection 8 - Effect Type",
2689 .wCollectionNumber = 7,
2690 .wUsagePage = HID_USAGE_PAGE_PID,
2691 .wUsage = PID_USAGE_EFFECT_TYPE,
2694 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2695 .guidType = GUID_Unknown,
2696 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(9),
2697 .tszName = L"Collection 9 - Axes Enable",
2698 .wCollectionNumber = 7,
2699 .wUsagePage = HID_USAGE_PAGE_PID,
2700 .wUsage = PID_USAGE_AXES_ENABLE,
2703 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2704 .guidType = GUID_Unknown,
2705 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(10),
2706 .tszName = L"Collection 10 - Direction",
2707 .wCollectionNumber = 7,
2708 .wUsagePage = HID_USAGE_PAGE_PID,
2709 .wUsage = PID_USAGE_DIRECTION,
2712 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2713 .guidType = GUID_Unknown,
2714 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(11),
2715 .tszName = L"Collection 11 - Set Periodic Report",
2716 .wUsagePage = HID_USAGE_PAGE_PID,
2717 .wUsage = PID_USAGE_SET_PERIODIC_REPORT,
2720 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2721 .guidType = GUID_Unknown,
2722 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(12),
2723 .tszName = L"Collection 12 - Set Envelope Report",
2724 .wUsagePage = HID_USAGE_PAGE_PID,
2725 .wUsage = PID_USAGE_SET_ENVELOPE_REPORT,
2728 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2729 .guidType = GUID_Unknown,
2730 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(13),
2731 .tszName = L"Collection 13 - Set Condition Report",
2732 .wUsagePage = HID_USAGE_PAGE_PID,
2733 .wUsage = PID_USAGE_SET_CONDITION_REPORT,
2736 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2737 .guidType = GUID_Unknown,
2738 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(14),
2739 .tszName = L"Collection 14 - Type Specific Block Offset",
2740 .wCollectionNumber = 13,
2741 .wUsagePage = HID_USAGE_PAGE_PID,
2742 .wUsage = PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET,
2745 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
2746 .guidType = GUID_Unknown,
2747 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(15),
2748 .tszName = L"Collection 15 - Device Gain Report",
2749 .wUsagePage = HID_USAGE_PAGE_PID,
2750 .wUsage = PID_USAGE_DEVICE_GAIN_REPORT,
2753 const DIEFFECTINFOW expect_effects[] =
2756 .dwSize = sizeof(DIEFFECTINFOW),
2757 .guid = GUID_Square,
2758 .dwEffType = DIEFT_PERIODIC | DIEFT_STARTDELAY | DIEFT_FFFADE | DIEFT_FFATTACK,
2759 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2760 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
2761 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2762 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
2763 .tszName = L"GUID_Square",
2766 .dwSize = sizeof(DIEFFECTINFOW),
2767 .guid = GUID_Sine,
2768 .dwEffType = DIEFT_PERIODIC | DIEFT_STARTDELAY | DIEFT_FFFADE | DIEFT_FFATTACK,
2769 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2770 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
2771 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2772 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
2773 .tszName = L"GUID_Sine",
2776 .dwSize = sizeof(DIEFFECTINFOW),
2777 .guid = GUID_Spring,
2778 .dwEffType = DIEFT_CONDITION | DIEFT_STARTDELAY | DIEFT_DEADBAND | DIEFT_SATURATION,
2779 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2780 DIEP_DURATION,
2781 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
2782 DIEP_DURATION,
2783 .tszName = L"GUID_Spring",
2787 struct check_objects_todos todo_objects_5[ARRAY_SIZE(expect_objects_5)] =
2789 {.guid = TRUE, .type = TRUE, .usage = TRUE, .name = TRUE},
2790 {0},
2791 {.guid = TRUE, .type = TRUE, .usage = TRUE, .name = TRUE},
2793 struct check_objects_params check_objects_params =
2795 .version = version,
2796 .expect_count = version < 0x700 ? ARRAY_SIZE(expect_objects_5) : ARRAY_SIZE(expect_objects),
2797 .expect_objs = version < 0x700 ? expect_objects_5 : expect_objects,
2798 .todo_objs = version < 0x700 ? todo_objects_5 : NULL,
2799 .todo_extra = version < 0x700 ? TRUE : FALSE,
2801 struct check_effects_params check_effects_params =
2803 .expect_count = ARRAY_SIZE(expect_effects),
2804 .expect_effects = expect_effects,
2806 DIPROPDWORD prop_dword =
2808 .diph =
2810 .dwSize = sizeof(DIPROPDWORD),
2811 .dwHeaderSize = sizeof(DIPROPHEADER),
2812 .dwHow = DIPH_DEVICE,
2815 DIPROPGUIDANDPATH prop_guid_path =
2817 .diph =
2819 .dwSize = sizeof(DIPROPGUIDANDPATH),
2820 .dwHeaderSize = sizeof(DIPROPHEADER),
2821 .dwHow = DIPH_DEVICE,
2824 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
2825 IDirectInputDevice8W *device = NULL;
2826 DIDEVICEOBJECTDATA objdata = {0};
2827 DIEFFECTINFOW effectinfo = {0};
2828 DIEFFESCAPE escape = {0};
2829 DIDEVCAPS caps = {0};
2830 char buffer[1024];
2831 ULONG res, ref;
2832 HANDLE file;
2833 HRESULT hr;
2834 HWND hwnd;
2836 winetest_push_context( "%#lx", version );
2837 cleanup_registry_keys();
2839 desc.report_descriptor_len = sizeof(report_descriptor);
2840 memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) );
2841 fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
2843 if (!hid_device_start( &desc )) goto done;
2844 if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done;
2846 check_dinput_devices( version, &devinst );
2848 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
2849 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
2850 check_member( devinst, expect_devinst, "%lu", dwSize );
2851 todo_wine
2852 check_member_guid( devinst, expect_devinst, guidInstance );
2853 check_member_guid( devinst, expect_devinst, guidProduct );
2854 check_member( devinst, expect_devinst, "%#lx", dwDevType );
2855 check_member_wstr( devinst, expect_devinst, tszInstanceName );
2856 check_member_wstr( devinst, expect_devinst, tszProductName );
2857 check_member_guid( devinst, expect_devinst, guidFFDriver );
2858 check_member( devinst, expect_devinst, "%04x", wUsagePage );
2859 check_member( devinst, expect_devinst, "%04x", wUsage );
2861 caps.dwSize = sizeof(DIDEVCAPS);
2862 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
2863 ok( hr == DI_OK, "GetCapabilities returned %#lx\n", hr );
2864 check_member( caps, expect_caps, "%lu", dwSize );
2865 check_member( caps, expect_caps, "%#lx", dwFlags );
2866 check_member( caps, expect_caps, "%#lx", dwDevType );
2867 check_member( caps, expect_caps, "%lu", dwAxes );
2868 check_member( caps, expect_caps, "%lu", dwButtons );
2869 check_member( caps, expect_caps, "%lu", dwPOVs );
2870 check_member( caps, expect_caps, "%lu", dwFFSamplePeriod );
2871 check_member( caps, expect_caps, "%lu", dwFFMinTimeResolution );
2872 check_member( caps, expect_caps, "%lu", dwFirmwareRevision );
2873 check_member( caps, expect_caps, "%lu", dwHardwareRevision );
2874 check_member( caps, expect_caps, "%lu", dwFFDriverVersion );
2876 prop_dword.dwData = 0xdeadbeef;
2877 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2878 ok( hr == DI_OK, "GetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2879 ok( prop_dword.dwData == 10000, "got %lu expected %u\n", prop_dword.dwData, 10000 );
2881 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2882 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
2884 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
2885 ok( hr == DI_OK, "EnumObjects returned %#lx\n", hr );
2886 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
2887 check_objects_params.expect_count - check_objects_params.index );
2889 res = 0;
2890 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, 0xfe );
2891 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2892 ok( res == 0, "got %lu expected %u\n", res, 0 );
2893 res = 0;
2894 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, DIEFT_PERIODIC );
2895 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2896 ok( res == 2, "got %lu expected %u\n", res, 2 );
2897 hr = IDirectInputDevice8_EnumEffects( device, check_effects, &check_effects_params, DIEFT_ALL );
2898 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2899 ok( check_effects_params.index >= check_effects_params.expect_count, "missing %u effects\n",
2900 check_effects_params.expect_count - check_effects_params.index );
2902 effectinfo.dwSize = sizeof(DIEFFECTINFOW);
2903 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
2904 ok( hr == DI_OK, "GetEffectInfo returned %#lx\n", hr );
2905 check_member_guid( effectinfo, expect_effects[1], guid );
2906 check_member( effectinfo, expect_effects[1], "%#lx", dwEffType );
2907 check_member( effectinfo, expect_effects[1], "%#lx", dwStaticParams );
2908 check_member( effectinfo, expect_effects[1], "%#lx", dwDynamicParams );
2909 check_member_wstr( effectinfo, expect_effects[1], tszName );
2911 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
2912 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2914 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
2915 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
2917 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2918 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
2919 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
2920 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
2922 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
2923 NULL, NULL, NULL, NULL );
2925 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
2926 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2928 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2929 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2930 prop_dword.dwData = DIPROPAUTOCENTER_ON;
2931 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2932 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2933 prop_dword.diph.dwHow = DIPH_DEVICE;
2934 prop_dword.diph.dwObj = 0;
2935 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2936 ok( hr == DI_OK, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2938 hr = IDirectInputDevice8_Acquire( device );
2939 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
2941 prop_dword.dwData = 0xdeadbeef;
2942 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2943 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2944 prop_dword.dwData = 1000;
2945 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2946 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2948 prop_dword.dwData = 0xdeadbeef;
2949 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2950 ok( hr == DIERR_READONLY, "SetProperty DIPROP_FFLOAD returned %#lx\n", hr );
2951 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2952 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
2953 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
2954 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetForceFeedbackState returned %#lx\n", hr );
2955 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
2956 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "SendForceFeedbackCommand returned %#lx\n", hr );
2958 escape.dwSize = sizeof(DIEFFESCAPE);
2959 escape.dwCommand = 0;
2960 escape.lpvInBuffer = buffer;
2961 escape.cbInBuffer = 10;
2962 escape.lpvOutBuffer = buffer + 10;
2963 escape.cbOutBuffer = 10;
2964 hr = IDirectInputDevice8_Escape( device, &escape );
2965 todo_wine
2966 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Escape returned: %#lx\n", hr );
2968 hr = IDirectInputDevice8_Unacquire( device );
2969 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2970 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
2971 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2972 prop_dword.dwData = DIPROPAUTOCENTER_ON;
2973 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2974 ok( hr == DI_OK, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2976 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
2977 hr = IDirectInputDevice8_Acquire( device );
2978 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
2979 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
2981 set_hid_expect( file, &expect_set_device_gain_2, sizeof(expect_set_device_gain_2) );
2982 prop_dword.dwData = 2000;
2983 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2984 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2985 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
2987 set_hid_expect( file, &expect_set_device_gain_1, sizeof(expect_set_device_gain_1) );
2988 prop_dword.dwData = 1000;
2989 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2990 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2991 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
2993 hr = IDirectInputDevice8_Escape( device, &escape );
2994 todo_wine
2995 ok( hr == DIERR_UNSUPPORTED, "Escape returned: %#lx\n", hr );
2997 prop_dword.dwData = 0xdeadbeef;
2998 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2999 todo_wine
3000 ok( hr == 0x80040301, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
3001 res = 0xdeadbeef;
3002 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
3003 todo_wine
3004 ok( hr == 0x80040301, "GetForceFeedbackState returned %#lx\n", hr );
3006 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
3007 ok( hr == DIERR_INVALIDPARAM, "SendForceFeedbackCommand returned %#lx\n", hr );
3009 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
3010 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
3011 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
3012 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
3014 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_STOPALL );
3015 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#lx\n", hr );
3016 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_PAUSE );
3017 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#lx\n", hr );
3018 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_CONTINUE );
3019 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#lx\n", hr );
3020 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSON );
3021 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#lx\n", hr );
3022 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSOFF );
3023 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#lx\n", hr );
3025 objdata.dwOfs = 0x1e;
3026 objdata.dwData = 0x80;
3027 res = 1;
3028 hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), &objdata, &res, 0 );
3029 if (version < 0x800) ok( hr == DI_OK, "SendDeviceData returned %#lx\n", hr );
3030 else todo_wine ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#lx\n", hr );
3032 test_periodic_effect( device, file, version );
3033 test_condition_effect( device, file, version );
3035 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
3036 hr = IDirectInputDevice8_Unacquire( device );
3037 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
3038 set_hid_expect( file, NULL, 0 );
3040 ref = IDirectInputDevice8_Release( device );
3041 ok( ref == 0, "Release returned %ld\n", ref );
3043 DestroyWindow( hwnd );
3044 CloseHandle( file );
3046 done:
3047 hid_device_stop( &desc );
3048 cleanup_registry_keys();
3049 winetest_pop_context();
3051 return device != NULL;
3054 static void test_device_managed_effect(void)
3056 #include "psh_hid_macros.h"
3057 const unsigned char report_descriptor[] = {
3058 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3059 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3060 COLLECTION(1, Application),
3061 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3062 COLLECTION(1, Report),
3063 REPORT_ID(1, 1),
3065 USAGE(1, HID_USAGE_GENERIC_X),
3066 USAGE(1, HID_USAGE_GENERIC_Y),
3067 USAGE(1, HID_USAGE_GENERIC_Z),
3068 LOGICAL_MINIMUM(1, 0),
3069 LOGICAL_MAXIMUM(1, 0x7f),
3070 PHYSICAL_MINIMUM(1, 0),
3071 PHYSICAL_MAXIMUM(1, 0x7f),
3072 REPORT_SIZE(1, 8),
3073 REPORT_COUNT(1, 3),
3074 INPUT(1, Data|Var|Abs),
3076 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3077 USAGE_MINIMUM(1, 1),
3078 USAGE_MAXIMUM(1, 2),
3079 LOGICAL_MINIMUM(1, 0),
3080 LOGICAL_MAXIMUM(1, 1),
3081 PHYSICAL_MINIMUM(1, 0),
3082 PHYSICAL_MAXIMUM(1, 1),
3083 REPORT_SIZE(1, 1),
3084 REPORT_COUNT(1, 2),
3085 INPUT(1, Data|Var|Abs),
3086 REPORT_COUNT(1, 6),
3087 INPUT(1, Cnst|Var|Abs),
3088 END_COLLECTION,
3090 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
3091 USAGE(1, PID_USAGE_STATE_REPORT),
3092 COLLECTION(1, Report),
3093 REPORT_ID(1, 2),
3095 USAGE(1, PID_USAGE_DEVICE_PAUSED),
3096 USAGE(1, PID_USAGE_ACTUATORS_ENABLED),
3097 USAGE(1, PID_USAGE_SAFETY_SWITCH),
3098 USAGE(1, PID_USAGE_ACTUATOR_OVERRIDE_SWITCH),
3099 USAGE(1, PID_USAGE_ACTUATOR_POWER),
3100 LOGICAL_MINIMUM(1, 0),
3101 LOGICAL_MAXIMUM(1, 1),
3102 PHYSICAL_MINIMUM(1, 0),
3103 PHYSICAL_MAXIMUM(1, 1),
3104 REPORT_SIZE(1, 1),
3105 REPORT_COUNT(1, 5),
3106 INPUT(1, Data|Var|Abs),
3107 REPORT_COUNT(1, 3),
3108 INPUT(1, Cnst|Var|Abs),
3110 USAGE(1, PID_USAGE_EFFECT_PLAYING),
3111 LOGICAL_MINIMUM(1, 0),
3112 LOGICAL_MAXIMUM(1, 1),
3113 PHYSICAL_MINIMUM(1, 0),
3114 PHYSICAL_MAXIMUM(1, 1),
3115 REPORT_SIZE(1, 1),
3116 REPORT_COUNT(1, 8),
3117 INPUT(1, Data|Var|Abs),
3119 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3120 LOGICAL_MINIMUM(1, 1),
3121 LOGICAL_MAXIMUM(1, 0x7f),
3122 PHYSICAL_MINIMUM(1, 1),
3123 PHYSICAL_MAXIMUM(1, 0x7f),
3124 REPORT_SIZE(1, 8),
3125 REPORT_COUNT(1, 1),
3126 INPUT(1, Data|Var|Abs),
3127 END_COLLECTION,
3129 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
3130 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
3131 COLLECTION(1, Report),
3132 REPORT_ID(1, 1),
3134 USAGE(1, PID_USAGE_DEVICE_CONTROL),
3135 COLLECTION(1, Logical),
3136 USAGE(1, PID_USAGE_DC_DEVICE_RESET),
3137 USAGE(1, PID_USAGE_DC_DEVICE_PAUSE),
3138 USAGE(1, PID_USAGE_DC_DEVICE_CONTINUE),
3139 USAGE(1, PID_USAGE_DC_ENABLE_ACTUATORS),
3140 USAGE(1, PID_USAGE_DC_DISABLE_ACTUATORS),
3141 USAGE(1, PID_USAGE_DC_STOP_ALL_EFFECTS),
3142 LOGICAL_MINIMUM(1, 1),
3143 LOGICAL_MAXIMUM(1, 6),
3144 PHYSICAL_MINIMUM(1, 1),
3145 PHYSICAL_MAXIMUM(1, 6),
3146 REPORT_SIZE(1, 8),
3147 REPORT_COUNT(1, 1),
3148 OUTPUT(1, Data|Ary|Abs),
3149 END_COLLECTION,
3150 END_COLLECTION,
3152 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT),
3153 COLLECTION(1, Report),
3154 REPORT_ID(1, 2),
3156 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3157 LOGICAL_MINIMUM(1, 1),
3158 LOGICAL_MAXIMUM(1, 0x7f),
3159 PHYSICAL_MINIMUM(1, 1),
3160 PHYSICAL_MAXIMUM(1, 0x7f),
3161 REPORT_SIZE(1, 8),
3162 REPORT_COUNT(1, 1),
3163 OUTPUT(1, Data|Var|Abs),
3165 USAGE(1, PID_USAGE_EFFECT_OPERATION),
3166 COLLECTION(1, NamedArray),
3167 USAGE(1, PID_USAGE_OP_EFFECT_START),
3168 USAGE(1, PID_USAGE_OP_EFFECT_START_SOLO),
3169 USAGE(1, PID_USAGE_OP_EFFECT_STOP),
3170 LOGICAL_MINIMUM(1, 1),
3171 LOGICAL_MAXIMUM(1, 3),
3172 PHYSICAL_MINIMUM(1, 1),
3173 PHYSICAL_MAXIMUM(1, 3),
3174 REPORT_SIZE(1, 8),
3175 REPORT_COUNT(1, 1),
3176 OUTPUT(1, Data|Ary|Abs),
3177 END_COLLECTION,
3179 USAGE(1, PID_USAGE_LOOP_COUNT),
3180 LOGICAL_MINIMUM(1, 0),
3181 LOGICAL_MAXIMUM(1, 0x7f),
3182 PHYSICAL_MINIMUM(1, 0),
3183 PHYSICAL_MAXIMUM(1, 0x7f),
3184 REPORT_SIZE(1, 8),
3185 REPORT_COUNT(1, 1),
3186 OUTPUT(1, Data|Var|Abs),
3187 END_COLLECTION,
3189 USAGE(1, PID_USAGE_SET_EFFECT_REPORT),
3190 COLLECTION(1, Report),
3191 REPORT_ID(1, 3),
3193 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3194 LOGICAL_MINIMUM(1, 1),
3195 LOGICAL_MAXIMUM(1, 0x7f),
3196 PHYSICAL_MINIMUM(1, 1),
3197 PHYSICAL_MAXIMUM(1, 0x7f),
3198 REPORT_SIZE(1, 8),
3199 REPORT_COUNT(1, 1),
3200 OUTPUT(1, Data|Var|Abs),
3202 USAGE(1, PID_USAGE_EFFECT_TYPE),
3203 COLLECTION(1, NamedArray),
3204 USAGE(1, PID_USAGE_ET_SQUARE),
3205 USAGE(1, PID_USAGE_ET_SINE),
3206 USAGE(1, PID_USAGE_ET_SPRING),
3207 LOGICAL_MINIMUM(1, 1),
3208 LOGICAL_MAXIMUM(1, 3),
3209 PHYSICAL_MINIMUM(1, 1),
3210 PHYSICAL_MAXIMUM(1, 3),
3211 REPORT_SIZE(1, 8),
3212 REPORT_COUNT(1, 1),
3213 OUTPUT(1, Data|Ary|Abs),
3214 END_COLLECTION,
3216 USAGE(1, PID_USAGE_AXES_ENABLE),
3217 COLLECTION(1, Logical),
3218 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_X),
3219 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Y),
3220 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Z),
3221 LOGICAL_MINIMUM(1, 0),
3222 LOGICAL_MAXIMUM(1, 1),
3223 PHYSICAL_MINIMUM(1, 0),
3224 PHYSICAL_MAXIMUM(1, 1),
3225 REPORT_SIZE(1, 1),
3226 REPORT_COUNT(1, 3),
3227 OUTPUT(1, Data|Var|Abs),
3228 END_COLLECTION,
3229 USAGE(1, PID_USAGE_DIRECTION_ENABLE),
3230 REPORT_COUNT(1, 1),
3231 OUTPUT(1, Data|Var|Abs),
3232 REPORT_COUNT(1, 4),
3233 OUTPUT(1, Cnst|Var|Abs),
3235 USAGE(1, PID_USAGE_DURATION),
3236 USAGE(1, PID_USAGE_START_DELAY),
3237 UNIT(2, 0x1003), /* Eng Lin:Time */
3238 UNIT_EXPONENT(1, -3), /* 10^-3 */
3239 LOGICAL_MINIMUM(1, 0),
3240 LOGICAL_MAXIMUM(2, 0x7fff),
3241 PHYSICAL_MINIMUM(1, 0),
3242 PHYSICAL_MAXIMUM(2, 0x7fff),
3243 REPORT_SIZE(1, 16),
3244 REPORT_COUNT(1, 2),
3245 OUTPUT(1, Data|Var|Abs),
3246 UNIT(1, 0),
3247 UNIT_EXPONENT(1, 0),
3249 USAGE(1, PID_USAGE_TRIGGER_BUTTON),
3250 LOGICAL_MINIMUM(1, 1),
3251 LOGICAL_MAXIMUM(1, 0x08),
3252 PHYSICAL_MINIMUM(1, 1),
3253 PHYSICAL_MAXIMUM(1, 0x08),
3254 REPORT_SIZE(1, 8),
3255 REPORT_COUNT(1, 1),
3256 OUTPUT(1, Data|Var|Abs),
3258 USAGE(1, PID_USAGE_DIRECTION),
3259 COLLECTION(1, Logical),
3260 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
3261 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
3262 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
3263 UNIT_EXPONENT(1, -2), /* 10^-2 */
3264 LOGICAL_MINIMUM(1, 0),
3265 LOGICAL_MAXIMUM(2, 0x00ff),
3266 PHYSICAL_MINIMUM(1, 0),
3267 PHYSICAL_MAXIMUM(4, 0x00008ca0),
3268 UNIT(1, 0),
3269 REPORT_SIZE(1, 8),
3270 REPORT_COUNT(1, 2),
3271 OUTPUT(1, Data|Var|Abs),
3272 UNIT_EXPONENT(1, 0),
3273 UNIT(1, 0),
3274 END_COLLECTION,
3275 END_COLLECTION,
3277 USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
3278 COLLECTION(1, Logical),
3279 REPORT_ID(1, 4),
3281 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3282 LOGICAL_MINIMUM(1, 1),
3283 LOGICAL_MAXIMUM(1, 0x7f),
3284 PHYSICAL_MINIMUM(1, 1),
3285 PHYSICAL_MAXIMUM(1, 0x7f),
3286 REPORT_SIZE(1, 8),
3287 REPORT_COUNT(1, 1),
3288 OUTPUT(1, Data|Var|Abs),
3290 USAGE(1, PID_USAGE_PARAMETER_BLOCK_OFFSET),
3291 LOGICAL_MINIMUM(1, 0),
3292 LOGICAL_MAXIMUM(1, 1),
3293 PHYSICAL_MINIMUM(1, 0),
3294 PHYSICAL_MAXIMUM(1, 1),
3295 REPORT_SIZE(1, 4),
3296 REPORT_COUNT(1, 1),
3297 OUTPUT(1, Data|Var|Abs),
3299 USAGE(1, PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET),
3300 COLLECTION(1, Logical),
3301 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
3302 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
3303 LOGICAL_MINIMUM(1, 0),
3304 LOGICAL_MAXIMUM(1, 1),
3305 PHYSICAL_MINIMUM(1, 0),
3306 PHYSICAL_MAXIMUM(1, 1),
3307 REPORT_SIZE(1, 2),
3308 REPORT_COUNT(1, 2),
3309 OUTPUT(1, Data|Var|Abs),
3310 END_COLLECTION,
3312 USAGE(1, PID_USAGE_CP_OFFSET),
3313 LOGICAL_MINIMUM(1, 0x80),
3314 LOGICAL_MAXIMUM(1, 0x7f),
3315 PHYSICAL_MINIMUM(2, 0xd8f0),
3316 PHYSICAL_MAXIMUM(2, 0x2710),
3317 REPORT_SIZE(1, 8),
3318 REPORT_COUNT(1, 1),
3319 OUTPUT(1, Data|Var|Abs),
3321 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
3322 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
3323 LOGICAL_MINIMUM(1, 0x80),
3324 LOGICAL_MAXIMUM(1, 0x7f),
3325 PHYSICAL_MINIMUM(2, 0xd8f0),
3326 PHYSICAL_MAXIMUM(2, 0x2710),
3327 REPORT_SIZE(1, 8),
3328 REPORT_COUNT(1, 2),
3329 OUTPUT(1, Data|Var|Abs),
3331 USAGE(1, PID_USAGE_POSITIVE_SATURATION),
3332 USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
3333 LOGICAL_MINIMUM(1, 0),
3334 LOGICAL_MAXIMUM(2, 0x00ff),
3335 PHYSICAL_MINIMUM(1, 0),
3336 PHYSICAL_MAXIMUM(2, 0x2710),
3337 REPORT_SIZE(1, 8),
3338 REPORT_COUNT(1, 2),
3339 OUTPUT(1, Data|Var|Abs),
3341 USAGE(1, PID_USAGE_DEAD_BAND),
3342 LOGICAL_MINIMUM(1, 0),
3343 LOGICAL_MAXIMUM(2, 0x00ff),
3344 PHYSICAL_MINIMUM(1, 0),
3345 PHYSICAL_MAXIMUM(2, 0x2710),
3346 REPORT_SIZE(1, 8),
3347 REPORT_COUNT(1, 1),
3348 OUTPUT(1, Data|Var|Abs),
3349 END_COLLECTION,
3351 USAGE(1, PID_USAGE_BLOCK_FREE_REPORT),
3352 COLLECTION(1, Logical),
3353 REPORT_ID(1, 5),
3355 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3356 LOGICAL_MINIMUM(1, 1),
3357 LOGICAL_MAXIMUM(1, 0x7f),
3358 PHYSICAL_MINIMUM(1, 1),
3359 PHYSICAL_MAXIMUM(1, 0x7f),
3360 REPORT_SIZE(1, 8),
3361 REPORT_COUNT(1, 1),
3362 OUTPUT(1, Data|Var|Abs),
3363 END_COLLECTION,
3365 USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT),
3366 COLLECTION(1, Logical),
3367 REPORT_ID(1, 6),
3369 USAGE(1, PID_USAGE_DEVICE_GAIN),
3370 LOGICAL_MINIMUM(1, 0),
3371 LOGICAL_MAXIMUM(2, 0x00ff),
3372 PHYSICAL_MINIMUM(1, 0),
3373 PHYSICAL_MAXIMUM(2, 0x2710),
3374 REPORT_SIZE(1, 8),
3375 REPORT_COUNT(1, 1),
3376 OUTPUT(1, Data|Var|Abs),
3377 END_COLLECTION,
3379 USAGE(1, PID_USAGE_POOL_REPORT),
3380 COLLECTION(1, Logical),
3381 REPORT_ID(1, 1),
3383 USAGE(1, PID_USAGE_RAM_POOL_SIZE),
3384 LOGICAL_MINIMUM(1, 0),
3385 LOGICAL_MAXIMUM(4, 0xffff),
3386 PHYSICAL_MINIMUM(1, 0),
3387 PHYSICAL_MAXIMUM(4, 0xffff),
3388 REPORT_SIZE(1, 16),
3389 REPORT_COUNT(1, 1),
3390 FEATURE(1, Data|Var|Abs),
3392 USAGE(1, PID_USAGE_SIMULTANEOUS_EFFECTS_MAX),
3393 LOGICAL_MINIMUM(1, 0),
3394 LOGICAL_MAXIMUM(1, 0x7f),
3395 PHYSICAL_MINIMUM(1, 0),
3396 PHYSICAL_MAXIMUM(1, 0x7f),
3397 REPORT_SIZE(1, 8),
3398 REPORT_COUNT(1, 1),
3399 FEATURE(1, Data|Var|Abs),
3401 USAGE(1, PID_USAGE_DEVICE_MANAGED_POOL),
3402 USAGE(1, PID_USAGE_SHARED_PARAMETER_BLOCKS),
3403 LOGICAL_MINIMUM(1, 0),
3404 LOGICAL_MAXIMUM(1, 1),
3405 PHYSICAL_MINIMUM(1, 0),
3406 PHYSICAL_MAXIMUM(1, 1),
3407 REPORT_SIZE(1, 1),
3408 REPORT_COUNT(1, 8),
3409 FEATURE(1, Data|Var|Abs),
3410 END_COLLECTION,
3412 USAGE(1, PID_USAGE_CREATE_NEW_EFFECT_REPORT),
3413 COLLECTION(1, Logical),
3414 REPORT_ID(1, 2),
3416 USAGE(1, PID_USAGE_EFFECT_TYPE),
3417 COLLECTION(1, NamedArray),
3418 USAGE(1, PID_USAGE_ET_SQUARE),
3419 USAGE(1, PID_USAGE_ET_SINE),
3420 USAGE(1, PID_USAGE_ET_SPRING),
3421 LOGICAL_MINIMUM(1, 1),
3422 LOGICAL_MAXIMUM(1, 3),
3423 PHYSICAL_MINIMUM(1, 1),
3424 PHYSICAL_MAXIMUM(1, 3),
3425 REPORT_SIZE(1, 8),
3426 REPORT_COUNT(1, 1),
3427 FEATURE(1, Data|Ary|Abs),
3428 END_COLLECTION,
3429 END_COLLECTION,
3431 USAGE(1, PID_USAGE_BLOCK_LOAD_REPORT),
3432 COLLECTION(1, Logical),
3433 REPORT_ID(1, 3),
3435 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
3436 LOGICAL_MINIMUM(1, 1),
3437 LOGICAL_MAXIMUM(1, 0x7f),
3438 PHYSICAL_MINIMUM(1, 1),
3439 PHYSICAL_MAXIMUM(1, 0x7f),
3440 REPORT_SIZE(1, 8),
3441 REPORT_COUNT(1, 1),
3442 FEATURE(1, Data|Var|Abs),
3444 USAGE(1, PID_USAGE_BLOCK_LOAD_STATUS),
3445 COLLECTION(1, NamedArray),
3446 USAGE(1, PID_USAGE_BLOCK_LOAD_SUCCESS),
3447 USAGE(1, PID_USAGE_BLOCK_LOAD_FULL),
3448 USAGE(1, PID_USAGE_BLOCK_LOAD_ERROR),
3449 LOGICAL_MINIMUM(1, 1),
3450 LOGICAL_MAXIMUM(1, 3),
3451 PHYSICAL_MINIMUM(1, 1),
3452 PHYSICAL_MAXIMUM(1, 3),
3453 REPORT_SIZE(1, 8),
3454 REPORT_COUNT(1, 1),
3455 FEATURE(1, Data|Ary|Abs),
3456 END_COLLECTION,
3458 USAGE(1, PID_USAGE_RAM_POOL_AVAILABLE),
3459 LOGICAL_MINIMUM(1, 0),
3460 LOGICAL_MAXIMUM(4, 0xffff),
3461 PHYSICAL_MINIMUM(1, 0),
3462 PHYSICAL_MAXIMUM(4, 0xffff),
3463 REPORT_SIZE(1, 16),
3464 REPORT_COUNT(1, 1),
3465 FEATURE(1, Data|Var|Abs),
3466 END_COLLECTION,
3467 END_COLLECTION,
3469 C_ASSERT(sizeof(report_descriptor) < MAX_HID_DESCRIPTOR_LEN);
3470 #include "pop_hid_macros.h"
3472 struct hid_device_desc desc =
3474 .use_report_id = TRUE,
3475 .caps =
3477 .InputReportByteLength = 5,
3478 .OutputReportByteLength = 11,
3479 .FeatureReportByteLength = 5,
3481 .attributes = default_attributes,
3483 struct hid_expect expect_acquire[] =
3485 /* device control */
3487 .code = IOCTL_HID_WRITE_REPORT,
3488 .report_id = 1,
3489 .report_len = 2,
3490 .report_buf = {1, 0x01},
3492 /* device gain */
3494 .code = IOCTL_HID_WRITE_REPORT,
3495 .report_id = 6,
3496 .report_len = 2,
3497 .report_buf = {6, 0xff},
3500 struct hid_expect expect_reset[] =
3502 /* device control */
3504 .code = IOCTL_HID_WRITE_REPORT,
3505 .report_id = 1,
3506 .report_len = 2,
3507 .report_buf = {1, 0x01},
3510 struct hid_expect expect_enable_actuators[] =
3512 /* device control */
3514 .code = IOCTL_HID_WRITE_REPORT,
3515 .report_id = 1,
3516 .report_len = 2,
3517 .report_buf = {1, 0x04},
3520 struct hid_expect expect_disable_actuators[] =
3522 /* device control */
3524 .code = IOCTL_HID_WRITE_REPORT,
3525 .report_id = 1,
3526 .report_len = 2,
3527 .report_buf = {1, 0x05},
3530 struct hid_expect expect_stop_all[] =
3532 /* device control */
3534 .code = IOCTL_HID_WRITE_REPORT,
3535 .report_id = 1,
3536 .report_len = 2,
3537 .report_buf = {1, 0x06},
3540 struct hid_expect expect_device_pause[] =
3542 /* device control */
3544 .code = IOCTL_HID_WRITE_REPORT,
3545 .report_id = 1,
3546 .report_len = 2,
3547 .report_buf = {1, 0x02},
3550 struct hid_expect expect_device_continue[] =
3552 /* device control */
3554 .code = IOCTL_HID_WRITE_REPORT,
3555 .report_id = 1,
3556 .report_len = 2,
3557 .report_buf = {1, 0x03},
3560 struct hid_expect expect_create[] =
3562 /* create new effect */
3564 .code = IOCTL_HID_SET_FEATURE,
3565 .report_id = 2,
3566 .report_len = 2,
3567 .report_buf = {2,0x03},
3569 /* block load */
3571 .code = IOCTL_HID_GET_FEATURE,
3572 .report_id = 3,
3573 .report_len = 5,
3574 .report_buf = {3,0x01,0x01,0x00,0x00},
3576 /* set condition */
3578 .code = IOCTL_HID_WRITE_REPORT,
3579 .report_id = 4,
3580 .report_len = 9,
3581 .report_buf = {4,0x01,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
3583 /* set condition */
3585 .code = IOCTL_HID_WRITE_REPORT,
3586 .report_id = 4,
3587 .report_len = 9,
3588 .report_buf = {4,0x01,0x01,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
3590 /* update effect */
3592 .code = IOCTL_HID_WRITE_REPORT,
3593 .report_id = 3,
3594 .report_len = 11,
3595 .report_buf = {3,0x01,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0x00},
3598 struct hid_expect expect_create_2[] =
3600 /* create new effect */
3602 .code = IOCTL_HID_SET_FEATURE,
3603 .report_id = 2,
3604 .report_len = 2,
3605 .report_buf = {2,0x03},
3607 /* block load */
3609 .code = IOCTL_HID_GET_FEATURE,
3610 .report_id = 3,
3611 .report_len = 5,
3612 .report_buf = {3,0x02,0x01,0x00,0x00},
3614 /* set condition */
3616 .code = IOCTL_HID_WRITE_REPORT,
3617 .report_id = 4,
3618 .report_len = 9,
3619 .report_buf = {4,0x02,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
3621 /* set condition */
3623 .code = IOCTL_HID_WRITE_REPORT,
3624 .report_id = 4,
3625 .report_len = 9,
3626 .report_buf = {4,0x02,0x01,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
3628 /* update effect */
3630 .code = IOCTL_HID_WRITE_REPORT,
3631 .report_id = 3,
3632 .report_len = 11,
3633 .report_buf = {3,0x02,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0x00},
3636 struct hid_expect expect_create_delay[] =
3638 /* create new effect */
3640 .code = IOCTL_HID_SET_FEATURE,
3641 .report_id = 2,
3642 .report_len = 2,
3643 .report_buf = {2,0x03},
3645 /* block load */
3647 .code = IOCTL_HID_GET_FEATURE,
3648 .report_id = 3,
3649 .report_len = 5,
3650 .report_buf = {3,0x01,0x01,0x00,0x00},
3652 /* set condition */
3654 .code = IOCTL_HID_WRITE_REPORT,
3655 .report_id = 4,
3656 .report_len = 9,
3657 .report_buf = {4,0x01,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
3659 /* set condition */
3661 .code = IOCTL_HID_WRITE_REPORT,
3662 .report_id = 4,
3663 .report_len = 9,
3664 .report_buf = {4,0x01,0x01,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
3666 /* update effect */
3668 .code = IOCTL_HID_WRITE_REPORT,
3669 .report_id = 3,
3670 .report_len = 11,
3671 .report_buf = {3,0x01,0x03,0x08,0x01,0x00,0xff,0x7f,0x01,0x55,0x00},
3674 struct hid_expect expect_create_duration[] =
3676 /* create new effect */
3678 .code = IOCTL_HID_SET_FEATURE,
3679 .report_id = 2,
3680 .report_len = 2,
3681 .report_buf = {2,0x03},
3683 /* block load */
3685 .code = IOCTL_HID_GET_FEATURE,
3686 .report_id = 3,
3687 .report_len = 5,
3688 .report_buf = {3,0x01,0x01,0x00,0x00},
3690 /* set condition */
3692 .code = IOCTL_HID_WRITE_REPORT,
3693 .report_id = 4,
3694 .report_len = 9,
3695 .report_buf = {4,0x01,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
3697 /* set condition */
3699 .code = IOCTL_HID_WRITE_REPORT,
3700 .report_id = 4,
3701 .report_len = 9,
3702 .report_buf = {4,0x01,0x01,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
3704 /* update effect */
3706 .code = IOCTL_HID_WRITE_REPORT,
3707 .report_id = 3,
3708 .report_len = 11,
3709 .report_buf = {3,0x01,0x03,0x08,0x00,0x00,0x00,0x00,0x01,0x55,0x00},
3712 struct hid_expect expect_start =
3714 /* effect control */
3715 .code = IOCTL_HID_WRITE_REPORT,
3716 .report_id = 2,
3717 .report_len = 4,
3718 .report_buf = {2, 0x01, 0x01, 0x01},
3720 struct hid_expect expect_start_2 =
3722 /* effect control */
3723 .code = IOCTL_HID_WRITE_REPORT,
3724 .report_id = 2,
3725 .report_len = 4,
3726 .report_buf = {2, 0x02, 0x02, 0x01},
3728 struct hid_expect expect_stop =
3730 /* effect control */
3731 .code = IOCTL_HID_WRITE_REPORT,
3732 .report_id = 2,
3733 .report_len = 4,
3734 .report_buf = {2, 0x01, 0x03, 0x00},
3736 struct hid_expect expect_stop_2 =
3738 /* effect control */
3739 .code = IOCTL_HID_WRITE_REPORT,
3740 .report_id = 2,
3741 .report_len = 4,
3742 .report_buf = {2, 0x02, 0x03, 0x00},
3744 struct hid_expect expect_destroy[] =
3746 /* effect operation */
3748 .code = IOCTL_HID_WRITE_REPORT,
3749 .report_id = 2,
3750 .report_len = 4,
3751 .report_buf = {2,0x01,0x03,0x00},
3753 /* block free */
3755 .code = IOCTL_HID_WRITE_REPORT,
3756 .report_id = 5,
3757 .report_len = 2,
3758 .report_buf = {5,0x01},
3761 struct hid_expect expect_destroy_2[] =
3763 /* effect operation */
3765 .code = IOCTL_HID_WRITE_REPORT,
3766 .report_id = 2,
3767 .report_len = 4,
3768 .report_buf = {2,0x02,0x03,0x00},
3770 /* block free */
3772 .code = IOCTL_HID_WRITE_REPORT,
3773 .report_id = 5,
3774 .report_len = 2,
3775 .report_buf = {5,0x02},
3778 struct hid_expect device_state_input[] =
3780 /* effect state */
3782 .code = IOCTL_HID_READ_REPORT,
3783 .report_id = 2,
3784 .report_len = 4,
3785 .report_buf = {2,0xff,0x00,0xff},
3787 /* device state */
3789 .code = IOCTL_HID_READ_REPORT,
3790 .report_id = 1,
3791 .report_len = 5,
3792 .report_buf = {1,0x12,0x34,0x56,0xff},
3795 struct hid_expect device_state_input_0[] =
3797 /* effect state */
3799 .code = IOCTL_HID_READ_REPORT,
3800 .report_id = 2,
3801 .report_len = 4,
3802 .report_buf = {2,0xff,0x00,0xff},
3804 /* device state */
3806 .code = IOCTL_HID_READ_REPORT,
3807 .report_id = 1,
3808 .report_len = 5,
3809 .report_buf = {1,0x56,0x12,0x34,0xff},
3812 struct hid_expect device_state_input_1[] =
3814 /* effect state */
3816 .code = IOCTL_HID_READ_REPORT,
3817 .report_id = 2,
3818 .report_len = 4,
3819 .report_buf = {2,0x00,0x01,0x01},
3821 /* device state */
3823 .code = IOCTL_HID_READ_REPORT,
3824 .report_id = 1,
3825 .report_len = 5,
3826 .report_buf = {1,0x65,0x43,0x21,0x00},
3829 struct hid_expect device_state_input_2[] =
3831 /* effect state */
3833 .code = IOCTL_HID_READ_REPORT,
3834 .report_id = 2,
3835 .report_len = 4,
3836 .report_buf = {2,0x03,0x00,0x01},
3838 /* device state */
3840 .code = IOCTL_HID_READ_REPORT,
3841 .report_id = 1,
3842 .report_len = 5,
3843 .report_buf = {1,0x12,0x34,0x56,0xff},
3846 struct hid_expect expect_pool[] =
3848 /* device pool */
3850 .code = IOCTL_HID_GET_FEATURE,
3851 .report_id = 1,
3852 .report_len = 5,
3853 .report_buf = {1,0x10,0x00,0x04,0x03},
3854 .todo = TRUE,
3856 /* device pool */
3858 .code = IOCTL_HID_GET_FEATURE,
3859 .report_id = 1,
3860 .report_len = 5,
3861 .report_buf = {1,0x10,0x00,0x04,0x03},
3862 .todo = TRUE,
3865 static const DWORD expect_axes[3] =
3867 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
3868 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
3869 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
3871 static const LONG expect_directions[3] = {
3872 +3000,
3876 static const DIENVELOPE expect_envelope =
3878 .dwSize = sizeof(DIENVELOPE),
3879 .dwAttackLevel = 1000,
3880 .dwAttackTime = 2000,
3881 .dwFadeLevel = 3000,
3882 .dwFadeTime = 4000,
3884 static const DICONDITION expect_condition[3] =
3887 .lOffset = -500,
3888 .lPositiveCoefficient = 2000,
3889 .lNegativeCoefficient = -3000,
3890 .dwPositiveSaturation = -4000,
3891 .dwNegativeSaturation = -5000,
3892 .lDeadBand = 6000,
3895 .lOffset = 6000,
3896 .lPositiveCoefficient = 5000,
3897 .lNegativeCoefficient = -4000,
3898 .dwPositiveSaturation = 3000,
3899 .dwNegativeSaturation = 2000,
3900 .lDeadBand = 1000,
3903 .lOffset = -7000,
3904 .lPositiveCoefficient = -8000,
3905 .lNegativeCoefficient = 9000,
3906 .dwPositiveSaturation = 10000,
3907 .dwNegativeSaturation = 11000,
3908 .lDeadBand = -12000,
3911 const DIEFFECT expect_desc =
3913 .dwSize = sizeof(DIEFFECT_DX6),
3914 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
3915 .dwDuration = 1000,
3916 .dwSamplePeriod = 2000,
3917 .dwGain = 3000,
3918 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
3919 .dwTriggerRepeatInterval = 5000,
3920 .cAxes = 2,
3921 .rgdwAxes = (void *)expect_axes,
3922 .rglDirection = (void *)expect_directions,
3923 .lpEnvelope = (void *)&expect_envelope,
3924 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
3925 .lpvTypeSpecificParams = (void *)expect_condition,
3926 .dwStartDelay = 6000,
3928 DIPROPGUIDANDPATH prop_guid_path =
3930 .diph =
3932 .dwSize = sizeof(DIPROPGUIDANDPATH),
3933 .dwHeaderSize = sizeof(DIPROPHEADER),
3934 .dwHow = DIPH_DEVICE,
3937 DIPROPDWORD prop_dword =
3939 .diph =
3941 .dwSize = sizeof(DIPROPDWORD),
3942 .dwHeaderSize = sizeof(DIPROPHEADER),
3943 .dwHow = DIPH_DEVICE,
3946 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
3947 IDirectInputDevice8W *device;
3948 IDirectInputEffect *effect, *effect2;
3949 DIEFFECT effect_desc;
3950 HANDLE file, event;
3951 ULONG res, ref;
3952 DWORD flags;
3953 HRESULT hr;
3954 HWND hwnd;
3956 cleanup_registry_keys();
3958 desc.report_descriptor_len = sizeof(report_descriptor);
3959 memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) );
3960 desc.expect_size = sizeof(expect_pool);
3961 memcpy( desc.expect, expect_pool, sizeof(expect_pool) );
3962 fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
3964 if (!hid_device_start( &desc )) goto done;
3965 if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
3967 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
3968 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
3969 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
3970 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
3971 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
3972 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
3974 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
3975 NULL, NULL, NULL, NULL );
3977 event = CreateEventW( NULL, FALSE, FALSE, NULL );
3978 ok( event != NULL, "CreateEventW failed, last error %lu\n", GetLastError() );
3979 hr = IDirectInputDevice8_SetEventNotification( device, event );
3980 ok( hr == DI_OK, "SetEventNotification returned: %#lx\n", hr );
3981 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
3982 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
3983 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
3984 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
3986 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
3987 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
3988 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
3989 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetForceFeedbackState returned %#lx\n", hr );
3990 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
3991 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "SendForceFeedbackCommand returned %#lx\n", hr );
3993 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
3994 hr = IDirectInputDevice8_Acquire( device );
3995 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
3996 wait_hid_expect( file, 100 );
3998 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
3999 prop_dword.dwData = 0xdeadbeef;
4000 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4001 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
4002 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#lx\n", prop_dword.dwData );
4003 set_hid_expect( file, NULL, 0 );
4005 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4006 res = 0xdeadbeef;
4007 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4008 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4009 flags = DIGFFS_STOPPED | DIGFFS_EMPTY;
4010 ok( res == flags, "got state %#lx\n", res );
4011 set_hid_expect( file, NULL, 0 );
4013 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4014 prop_dword.dwData = 0xdeadbeef;
4015 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4016 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
4017 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#lx\n", prop_dword.dwData );
4018 set_hid_expect( file, NULL, 0 );
4020 send_hid_input( file, device_state_input, sizeof(struct hid_expect) );
4021 res = WaitForSingleObject( event, 100 );
4022 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
4023 send_hid_input( file, device_state_input, sizeof(device_state_input) );
4024 res = WaitForSingleObject( event, 100 );
4025 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#lx\n", res );
4027 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4028 res = 0xdeadbeef;
4029 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4030 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4031 flags = DIGFFS_PAUSED | DIGFFS_EMPTY | DIGFFS_ACTUATORSON | DIGFFS_POWERON |
4032 DIGFFS_SAFETYSWITCHON | DIGFFS_USERFFSWITCHON;
4033 ok( res == flags, "got state %#lx\n", res );
4034 set_hid_expect( file, NULL, 0 );
4036 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, NULL, &effect, NULL );
4037 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
4039 hr = IDirectInputEffect_GetEffectStatus( effect, NULL );
4040 ok( hr == E_POINTER, "GetEffectStatus returned %#lx\n", hr );
4041 res = 0xdeadbeef;
4042 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4043 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#lx\n", hr );
4044 ok( res == 0, "got status %#lx\n", res );
4046 flags = DIEP_ALLPARAMS;
4047 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags | DIEP_NODOWNLOAD );
4048 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#lx\n", hr );
4050 set_hid_expect( file, expect_reset, sizeof(struct hid_expect) );
4051 hr = IDirectInputDevice8_Unacquire( device );
4052 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
4053 set_hid_expect( file, NULL, 0 );
4055 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4056 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetEffectStatus returned %#lx\n", hr );
4058 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
4059 hr = IDirectInputDevice8_Acquire( device );
4060 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
4061 wait_hid_expect( file, 100 );
4063 res = 0xdeadbeef;
4064 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4065 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#lx\n", hr );
4066 ok( res == 0, "got status %#lx\n", res );
4068 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4069 res = 0xdeadbeef;
4070 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4071 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4072 flags = DIGFFS_STOPPED | DIGFFS_EMPTY;
4073 ok( res == flags, "got state %#lx\n", res );
4074 set_hid_expect( file, NULL, 0 );
4076 set_hid_expect( file, expect_create, sizeof(expect_create) );
4077 hr = IDirectInputEffect_Download( effect );
4078 ok( hr == DI_OK, "Download returned %#lx\n", hr );
4079 set_hid_expect( file, NULL, 0 );
4081 res = 0xdeadbeef;
4082 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4083 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4084 ok( res == 0, "got status %#lx\n", res );
4085 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4086 res = 0xdeadbeef;
4087 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4088 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4089 flags = DIGFFS_STOPPED;
4090 ok( res == flags, "got state %#lx\n", res );
4091 set_hid_expect( file, NULL, 0 );
4093 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4094 prop_dword.dwData = 0xdeadbeef;
4095 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4096 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
4097 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#lx\n", prop_dword.dwData );
4098 set_hid_expect( file, NULL, 0 );
4100 set_hid_expect( file, &expect_start, sizeof(expect_start) );
4101 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
4102 ok( hr == DI_OK, "Start returned %#lx\n", hr );
4103 set_hid_expect( file, NULL, 0 );
4105 set_hid_expect( file, expect_create_2, sizeof(expect_create_2) );
4106 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &expect_desc, &effect2, NULL );
4107 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
4108 set_hid_expect( file, NULL, 0 );
4109 set_hid_expect( file, &expect_start_2, sizeof(expect_start_2) );
4110 hr = IDirectInputEffect_Start( effect2, 1, DIES_SOLO );
4111 ok( hr == DI_OK, "Start returned %#lx\n", hr );
4112 set_hid_expect( file, NULL, 0 );
4113 res = 0xdeadbeef;
4114 hr = IDirectInputEffect_GetEffectStatus( effect2, &res );
4115 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4116 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4117 res = 0xdeadbeef;
4118 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4119 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4120 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4121 set_hid_expect( file, &expect_stop_2, sizeof(expect_stop_2) );
4122 hr = IDirectInputEffect_Stop( effect2 );
4123 ok( hr == DI_OK, "Stop returned %#lx\n", hr );
4124 set_hid_expect( file, NULL, 0 );
4125 res = 0xdeadbeef;
4126 hr = IDirectInputEffect_GetEffectStatus( effect2, &res );
4127 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4128 ok( res == 0, "got status %#lx\n", res );
4129 set_hid_expect( file, expect_destroy_2, sizeof(expect_destroy_2) );
4130 ref = IDirectInputEffect_Release( effect2 );
4131 ok( ref == 0, "Release returned %ld\n", ref );
4132 set_hid_expect( file, NULL, 0 );
4134 /* sending commands has no direct effect on status */
4135 set_hid_expect( file, expect_stop_all, sizeof(expect_stop_all) );
4136 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_STOPALL );
4137 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
4138 set_hid_expect( file, NULL, 0 );
4139 res = 0xdeadbeef;
4140 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4141 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4142 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4143 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4144 res = 0xdeadbeef;
4145 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4146 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4147 flags = DIGFFS_STOPPED;
4148 ok( res == flags, "got state %#lx\n", res );
4149 set_hid_expect( file, NULL, 0 );
4151 set_hid_expect( file, expect_device_pause, sizeof(expect_device_pause) );
4152 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_PAUSE );
4153 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
4154 set_hid_expect( file, NULL, 0 );
4155 res = 0xdeadbeef;
4156 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4157 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4158 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4159 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4160 res = 0xdeadbeef;
4161 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4162 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4163 flags = DIGFFS_STOPPED;
4164 ok( res == flags, "got state %#lx\n", res );
4165 set_hid_expect( file, NULL, 0 );
4167 set_hid_expect( file, expect_device_continue, sizeof(expect_device_continue) );
4168 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_CONTINUE );
4169 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
4170 set_hid_expect( file, NULL, 0 );
4171 res = 0xdeadbeef;
4172 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4173 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4174 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4175 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4176 res = 0xdeadbeef;
4177 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4178 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4179 flags = DIGFFS_STOPPED;
4180 ok( res == flags, "got state %#lx\n", res );
4181 set_hid_expect( file, NULL, 0 );
4183 set_hid_expect( file, expect_disable_actuators, sizeof(expect_disable_actuators) );
4184 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSOFF );
4185 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
4186 set_hid_expect( file, NULL, 0 );
4187 res = 0xdeadbeef;
4188 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4189 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4190 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4191 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4192 res = 0xdeadbeef;
4193 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4194 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4195 flags = DIGFFS_STOPPED;
4196 ok( res == flags, "got state %#lx\n", res );
4197 set_hid_expect( file, NULL, 0 );
4199 set_hid_expect( file, expect_enable_actuators, sizeof(expect_enable_actuators) );
4200 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSON );
4201 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#lx\n", hr );
4202 set_hid_expect( file, NULL, 0 );
4203 res = 0xdeadbeef;
4204 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4205 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4206 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4207 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4208 res = 0xdeadbeef;
4209 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4210 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4211 flags = DIGFFS_STOPPED;
4212 ok( res == flags, "got state %#lx\n", res );
4213 set_hid_expect( file, NULL, 0 );
4215 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
4216 hr = IDirectInputEffect_Stop( effect );
4217 ok( hr == DI_OK, "Stop returned %#lx\n", hr );
4218 set_hid_expect( file, NULL, 0 );
4219 res = 0xdeadbeef;
4220 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4221 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4222 ok( res == 0, "got status %#lx\n", res );
4223 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4224 res = 0xdeadbeef;
4225 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4226 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4227 flags = DIGFFS_STOPPED;
4228 ok( res == flags, "got state %#lx\n", res );
4229 set_hid_expect( file, NULL, 0 );
4231 send_hid_input( file, device_state_input_0, sizeof(device_state_input_0) );
4232 res = WaitForSingleObject( event, 100 );
4233 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#lx\n", res );
4234 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4235 res = 0xdeadbeef;
4236 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4237 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4238 flags = DIGFFS_PAUSED | DIGFFS_ACTUATORSON | DIGFFS_POWERON | DIGFFS_SAFETYSWITCHON | DIGFFS_USERFFSWITCHON;
4239 ok( res == flags, "got state %#lx\n", res );
4240 set_hid_expect( file, NULL, 0 );
4242 send_hid_input( file, device_state_input_1, sizeof(device_state_input_1) );
4243 res = WaitForSingleObject( event, 100 );
4244 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#lx\n", res );
4245 res = 0xdeadbeef;
4246 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4247 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4248 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4249 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4250 res = 0xdeadbeef;
4251 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4252 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4253 flags = DIGFFS_ACTUATORSOFF | DIGFFS_POWEROFF | DIGFFS_SAFETYSWITCHOFF | DIGFFS_USERFFSWITCHOFF;
4254 ok( res == flags, "got state %#lx\n", res );
4255 set_hid_expect( file, NULL, 0 );
4257 send_hid_input( file, device_state_input_2, sizeof(device_state_input_2) );
4258 res = WaitForSingleObject( event, 100 );
4259 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#lx\n", res );
4260 res = 0xdeadbeef;
4261 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4262 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4263 ok( res == 0, "got status %#lx\n", res );
4264 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4265 res = 0xdeadbeef;
4266 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4267 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4268 flags = DIGFFS_PAUSED | DIGFFS_ACTUATORSON | DIGFFS_POWEROFF | DIGFFS_SAFETYSWITCHOFF | DIGFFS_USERFFSWITCHOFF;
4269 ok( res == flags, "got state %#lx\n", res );
4270 set_hid_expect( file, NULL, 0 );
4272 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
4273 hr = IDirectInputEffect_Stop( effect );
4274 ok( hr == DI_OK, "Stop returned %#lx\n", hr );
4275 set_hid_expect( file, NULL, 0 );
4277 res = 0xdeadbeef;
4278 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4279 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4280 ok( res == 0, "got status %#lx\n", res );
4281 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4282 res = 0xdeadbeef;
4283 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4284 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4285 flags = DIGFFS_PAUSED | DIGFFS_ACTUATORSON | DIGFFS_POWEROFF | DIGFFS_SAFETYSWITCHOFF | DIGFFS_USERFFSWITCHOFF;
4286 ok( res == flags, "got state %#lx\n", res );
4287 set_hid_expect( file, NULL, 0 );
4289 set_hid_expect( file, expect_destroy, sizeof(expect_destroy) );
4290 hr = IDirectInputEffect_Unload( effect );
4291 ok( hr == DI_OK, "Unload returned %#lx\n", hr );
4292 set_hid_expect( file, NULL, 0 );
4294 res = 0xdeadbeef;
4295 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4296 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#lx\n", hr );
4297 ok( res == 0, "got status %#lx\n", res );
4298 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
4299 res = 0xdeadbeef;
4300 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
4301 ok( hr == DI_OK, "GetForceFeedbackState returned %#lx\n", hr );
4302 flags = DIGFFS_EMPTY | DIGFFS_PAUSED | DIGFFS_ACTUATORSON | DIGFFS_POWEROFF |
4303 DIGFFS_SAFETYSWITCHOFF | DIGFFS_USERFFSWITCHOFF;
4304 ok( res == flags, "got state %#lx\n", res );
4305 set_hid_expect( file, NULL, 0 );
4307 ref = IDirectInputEffect_Release( effect );
4308 ok( ref == 0, "Release returned %ld\n", ref );
4310 /* start delay has no direct effect on effect status */
4311 effect_desc = expect_desc;
4312 effect_desc.dwStartDelay = 32767000;
4313 set_hid_expect( file, expect_create_delay, sizeof(expect_create_delay) );
4314 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &effect_desc, &effect, NULL );
4315 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
4316 set_hid_expect( file, NULL, 0 );
4317 res = 0xdeadbeef;
4318 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4319 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4320 ok( res == 0, "got status %#lx\n", res );
4321 set_hid_expect( file, &expect_start, sizeof(expect_start) );
4322 hr = IDirectInputEffect_Start( effect, 1, 0 );
4323 ok( hr == DI_OK, "Start returned %#lx\n", hr );
4324 set_hid_expect( file, NULL, 0 );
4325 res = 0xdeadbeef;
4326 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4327 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4328 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4329 set_hid_expect( file, expect_destroy, sizeof(expect_destroy) );
4330 ref = IDirectInputEffect_Release( effect );
4331 ok( ref == 0, "Release returned %ld\n", ref );
4332 set_hid_expect( file, NULL, 0 );
4334 /* duration has no direct effect on effect status */
4335 effect_desc = expect_desc;
4336 effect_desc.dwDuration = 100;
4337 effect_desc.dwStartDelay = 0;
4338 set_hid_expect( file, expect_create_duration, sizeof(expect_create_duration) );
4339 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &effect_desc, &effect, NULL );
4340 ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
4341 set_hid_expect( file, NULL, 0 );
4342 res = 0xdeadbeef;
4343 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4344 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4345 ok( res == 0, "got status %#lx\n", res );
4346 set_hid_expect( file, &expect_start, sizeof(expect_start) );
4347 hr = IDirectInputEffect_Start( effect, 1, 0 );
4348 ok( hr == DI_OK, "Start returned %#lx\n", hr );
4349 set_hid_expect( file, NULL, 0 );
4350 Sleep( 100 );
4351 res = 0xdeadbeef;
4352 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
4353 ok( hr == DI_OK, "GetEffectStatus returned %#lx\n", hr );
4354 ok( res == DIEGES_PLAYING, "got status %#lx\n", res );
4355 set_hid_expect( file, expect_destroy, sizeof(expect_destroy) );
4356 ref = IDirectInputEffect_Release( effect );
4357 ok( ref == 0, "Release returned %ld\n", ref );
4358 set_hid_expect( file, NULL, 0 );
4360 set_hid_expect( file, expect_reset, sizeof(struct hid_expect) );
4361 hr = IDirectInputDevice8_Unacquire( device );
4362 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
4363 set_hid_expect( file, NULL, 0 );
4365 ref = IDirectInputDevice8_Release( device );
4366 ok( ref == 0, "Release returned %ld\n", ref );
4368 DestroyWindow( hwnd );
4369 CloseHandle( event );
4370 CloseHandle( file );
4372 done:
4373 hid_device_stop( &desc );
4374 cleanup_registry_keys();
4375 winetest_pop_context();
4378 #define check_interface( a, b, c ) check_interface_( __LINE__, a, b, c )
4379 static void check_interface_( unsigned int line, void *iface_ptr, REFIID iid, BOOL supported )
4381 IUnknown *iface = iface_ptr;
4382 HRESULT hr, expected;
4383 IUnknown *unk;
4385 expected = supported ? S_OK : E_NOINTERFACE;
4386 hr = IUnknown_QueryInterface( iface, iid, (void **)&unk );
4387 ok_(__FILE__, line)( hr == expected, "got hr %#lx, expected %#lx.\n", hr, expected );
4388 if (SUCCEEDED(hr)) IUnknown_Release( unk );
4391 #define check_runtimeclass( a, b ) check_runtimeclass_( __LINE__, (IInspectable *)a, b )
4392 static void check_runtimeclass_( int line, IInspectable *inspectable, const WCHAR *class_name )
4394 const WCHAR *buffer;
4395 UINT32 length;
4396 HSTRING str;
4397 HRESULT hr;
4399 hr = IInspectable_GetRuntimeClassName( inspectable, &str );
4400 ok_(__FILE__, line)( hr == S_OK, "GetRuntimeClassName returned %#lx\n", hr );
4401 buffer = pWindowsGetStringRawBuffer( str, &length );
4402 ok_(__FILE__, line)( !wcscmp( buffer, class_name ), "got class name %s\n", debugstr_w(buffer) );
4403 pWindowsDeleteString( str );
4406 struct controller_handler
4408 IEventHandler_RawGameController IEventHandler_RawGameController_iface;
4409 HANDLE event;
4410 BOOL invoked;
4413 static inline struct controller_handler *impl_from_IEventHandler_RawGameController( IEventHandler_RawGameController *iface )
4415 return CONTAINING_RECORD( iface, struct controller_handler, IEventHandler_RawGameController_iface );
4418 static HRESULT WINAPI controller_handler_QueryInterface( IEventHandler_RawGameController *iface, REFIID iid, void **out )
4420 if (IsEqualGUID( iid, &IID_IUnknown ) ||
4421 IsEqualGUID( iid, &IID_IAgileObject ) ||
4422 IsEqualGUID( iid, &IID_IEventHandler_RawGameController ))
4424 IUnknown_AddRef( iface );
4425 *out = iface;
4426 return S_OK;
4429 trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
4430 *out = NULL;
4431 return E_NOINTERFACE;
4434 static ULONG WINAPI controller_handler_AddRef( IEventHandler_RawGameController *iface )
4436 return 2;
4439 static ULONG WINAPI controller_handler_Release( IEventHandler_RawGameController *iface )
4441 return 1;
4444 static HRESULT WINAPI controller_handler_Invoke( IEventHandler_RawGameController *iface,
4445 IInspectable *sender, IRawGameController *controller )
4447 struct controller_handler *impl = impl_from_IEventHandler_RawGameController( iface );
4449 trace( "iface %p, sender %p, controller %p\n", iface, sender, controller );
4451 ok( sender == NULL, "got sender %p\n", sender );
4452 impl->invoked = TRUE;
4453 SetEvent( impl->event );
4455 return S_OK;
4458 static const IEventHandler_RawGameControllerVtbl controller_handler_vtbl =
4460 controller_handler_QueryInterface,
4461 controller_handler_AddRef,
4462 controller_handler_Release,
4463 controller_handler_Invoke,
4466 static struct controller_handler controller_added = {{&controller_handler_vtbl}};
4468 #define check_bool_async( a, b, c, d, e ) check_bool_async_( __LINE__, a, b, c, d, e )
4469 static void check_bool_async_( int line, IAsyncOperation_boolean *async, UINT32 expect_id, AsyncStatus expect_status,
4470 HRESULT expect_hr, BOOLEAN expect_result )
4472 AsyncStatus async_status;
4473 IAsyncInfo *async_info;
4474 HRESULT hr, async_hr;
4475 UINT32 async_id;
4476 BOOLEAN result;
4478 hr = IAsyncOperation_boolean_QueryInterface( async, &IID_IAsyncInfo, (void **)&async_info );
4479 ok_(__FILE__, line)( hr == S_OK, "QueryInterface returned %#lx\n", hr );
4481 async_id = 0xdeadbeef;
4482 hr = IAsyncInfo_get_Id( async_info, &async_id );
4483 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Id returned %#lx\n", hr );
4484 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Id returned %#lx\n", hr );
4485 ok_(__FILE__, line)( async_id == expect_id, "got id %u\n", async_id );
4487 async_status = 0xdeadbeef;
4488 hr = IAsyncInfo_get_Status( async_info, &async_status );
4489 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Status returned %#lx\n", hr );
4490 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Status returned %#lx\n", hr );
4491 ok_(__FILE__, line)( async_status == expect_status, "got status %u\n", async_status );
4493 async_hr = 0xdeadbeef;
4494 hr = IAsyncInfo_get_ErrorCode( async_info, &async_hr );
4495 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_ErrorCode returned %#lx\n", hr );
4496 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_ErrorCode returned %#lx\n", hr );
4497 if (expect_status < 4) todo_wine_if(FAILED(expect_hr)) ok_(__FILE__, line)( async_hr == expect_hr, "got error %#lx\n", async_hr );
4498 else ok_(__FILE__, line)( async_hr == E_ILLEGAL_METHOD_CALL, "got error %#lx\n", async_hr );
4500 IAsyncInfo_Release( async_info );
4502 result = !expect_result;
4503 hr = IAsyncOperation_boolean_GetResults( async, &result );
4504 switch (expect_status)
4506 case Completed:
4507 case Error:
4508 todo_wine_if(FAILED(expect_hr))
4509 ok_(__FILE__, line)( hr == expect_hr, "GetResults returned %#lx\n", hr );
4510 ok_(__FILE__, line)( result == expect_result, "got result %u\n", result );
4511 break;
4512 case Canceled:
4513 case Started:
4514 default:
4515 ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "GetResults returned %#lx\n", hr );
4516 break;
4520 #define check_result_async( a, b, c, d, e ) check_result_async_( __LINE__, a, b, c, d, e )
4521 static void check_result_async_( int line, IAsyncOperation_ForceFeedbackLoadEffectResult *async, UINT32 expect_id,
4522 AsyncStatus expect_status, HRESULT expect_hr, ForceFeedbackLoadEffectResult expect_result )
4524 ForceFeedbackLoadEffectResult result;
4525 AsyncStatus async_status;
4526 IAsyncInfo *async_info;
4527 HRESULT hr, async_hr;
4528 UINT32 async_id;
4530 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_QueryInterface( async, &IID_IAsyncInfo, (void **)&async_info );
4531 ok_(__FILE__, line)( hr == S_OK, "QueryInterface returned %#lx\n", hr );
4533 async_id = 0xdeadbeef;
4534 hr = IAsyncInfo_get_Id( async_info, &async_id );
4535 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Id returned %#lx\n", hr );
4536 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Id returned %#lx\n", hr );
4537 ok_(__FILE__, line)( async_id == expect_id, "got id %u\n", async_id );
4539 async_status = 0xdeadbeef;
4540 hr = IAsyncInfo_get_Status( async_info, &async_status );
4541 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Status returned %#lx\n", hr );
4542 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Status returned %#lx\n", hr );
4543 ok_(__FILE__, line)( async_status == expect_status, "got status %u\n", async_status );
4545 async_hr = 0xdeadbeef;
4546 hr = IAsyncInfo_get_ErrorCode( async_info, &async_hr );
4547 if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_ErrorCode returned %#lx\n", hr );
4548 else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_ErrorCode returned %#lx\n", hr );
4549 if (expect_status < 4) todo_wine_if(FAILED(expect_hr)) ok_(__FILE__, line)( async_hr == expect_hr, "got error %#lx\n", async_hr );
4550 else ok_(__FILE__, line)( async_hr == E_ILLEGAL_METHOD_CALL, "got error %#lx\n", async_hr );
4552 IAsyncInfo_Release( async_info );
4554 result = !expect_result;
4555 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_GetResults( async, &result );
4556 switch (expect_status)
4558 case Completed:
4559 case Error:
4560 todo_wine_if(FAILED(expect_hr))
4561 ok_(__FILE__, line)( hr == expect_hr, "GetResults returned %#lx\n", hr );
4562 ok_(__FILE__, line)( result == expect_result, "got result %u\n", result );
4563 break;
4564 case Canceled:
4565 case Started:
4566 default:
4567 ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "GetResults returned %#lx\n", hr );
4568 break;
4572 struct bool_async_handler
4574 IAsyncOperationCompletedHandler_boolean IAsyncOperationCompletedHandler_boolean_iface;
4575 IAsyncOperation_boolean *async;
4576 AsyncStatus status;
4577 BOOL invoked;
4578 HANDLE event;
4581 static inline struct bool_async_handler *impl_from_IAsyncOperationCompletedHandler_boolean( IAsyncOperationCompletedHandler_boolean *iface )
4583 return CONTAINING_RECORD( iface, struct bool_async_handler, IAsyncOperationCompletedHandler_boolean_iface );
4586 static HRESULT WINAPI bool_async_handler_QueryInterface( IAsyncOperationCompletedHandler_boolean *iface, REFIID iid, void **out )
4588 if (IsEqualGUID( iid, &IID_IUnknown ) ||
4589 IsEqualGUID( iid, &IID_IAgileObject ) ||
4590 IsEqualGUID( iid, &IID_IAsyncOperationCompletedHandler_boolean ))
4592 IUnknown_AddRef( iface );
4593 *out = iface;
4594 return S_OK;
4597 trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
4598 *out = NULL;
4599 return E_NOINTERFACE;
4602 static ULONG WINAPI bool_async_handler_AddRef( IAsyncOperationCompletedHandler_boolean *iface )
4604 return 2;
4607 static ULONG WINAPI bool_async_handler_Release( IAsyncOperationCompletedHandler_boolean *iface )
4609 return 1;
4612 static HRESULT WINAPI bool_async_handler_Invoke( IAsyncOperationCompletedHandler_boolean *iface,
4613 IAsyncOperation_boolean *async, AsyncStatus status )
4615 struct bool_async_handler *impl = impl_from_IAsyncOperationCompletedHandler_boolean( iface );
4617 trace( "iface %p, async %p, status %u\n", iface, async, status );
4619 ok( !impl->invoked, "invoked twice\n" );
4620 impl->invoked = TRUE;
4621 impl->async = async;
4622 impl->status = status;
4623 if (impl->event) SetEvent( impl->event );
4625 return S_OK;
4628 static IAsyncOperationCompletedHandler_booleanVtbl bool_async_handler_vtbl =
4630 /*** IUnknown methods ***/
4631 bool_async_handler_QueryInterface,
4632 bool_async_handler_AddRef,
4633 bool_async_handler_Release,
4634 /*** IAsyncOperationCompletedHandler<boolean> methods ***/
4635 bool_async_handler_Invoke,
4638 static struct bool_async_handler default_bool_async_handler = {{&bool_async_handler_vtbl}};
4640 struct result_async_handler
4642 IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface;
4643 IAsyncOperation_ForceFeedbackLoadEffectResult *async;
4644 AsyncStatus status;
4645 BOOL invoked;
4646 HANDLE event;
4649 static inline struct result_async_handler *impl_from_IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult( IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult *iface )
4651 return CONTAINING_RECORD( iface, struct result_async_handler, IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
4654 static HRESULT WINAPI result_async_handler_QueryInterface( IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult *iface, REFIID iid, void **out )
4656 if (IsEqualGUID( iid, &IID_IUnknown ) ||
4657 IsEqualGUID( iid, &IID_IAgileObject ) ||
4658 IsEqualGUID( iid, &IID_IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult ))
4660 IUnknown_AddRef( iface );
4661 *out = iface;
4662 return S_OK;
4665 trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
4666 *out = NULL;
4667 return E_NOINTERFACE;
4670 static ULONG WINAPI result_async_handler_AddRef( IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult *iface )
4672 return 2;
4675 static ULONG WINAPI result_async_handler_Release( IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult *iface )
4677 return 1;
4680 static HRESULT WINAPI result_async_handler_Invoke( IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult *iface,
4681 IAsyncOperation_ForceFeedbackLoadEffectResult *async, AsyncStatus status )
4683 struct result_async_handler *impl = impl_from_IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult( iface );
4685 trace( "iface %p, async %p, status %u\n", iface, async, status );
4687 ok( !impl->invoked, "invoked twice\n" );
4688 impl->invoked = TRUE;
4689 impl->async = async;
4690 impl->status = status;
4691 if (impl->event) SetEvent( impl->event );
4693 return S_OK;
4696 static IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResultVtbl result_async_handler_vtbl =
4698 /*** IUnknown methods ***/
4699 result_async_handler_QueryInterface,
4700 result_async_handler_AddRef,
4701 result_async_handler_Release,
4702 /*** IAsyncOperationCompletedHandler<ForceFeedbackLoadEffectResult> methods ***/
4703 result_async_handler_Invoke,
4706 static struct result_async_handler default_result_async_handler = {{&result_async_handler_vtbl}};
4708 static void test_windows_gaming_input(void)
4710 #include "psh_hid_macros.h"
4711 const unsigned char report_desc[] =
4713 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
4714 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4715 COLLECTION(1, Application),
4716 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4717 COLLECTION(1, Physical),
4718 REPORT_ID(1, 1),
4720 USAGE(1, HID_USAGE_GENERIC_X),
4721 USAGE(1, HID_USAGE_GENERIC_Y),
4722 USAGE(1, HID_USAGE_GENERIC_Z),
4723 LOGICAL_MINIMUM(1, 0),
4724 LOGICAL_MAXIMUM(1, 127),
4725 PHYSICAL_MINIMUM(1, 0),
4726 PHYSICAL_MAXIMUM(1, 127),
4727 REPORT_SIZE(1, 8),
4728 REPORT_COUNT(1, 3),
4729 INPUT(1, Data|Var|Abs),
4731 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
4732 LOGICAL_MINIMUM(1, 1),
4733 LOGICAL_MAXIMUM(1, 8),
4734 PHYSICAL_MINIMUM(1, 0),
4735 PHYSICAL_MAXIMUM(1, 8),
4736 REPORT_SIZE(1, 8),
4737 REPORT_COUNT(1, 1),
4738 INPUT(1, Data|Var|Abs|Null),
4740 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
4741 USAGE_MINIMUM(1, 1),
4742 USAGE_MAXIMUM(1, 5),
4743 LOGICAL_MINIMUM(1, 0),
4744 LOGICAL_MAXIMUM(1, 1),
4745 PHYSICAL_MINIMUM(1, 0),
4746 PHYSICAL_MAXIMUM(1, 1),
4747 REPORT_SIZE(1, 1),
4748 REPORT_COUNT(1, 8),
4749 INPUT(1, Data|Var|Abs),
4750 END_COLLECTION,
4752 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
4753 USAGE(1, PID_USAGE_STATE_REPORT),
4754 COLLECTION(1, Report),
4755 REPORT_ID(1, 2),
4757 USAGE(1, PID_USAGE_DEVICE_PAUSED),
4758 USAGE(1, PID_USAGE_ACTUATORS_ENABLED),
4759 USAGE(1, PID_USAGE_SAFETY_SWITCH),
4760 USAGE(1, PID_USAGE_ACTUATOR_OVERRIDE_SWITCH),
4761 USAGE(1, PID_USAGE_ACTUATOR_POWER),
4762 LOGICAL_MINIMUM(1, 0),
4763 LOGICAL_MAXIMUM(1, 1),
4764 PHYSICAL_MINIMUM(1, 0),
4765 PHYSICAL_MAXIMUM(1, 1),
4766 REPORT_SIZE(1, 1),
4767 REPORT_COUNT(1, 5),
4768 INPUT(1, Data|Var|Abs),
4769 REPORT_COUNT(1, 3),
4770 INPUT(1, Cnst|Var|Abs),
4772 USAGE(1, PID_USAGE_EFFECT_PLAYING),
4773 LOGICAL_MINIMUM(1, 0),
4774 LOGICAL_MAXIMUM(1, 1),
4775 PHYSICAL_MINIMUM(1, 0),
4776 PHYSICAL_MAXIMUM(1, 1),
4777 REPORT_SIZE(1, 1),
4778 REPORT_COUNT(1, 8),
4779 INPUT(1, Data|Var|Abs),
4781 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
4782 LOGICAL_MINIMUM(1, 1),
4783 LOGICAL_MAXIMUM(1, 0x7f),
4784 PHYSICAL_MINIMUM(1, 1),
4785 PHYSICAL_MAXIMUM(1, 0x7f),
4786 REPORT_SIZE(1, 8),
4787 REPORT_COUNT(1, 1),
4788 INPUT(1, Data|Var|Abs),
4789 END_COLLECTION,
4791 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
4792 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
4793 COLLECTION(1, Report),
4794 REPORT_ID(1, 1),
4796 USAGE(1, PID_USAGE_DEVICE_CONTROL),
4797 COLLECTION(1, Logical),
4798 USAGE(1, PID_USAGE_DC_DEVICE_RESET),
4799 USAGE(1, PID_USAGE_DC_DEVICE_PAUSE),
4800 USAGE(1, PID_USAGE_DC_DEVICE_CONTINUE),
4801 USAGE(1, PID_USAGE_DC_ENABLE_ACTUATORS),
4802 USAGE(1, PID_USAGE_DC_DISABLE_ACTUATORS),
4803 USAGE(1, PID_USAGE_DC_STOP_ALL_EFFECTS),
4804 LOGICAL_MINIMUM(1, 1),
4805 LOGICAL_MAXIMUM(1, 6),
4806 PHYSICAL_MINIMUM(1, 1),
4807 PHYSICAL_MAXIMUM(1, 6),
4808 REPORT_SIZE(1, 8),
4809 REPORT_COUNT(1, 1),
4810 OUTPUT(1, Data|Ary|Abs),
4811 END_COLLECTION,
4812 END_COLLECTION,
4814 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT),
4815 COLLECTION(1, Report),
4816 REPORT_ID(1, 2),
4818 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
4819 LOGICAL_MINIMUM(1, 1),
4820 LOGICAL_MAXIMUM(1, 0x7f),
4821 PHYSICAL_MINIMUM(1, 1),
4822 PHYSICAL_MAXIMUM(1, 0x7f),
4823 REPORT_SIZE(1, 8),
4824 REPORT_COUNT(1, 1),
4825 OUTPUT(1, Data|Var|Abs),
4827 USAGE(1, PID_USAGE_EFFECT_OPERATION),
4828 COLLECTION(1, NamedArray),
4829 USAGE(1, PID_USAGE_OP_EFFECT_START),
4830 USAGE(1, PID_USAGE_OP_EFFECT_START_SOLO),
4831 USAGE(1, PID_USAGE_OP_EFFECT_STOP),
4832 LOGICAL_MINIMUM(1, 1),
4833 LOGICAL_MAXIMUM(1, 3),
4834 PHYSICAL_MINIMUM(1, 1),
4835 PHYSICAL_MAXIMUM(1, 3),
4836 REPORT_SIZE(1, 8),
4837 REPORT_COUNT(1, 1),
4838 OUTPUT(1, Data|Ary|Abs),
4839 END_COLLECTION,
4841 USAGE(1, PID_USAGE_LOOP_COUNT),
4842 LOGICAL_MINIMUM(1, 0),
4843 LOGICAL_MAXIMUM(1, 0x7f),
4844 PHYSICAL_MINIMUM(1, 0),
4845 PHYSICAL_MAXIMUM(1, 0x7f),
4846 REPORT_SIZE(1, 8),
4847 REPORT_COUNT(1, 1),
4848 OUTPUT(1, Data|Var|Abs),
4849 END_COLLECTION,
4851 USAGE(1, PID_USAGE_SET_EFFECT_REPORT),
4852 COLLECTION(1, Report),
4853 REPORT_ID(1, 3),
4855 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
4856 LOGICAL_MINIMUM(1, 1),
4857 LOGICAL_MAXIMUM(1, 0x7f),
4858 PHYSICAL_MINIMUM(1, 1),
4859 PHYSICAL_MAXIMUM(1, 0x7f),
4860 REPORT_SIZE(1, 8),
4861 REPORT_COUNT(1, 1),
4862 OUTPUT(1, Data|Var|Abs),
4864 USAGE(1, PID_USAGE_EFFECT_TYPE),
4865 COLLECTION(1, NamedArray),
4866 USAGE(1, PID_USAGE_ET_SQUARE),
4867 USAGE(1, PID_USAGE_ET_SINE),
4868 USAGE(1, PID_USAGE_ET_SPRING),
4869 USAGE(1, PID_USAGE_ET_CONSTANT_FORCE),
4870 USAGE(1, PID_USAGE_ET_RAMP),
4871 LOGICAL_MINIMUM(1, 1),
4872 LOGICAL_MAXIMUM(1, 5),
4873 PHYSICAL_MINIMUM(1, 1),
4874 PHYSICAL_MAXIMUM(1, 5),
4875 REPORT_SIZE(1, 8),
4876 REPORT_COUNT(1, 1),
4877 OUTPUT(1, Data|Ary|Abs),
4878 END_COLLECTION,
4880 USAGE(1, PID_USAGE_AXES_ENABLE),
4881 COLLECTION(1, Logical),
4882 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_X),
4883 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Y),
4884 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Z),
4885 LOGICAL_MINIMUM(1, 0),
4886 LOGICAL_MAXIMUM(1, 1),
4887 PHYSICAL_MINIMUM(1, 0),
4888 PHYSICAL_MAXIMUM(1, 1),
4889 REPORT_SIZE(1, 1),
4890 REPORT_COUNT(1, 3),
4891 OUTPUT(1, Data|Var|Abs),
4892 END_COLLECTION,
4893 USAGE(1, PID_USAGE_DIRECTION_ENABLE),
4894 REPORT_COUNT(1, 1),
4895 OUTPUT(1, Data|Var|Abs),
4896 REPORT_COUNT(1, 4),
4897 OUTPUT(1, Cnst|Var|Abs),
4899 USAGE(1, PID_USAGE_DURATION),
4900 USAGE(1, PID_USAGE_TRIGGER_REPEAT_INTERVAL),
4901 USAGE(1, PID_USAGE_SAMPLE_PERIOD),
4902 USAGE(1, PID_USAGE_START_DELAY),
4903 UNIT(2, 0x1003), /* Eng Lin:Time */
4904 UNIT_EXPONENT(1, -3), /* 10^-3 */
4905 LOGICAL_MINIMUM(1, 0),
4906 LOGICAL_MAXIMUM(2, 0x7fff),
4907 PHYSICAL_MINIMUM(1, 0),
4908 PHYSICAL_MAXIMUM(2, 0x7fff),
4909 REPORT_SIZE(1, 16),
4910 REPORT_COUNT(1, 4),
4911 OUTPUT(1, Data|Var|Abs),
4912 UNIT(1, 0),
4913 UNIT_EXPONENT(1, 0),
4915 USAGE(1, PID_USAGE_TRIGGER_BUTTON),
4916 LOGICAL_MINIMUM(1, 1),
4917 LOGICAL_MAXIMUM(1, 0x08),
4918 PHYSICAL_MINIMUM(1, 1),
4919 PHYSICAL_MAXIMUM(1, 0x08),
4920 REPORT_SIZE(1, 8),
4921 REPORT_COUNT(1, 1),
4922 OUTPUT(1, Data|Var|Abs),
4924 USAGE(1, PID_USAGE_GAIN),
4925 LOGICAL_MINIMUM(1, 0),
4926 LOGICAL_MAXIMUM(2, 0x00ff),
4927 PHYSICAL_MINIMUM(1, 0),
4928 PHYSICAL_MAXIMUM(2, 0x2710),
4929 REPORT_SIZE(1, 8),
4930 REPORT_COUNT(1, 1),
4931 OUTPUT(1, Data|Var|Abs),
4933 USAGE(1, PID_USAGE_DIRECTION),
4934 COLLECTION(1, Logical),
4935 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
4936 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
4937 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
4938 UNIT_EXPONENT(1, -2), /* 10^-2 */
4939 LOGICAL_MINIMUM(1, 0),
4940 LOGICAL_MAXIMUM(4, 360),
4941 PHYSICAL_MINIMUM(1, 0),
4942 PHYSICAL_MAXIMUM(4, 36000),
4943 UNIT(1, 0),
4944 REPORT_SIZE(1, 16),
4945 REPORT_COUNT(1, 2),
4946 OUTPUT(1, Data|Var|Abs),
4947 UNIT_EXPONENT(1, 0),
4948 UNIT(1, 0),
4949 END_COLLECTION,
4950 END_COLLECTION,
4952 USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
4953 COLLECTION(1, Logical),
4954 REPORT_ID(1, 4),
4956 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
4957 LOGICAL_MINIMUM(1, 1),
4958 LOGICAL_MAXIMUM(1, 0x7f),
4959 PHYSICAL_MINIMUM(1, 1),
4960 PHYSICAL_MAXIMUM(1, 0x7f),
4961 REPORT_SIZE(1, 8),
4962 REPORT_COUNT(1, 1),
4963 OUTPUT(1, Data|Var|Abs),
4965 USAGE(1, PID_USAGE_PARAMETER_BLOCK_OFFSET),
4966 LOGICAL_MINIMUM(1, 0),
4967 LOGICAL_MAXIMUM(1, 1),
4968 PHYSICAL_MINIMUM(1, 0),
4969 PHYSICAL_MAXIMUM(1, 1),
4970 REPORT_SIZE(1, 4),
4971 REPORT_COUNT(1, 1),
4972 OUTPUT(1, Data|Var|Abs),
4974 USAGE(1, PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET),
4975 COLLECTION(1, Logical),
4976 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
4977 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
4978 LOGICAL_MINIMUM(1, 0),
4979 LOGICAL_MAXIMUM(1, 1),
4980 PHYSICAL_MINIMUM(1, 0),
4981 PHYSICAL_MAXIMUM(1, 1),
4982 REPORT_SIZE(1, 2),
4983 REPORT_COUNT(1, 2),
4984 OUTPUT(1, Data|Var|Abs),
4985 END_COLLECTION,
4987 USAGE(1, PID_USAGE_CP_OFFSET),
4988 LOGICAL_MINIMUM(2, -10000),
4989 LOGICAL_MAXIMUM(2, +10000),
4990 PHYSICAL_MINIMUM(2, -10000),
4991 PHYSICAL_MAXIMUM(2, +10000),
4992 REPORT_SIZE(1, 16),
4993 REPORT_COUNT(1, 1),
4994 OUTPUT(1, Data|Var|Abs),
4996 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
4997 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
4998 LOGICAL_MINIMUM(2, -10000),
4999 LOGICAL_MAXIMUM(2, +10000),
5000 PHYSICAL_MINIMUM(2, -10000),
5001 PHYSICAL_MAXIMUM(2, +10000),
5002 REPORT_SIZE(1, 16),
5003 REPORT_COUNT(1, 2),
5004 OUTPUT(1, Data|Var|Abs),
5006 USAGE(1, PID_USAGE_POSITIVE_SATURATION),
5007 USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
5008 LOGICAL_MINIMUM(1, 0),
5009 LOGICAL_MAXIMUM(2, 0x00ff),
5010 PHYSICAL_MINIMUM(1, 0),
5011 PHYSICAL_MAXIMUM(2, 10000),
5012 REPORT_SIZE(1, 8),
5013 REPORT_COUNT(1, 2),
5014 OUTPUT(1, Data|Var|Abs),
5016 USAGE(1, PID_USAGE_DEAD_BAND),
5017 LOGICAL_MINIMUM(1, 0),
5018 LOGICAL_MAXIMUM(2, 0x00ff),
5019 PHYSICAL_MINIMUM(1, 0),
5020 PHYSICAL_MAXIMUM(2, 10000),
5021 REPORT_SIZE(1, 8),
5022 REPORT_COUNT(1, 1),
5023 OUTPUT(1, Data|Var|Abs),
5024 END_COLLECTION,
5026 USAGE(1, PID_USAGE_BLOCK_FREE_REPORT),
5027 COLLECTION(1, Logical),
5028 REPORT_ID(1, 5),
5030 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5031 LOGICAL_MINIMUM(1, 1),
5032 LOGICAL_MAXIMUM(1, 0x7f),
5033 PHYSICAL_MINIMUM(1, 1),
5034 PHYSICAL_MAXIMUM(1, 0x7f),
5035 REPORT_SIZE(1, 8),
5036 REPORT_COUNT(1, 1),
5037 OUTPUT(1, Data|Var|Abs),
5038 END_COLLECTION,
5040 USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT),
5041 COLLECTION(1, Logical),
5042 REPORT_ID(1, 6),
5044 USAGE(1, PID_USAGE_DEVICE_GAIN),
5045 LOGICAL_MINIMUM(1, 0),
5046 LOGICAL_MAXIMUM(2, 0x00ff),
5047 PHYSICAL_MINIMUM(1, 0),
5048 PHYSICAL_MAXIMUM(2, 0x2710),
5049 REPORT_SIZE(1, 8),
5050 REPORT_COUNT(1, 1),
5051 OUTPUT(1, Data|Var|Abs),
5052 END_COLLECTION,
5054 USAGE(1, PID_USAGE_SET_PERIODIC_REPORT),
5055 COLLECTION(1, Logical),
5056 REPORT_ID(1, 7),
5058 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5059 LOGICAL_MINIMUM(1, 1),
5060 LOGICAL_MAXIMUM(1, 0x7f),
5061 PHYSICAL_MINIMUM(1, 1),
5062 PHYSICAL_MAXIMUM(1, 0x7f),
5063 REPORT_SIZE(1, 8),
5064 REPORT_COUNT(1, 1),
5065 OUTPUT(1, Data|Var|Abs),
5067 USAGE(1, PID_USAGE_MAGNITUDE),
5068 LOGICAL_MINIMUM(1, 0),
5069 LOGICAL_MAXIMUM(2, 10000),
5070 PHYSICAL_MINIMUM(1, 0),
5071 PHYSICAL_MAXIMUM(2, 10000),
5072 REPORT_SIZE(1, 16),
5073 REPORT_COUNT(1, 1),
5074 OUTPUT(1, Data|Var|Abs),
5076 USAGE(1, PID_USAGE_OFFSET),
5077 LOGICAL_MINIMUM(2, -10000),
5078 LOGICAL_MAXIMUM(2, +10000),
5079 PHYSICAL_MINIMUM(2, -10000),
5080 PHYSICAL_MAXIMUM(2, +10000),
5081 REPORT_SIZE(1, 16),
5082 REPORT_COUNT(1, 1),
5083 OUTPUT(1, Data|Var|Abs),
5085 USAGE(1, PID_USAGE_PHASE),
5086 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
5087 UNIT_EXPONENT(1, -2),
5088 LOGICAL_MINIMUM(2, -180),
5089 LOGICAL_MAXIMUM(2, +180),
5090 PHYSICAL_MINIMUM(2, -18000),
5091 PHYSICAL_MAXIMUM(2, +18000),
5092 REPORT_SIZE(1, 16),
5093 REPORT_COUNT(1, 1),
5094 OUTPUT(1, Data|Var|Abs),
5096 USAGE(1, PID_USAGE_PERIOD),
5097 UNIT(2, 0x1003), /* Eng Lin:Time */
5098 UNIT_EXPONENT(1, -3), /* 10^-3 */
5099 LOGICAL_MINIMUM(1, 0),
5100 LOGICAL_MAXIMUM(2, 0x7fff),
5101 PHYSICAL_MINIMUM(1, 0),
5102 PHYSICAL_MAXIMUM(2, 0x7fff),
5103 REPORT_SIZE(1, 16),
5104 REPORT_COUNT(1, 1),
5105 OUTPUT(1, Data|Var|Abs),
5107 UNIT_EXPONENT(1, 0),
5108 UNIT(1, 0), /* None */
5109 END_COLLECTION,
5111 USAGE(1, PID_USAGE_SET_ENVELOPE_REPORT),
5112 COLLECTION(1, Logical),
5113 REPORT_ID(1, 8),
5115 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5116 LOGICAL_MINIMUM(1, 1),
5117 LOGICAL_MAXIMUM(1, 0x7f),
5118 PHYSICAL_MINIMUM(1, 1),
5119 PHYSICAL_MAXIMUM(1, 0x7f),
5120 REPORT_SIZE(1, 8),
5121 REPORT_COUNT(1, 1),
5122 OUTPUT(1, Data|Var|Abs),
5124 USAGE(1, PID_USAGE_ATTACK_LEVEL),
5125 USAGE(1, PID_USAGE_FADE_LEVEL),
5126 LOGICAL_MINIMUM(1, 0),
5127 LOGICAL_MAXIMUM(2, 0x00ff),
5128 PHYSICAL_MINIMUM(1, 0),
5129 PHYSICAL_MAXIMUM(2, 0x2710),
5130 REPORT_SIZE(1, 8),
5131 REPORT_COUNT(1, 2),
5132 OUTPUT(1, Data|Var|Abs),
5134 USAGE(1, PID_USAGE_ATTACK_TIME),
5135 USAGE(1, PID_USAGE_FADE_TIME),
5136 UNIT(2, 0x1003), /* Eng Lin:Time */
5137 UNIT_EXPONENT(1, -3), /* 10^-3 */
5138 LOGICAL_MINIMUM(1, 0),
5139 LOGICAL_MAXIMUM(2, 0x7fff),
5140 PHYSICAL_MINIMUM(1, 0),
5141 PHYSICAL_MAXIMUM(2, 0x7fff),
5142 REPORT_SIZE(1, 16),
5143 REPORT_COUNT(1, 2),
5144 OUTPUT(1, Data|Var|Abs),
5145 UNIT_EXPONENT(1, 0),
5146 UNIT(1, 0),
5147 END_COLLECTION,
5149 USAGE(1, PID_USAGE_SET_CONSTANT_FORCE_REPORT),
5150 COLLECTION(1, Logical),
5151 REPORT_ID(1, 9),
5153 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5154 LOGICAL_MINIMUM(1, 1),
5155 LOGICAL_MAXIMUM(1, 0x7f),
5156 PHYSICAL_MINIMUM(1, 1),
5157 PHYSICAL_MAXIMUM(1, 0x7f),
5158 REPORT_SIZE(1, 8),
5159 REPORT_COUNT(1, 1),
5160 OUTPUT(1, Data|Var|Abs),
5162 USAGE(1, PID_USAGE_MAGNITUDE),
5163 LOGICAL_MINIMUM(2, -10000),
5164 LOGICAL_MAXIMUM(2, +10000),
5165 PHYSICAL_MINIMUM(2, -10000),
5166 PHYSICAL_MAXIMUM(2, +10000),
5167 REPORT_SIZE(1, 16),
5168 REPORT_COUNT(1, 1),
5169 OUTPUT(1, Data|Var|Abs),
5170 END_COLLECTION,
5172 USAGE(1, PID_USAGE_SET_RAMP_FORCE_REPORT),
5173 COLLECTION(1, Logical),
5174 REPORT_ID(1, 10),
5176 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5177 LOGICAL_MINIMUM(1, 1),
5178 LOGICAL_MAXIMUM(1, 0x7f),
5179 PHYSICAL_MINIMUM(1, 1),
5180 PHYSICAL_MAXIMUM(1, 0x7f),
5181 REPORT_SIZE(1, 8),
5182 REPORT_COUNT(1, 1),
5183 OUTPUT(1, Data|Var|Abs),
5185 USAGE(1, PID_USAGE_RAMP_START),
5186 USAGE(1, PID_USAGE_RAMP_END),
5187 LOGICAL_MINIMUM(2, -10000),
5188 LOGICAL_MAXIMUM(2, +10000),
5189 PHYSICAL_MINIMUM(2, -10000),
5190 PHYSICAL_MAXIMUM(2, +10000),
5191 REPORT_SIZE(1, 16),
5192 REPORT_COUNT(1, 2),
5193 OUTPUT(1, Data|Var|Abs),
5194 END_COLLECTION,
5196 USAGE(1, PID_USAGE_POOL_REPORT),
5197 COLLECTION(1, Logical),
5198 REPORT_ID(1, 1),
5200 USAGE(1, PID_USAGE_RAM_POOL_SIZE),
5201 LOGICAL_MINIMUM(1, 0),
5202 LOGICAL_MAXIMUM(4, 0xffff),
5203 PHYSICAL_MINIMUM(1, 0),
5204 PHYSICAL_MAXIMUM(4, 0xffff),
5205 REPORT_SIZE(1, 16),
5206 REPORT_COUNT(1, 1),
5207 FEATURE(1, Data|Var|Abs),
5209 USAGE(1, PID_USAGE_SIMULTANEOUS_EFFECTS_MAX),
5210 LOGICAL_MINIMUM(1, 0),
5211 LOGICAL_MAXIMUM(1, 0x7f),
5212 PHYSICAL_MINIMUM(1, 0),
5213 PHYSICAL_MAXIMUM(1, 0x7f),
5214 REPORT_SIZE(1, 8),
5215 REPORT_COUNT(1, 1),
5216 FEATURE(1, Data|Var|Abs),
5218 USAGE(1, PID_USAGE_DEVICE_MANAGED_POOL),
5219 USAGE(1, PID_USAGE_SHARED_PARAMETER_BLOCKS),
5220 LOGICAL_MINIMUM(1, 0),
5221 LOGICAL_MAXIMUM(1, 1),
5222 PHYSICAL_MINIMUM(1, 0),
5223 PHYSICAL_MAXIMUM(1, 1),
5224 REPORT_SIZE(1, 1),
5225 REPORT_COUNT(1, 8),
5226 FEATURE(1, Data|Var|Abs),
5227 END_COLLECTION,
5229 USAGE(1, PID_USAGE_CREATE_NEW_EFFECT_REPORT),
5230 COLLECTION(1, Logical),
5231 REPORT_ID(1, 2),
5233 USAGE(1, PID_USAGE_EFFECT_TYPE),
5234 COLLECTION(1, NamedArray),
5235 USAGE(1, PID_USAGE_ET_SQUARE),
5236 USAGE(1, PID_USAGE_ET_SINE),
5237 USAGE(1, PID_USAGE_ET_SPRING),
5238 USAGE(1, PID_USAGE_ET_CONSTANT_FORCE),
5239 USAGE(1, PID_USAGE_ET_RAMP),
5240 LOGICAL_MINIMUM(1, 1),
5241 LOGICAL_MAXIMUM(1, 5),
5242 PHYSICAL_MINIMUM(1, 1),
5243 PHYSICAL_MAXIMUM(1, 5),
5244 REPORT_SIZE(1, 8),
5245 REPORT_COUNT(1, 1),
5246 FEATURE(1, Data|Ary|Abs),
5247 END_COLLECTION,
5249 USAGE(4, (HID_USAGE_PAGE_GENERIC<<16)|HID_USAGE_GENERIC_BYTE_COUNT),
5250 LOGICAL_MINIMUM(1, 0x7f),
5251 LOGICAL_MAXIMUM(1, 0x7f),
5252 PHYSICAL_MINIMUM(1, 0x7f),
5253 PHYSICAL_MAXIMUM(1, 0x7f),
5254 REPORT_SIZE(1, 8),
5255 REPORT_COUNT(1, 1),
5256 FEATURE(1, Data|Ary|Abs),
5257 END_COLLECTION,
5259 USAGE(1, PID_USAGE_BLOCK_LOAD_REPORT),
5260 COLLECTION(1, Logical),
5261 REPORT_ID(1, 3),
5263 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
5264 LOGICAL_MINIMUM(1, 1),
5265 LOGICAL_MAXIMUM(1, 0x7f),
5266 PHYSICAL_MINIMUM(1, 1),
5267 PHYSICAL_MAXIMUM(1, 0x7f),
5268 REPORT_SIZE(1, 8),
5269 REPORT_COUNT(1, 1),
5270 FEATURE(1, Data|Var|Abs),
5272 USAGE(1, PID_USAGE_BLOCK_LOAD_STATUS),
5273 COLLECTION(1, NamedArray),
5274 USAGE(1, PID_USAGE_BLOCK_LOAD_SUCCESS),
5275 USAGE(1, PID_USAGE_BLOCK_LOAD_FULL),
5276 USAGE(1, PID_USAGE_BLOCK_LOAD_ERROR),
5277 LOGICAL_MINIMUM(1, 1),
5278 LOGICAL_MAXIMUM(1, 3),
5279 PHYSICAL_MINIMUM(1, 1),
5280 PHYSICAL_MAXIMUM(1, 3),
5281 REPORT_SIZE(1, 8),
5282 REPORT_COUNT(1, 1),
5283 FEATURE(1, Data|Ary|Abs),
5284 END_COLLECTION,
5286 USAGE(1, PID_USAGE_RAM_POOL_AVAILABLE),
5287 LOGICAL_MINIMUM(1, 0),
5288 LOGICAL_MAXIMUM(4, 0xffff),
5289 PHYSICAL_MINIMUM(1, 0),
5290 PHYSICAL_MAXIMUM(4, 0xffff),
5291 REPORT_SIZE(1, 16),
5292 REPORT_COUNT(1, 1),
5293 FEATURE(1, Data|Var|Abs),
5294 END_COLLECTION,
5295 END_COLLECTION,
5297 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
5298 #include "pop_hid_macros.h"
5300 struct hid_device_desc desc =
5302 .use_report_id = TRUE,
5303 .caps =
5305 .InputReportByteLength = 6,
5306 .OutputReportByteLength = 18,
5307 .FeatureReportByteLength = 5,
5309 .attributes = default_attributes,
5311 struct hid_expect expect_init[] =
5313 /* device pool */
5315 .code = IOCTL_HID_GET_FEATURE,
5316 .report_id = 1,
5317 .report_len = 5,
5318 .report_buf = {1,0xff,0x7f,0x7f,0x03},
5319 .todo = TRUE,
5322 struct hid_expect expect_acquire[] =
5324 /* device pool */
5326 .code = IOCTL_HID_GET_FEATURE,
5327 .report_id = 1,
5328 .report_len = 5,
5329 .report_buf = {1,0xff,0x7f,0x7f,0x03},
5330 .todo = TRUE,
5332 /* device control */
5334 .code = IOCTL_HID_WRITE_REPORT,
5335 .report_id = 1,
5336 .report_len = 2,
5337 .report_buf = {1, 0x06},
5338 .todo = TRUE,
5340 /* device control */
5342 .code = IOCTL_HID_WRITE_REPORT,
5343 .report_id = 1,
5344 .report_len = 2,
5345 .report_buf = {1, 0x05},
5346 .todo = TRUE,
5348 /* device control */
5350 .code = IOCTL_HID_WRITE_REPORT,
5351 .report_id = 1,
5352 .report_len = 2,
5353 .report_buf = {1, 0x01},
5355 /* device gain */
5357 .code = IOCTL_HID_WRITE_REPORT,
5358 .report_id = 6,
5359 .report_len = 2,
5360 .report_buf = {6, 0xff},
5363 static struct hid_expect expect_set_gain =
5365 .code = IOCTL_HID_WRITE_REPORT,
5366 .report_id = 6,
5367 .report_len = 2,
5368 .report_buf = {6, 0x7f},
5370 static struct hid_expect expect_pause =
5372 .code = IOCTL_HID_WRITE_REPORT,
5373 .report_id = 1,
5374 .report_len = 2,
5375 .report_buf = {1, 0x02},
5377 static struct hid_expect expect_resume =
5379 .code = IOCTL_HID_WRITE_REPORT,
5380 .report_id = 1,
5381 .report_len = 2,
5382 .report_buf = {1, 0x03},
5384 static struct hid_expect expect_stop =
5386 .code = IOCTL_HID_WRITE_REPORT,
5387 .report_id = 1,
5388 .report_len = 2,
5389 .report_buf = {1, 0x06},
5391 static struct hid_expect expect_disable =
5393 .code = IOCTL_HID_WRITE_REPORT,
5394 .report_id = 1,
5395 .report_len = 2,
5396 .report_buf = {1, 0x05},
5398 static struct hid_expect expect_enable =
5400 .code = IOCTL_HID_WRITE_REPORT,
5401 .report_id = 1,
5402 .report_len = 2,
5403 .report_buf = {1, 0x04},
5405 static struct hid_expect expect_enable_fail =
5407 .code = IOCTL_HID_WRITE_REPORT,
5408 .ret_status = STATUS_NOT_SUPPORTED,
5409 .report_id = 1,
5410 .report_len = 2,
5411 .report_buf = {1, 0x04},
5413 static struct hid_expect expect_reset_delay[] =
5415 /* device control */
5417 .code = IOCTL_HID_WRITE_REPORT,
5418 .ret_status = STATUS_PENDING,
5419 .report_id = 1,
5420 .report_len = 2,
5421 .report_buf = {1, 0x01},
5423 /* device gain */
5425 .code = IOCTL_HID_WRITE_REPORT,
5426 .report_id = 6,
5427 .report_len = 2,
5428 .report_buf = {6, 0x7f},
5431 struct hid_expect expect_reset[] =
5433 /* device control */
5435 .code = IOCTL_HID_WRITE_REPORT,
5436 .report_id = 1,
5437 .report_len = 2,
5438 .report_buf = {1, 0x01},
5440 /* device gain */
5442 .code = IOCTL_HID_WRITE_REPORT,
5443 .report_id = 6,
5444 .report_len = 2,
5445 .report_buf = {6, 0x7f},
5448 struct hid_expect expect_create_periodic[] =
5450 /* create new effect */
5452 .code = IOCTL_HID_SET_FEATURE,
5453 .report_id = 2,
5454 .report_len = 3,
5455 .report_buf = {2,0x02,0x00},
5457 /* block load */
5459 .code = IOCTL_HID_GET_FEATURE,
5460 .report_id = 3,
5461 .report_len = 5,
5462 .report_buf = {3,0x01,0x01,0x00,0x00},
5464 /* set periodic */
5466 .code = IOCTL_HID_WRITE_REPORT,
5467 .report_id = 7,
5468 .report_len = 10,
5469 .report_buf = {7,0x01,0xa0,0x0f,0xd0,0x07,0x70,0xff,0x0a,0x00},
5471 /* set envelope */
5473 .code = IOCTL_HID_WRITE_REPORT,
5474 .report_id = 8,
5475 .report_len = 8,
5476 .report_buf = {8,0x01,0x4c,0x7f,0x28,0x00,0x50,0x00},
5478 /* update effect */
5480 .code = IOCTL_HID_WRITE_REPORT,
5481 .report_id = 3,
5482 .report_len = 18,
5483 .report_buf = {3,0x01,0x02,0x08,0x78,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0xff,0xff,0x4e,0x01,0x00,0x00},
5486 struct hid_expect expect_create_condition[] =
5488 /* create new effect */
5490 .code = IOCTL_HID_SET_FEATURE,
5491 .report_id = 2,
5492 .report_len = 3,
5493 .report_buf = {2,0x03,0x00},
5495 /* block load */
5497 .code = IOCTL_HID_GET_FEATURE,
5498 .report_id = 3,
5499 .report_len = 5,
5500 .report_buf = {3,0x01,0x01,0x00,0x00},
5502 /* set condition */
5504 .code = IOCTL_HID_WRITE_REPORT,
5505 .report_id = 4,
5506 .report_len = 12,
5507 .report_buf = {4,0x01,0x00,0x70,0x17,0x7b,0x02,0xe9,0x04,0x4c,0x66,0x7f},
5509 /* update effect */
5511 .code = IOCTL_HID_WRITE_REPORT,
5512 .report_id = 3,
5513 .report_len = 18,
5514 .report_buf = {3,0x01,0x03,0x08,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x00,0x00,0x00},
5517 struct hid_expect expect_create_constant[] =
5519 /* create new effect */
5521 .code = IOCTL_HID_SET_FEATURE,
5522 .report_id = 2,
5523 .report_len = 3,
5524 .report_buf = {2,0x04,0x00},
5526 /* block load */
5528 .code = IOCTL_HID_GET_FEATURE,
5529 .report_id = 3,
5530 .report_len = 5,
5531 .report_buf = {3,0x01,0x01,0x00,0x00},
5533 /* set constant */
5535 .code = IOCTL_HID_WRITE_REPORT,
5536 .report_id = 9,
5537 .report_len = 4,
5538 .report_buf = {9,0x01,0xc8,0x00},
5540 /* set envelope */
5542 .code = IOCTL_HID_WRITE_REPORT,
5543 .report_id = 8,
5544 .report_len = 8,
5545 .report_buf = {8,0x01,0x19,0x4c,0x14,0x00,0x3c,0x00},
5547 /* update effect */
5549 .code = IOCTL_HID_WRITE_REPORT,
5550 .report_id = 3,
5551 .report_len = 18,
5552 .report_buf = {3,0x01,0x04,0x08,0x5a,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0xff,0x7f,0x4e,0x01,0x00,0x00},
5555 struct hid_expect expect_create_ramp[] =
5557 /* create new effect */
5559 .code = IOCTL_HID_SET_FEATURE,
5560 .report_id = 2,
5561 .report_len = 3,
5562 .report_buf = {2,0x05,0x00},
5564 /* block load */
5566 .code = IOCTL_HID_GET_FEATURE,
5567 .report_id = 3,
5568 .report_len = 5,
5569 .report_buf = {3,0x01,0x01,0x00,0x00},
5571 /* set ramp */
5573 .code = IOCTL_HID_WRITE_REPORT,
5574 .report_id = 10,
5575 .report_len = 6,
5576 .report_buf = {10,0x01,0xc8,0x00,0x20,0x03},
5578 /* set envelope */
5580 .code = IOCTL_HID_WRITE_REPORT,
5581 .report_id = 8,
5582 .report_len = 8,
5583 .report_buf = {8,0x01,0x19,0x4c,0x14,0x00,0x3c,0x00},
5585 /* update effect */
5587 .code = IOCTL_HID_WRITE_REPORT,
5588 .report_id = 3,
5589 .report_len = 18,
5590 .report_buf = {3,0x01,0x05,0x08,0x5a,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0xff,0xff,0x4e,0x01,0x00,0x00},
5593 struct hid_expect expect_effect_start =
5595 .code = IOCTL_HID_WRITE_REPORT,
5596 .report_id = 2,
5597 .report_len = 4,
5598 .report_buf = {2,0x01,0x01,0x01},
5599 .todo = TRUE,
5601 struct hid_expect expect_effect_stop =
5603 .code = IOCTL_HID_WRITE_REPORT,
5604 .report_id = 2,
5605 .report_len = 4,
5606 .report_buf = {2,0x01,0x03,0x00},
5607 .todo = TRUE,
5609 struct hid_expect expect_unload[] =
5611 /* effect stop */
5613 .code = IOCTL_HID_WRITE_REPORT,
5614 .report_id = 2,
5615 .report_len = 4,
5616 .report_buf = {2,0x01,0x03,0x00},
5618 /* effect free */
5620 .code = IOCTL_HID_WRITE_REPORT,
5621 .report_id = 5,
5622 .report_len = 2,
5623 .report_buf = {5,0x01},
5626 static const WCHAR *condition_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConditionForceEffect;
5627 static const WCHAR *periodic_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_PeriodicForceEffect;
5628 static const WCHAR *constant_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConstantForceEffect;
5629 static const WCHAR *force_feedback_motor = RuntimeClass_Windows_Gaming_Input_ForceFeedback_ForceFeedbackMotor;
5630 static const WCHAR *ramp_effect_class_name = RuntimeClass_Windows_Gaming_Input_ForceFeedback_RampForceEffect;
5631 static const WCHAR *controller_class_name = RuntimeClass_Windows_Gaming_Input_RawGameController;
5633 DIPROPGUIDANDPATH guid_path =
5635 .diph =
5637 .dwSize = sizeof(DIPROPGUIDANDPATH),
5638 .dwHeaderSize = sizeof(DIPROPHEADER),
5639 .dwHow = DIPH_DEVICE,
5642 TimeSpan delay = {100000}, attack_duration = {200000}, release_duration = {300000}, duration = {400000};
5643 Vector3 direction = {0.1, 0.2, 0.3}, end_direction = {0.4, 0.5, 0.6};
5644 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
5645 IAsyncOperation_ForceFeedbackLoadEffectResult *result_async;
5646 IAsyncOperationCompletedHandler_boolean *tmp_handler;
5647 struct result_async_handler result_async_handler;
5648 IVectorView_RawGameController *controllers_view;
5649 IConditionForceEffectFactory *condition_factory;
5650 IRawGameControllerStatics *controller_statics;
5651 EventRegistrationToken controller_added_token;
5652 IPeriodicForceEffectFactory *periodic_factory;
5653 struct bool_async_handler bool_async_handler;
5654 IVectorView_ForceFeedbackMotor *motors_view;
5655 IConditionForceEffect *condition_effect;
5656 ConditionForceEffectKind condition_kind;
5657 ForceFeedbackEffectAxes supported_axes;
5658 IActivationFactory *activation_factory;
5659 IPeriodicForceEffect *periodic_effect;
5660 IConstantForceEffect *constant_effect;
5661 PeriodicForceEffectKind periodic_kind;
5662 IAsyncOperation_boolean *bool_async;
5663 IRawGameController *raw_controller;
5664 ForceFeedbackEffectState state;
5665 IRampForceEffect *ramp_effect;
5666 IInspectable *tmp_inspectable;
5667 IForceFeedbackEffect *effect;
5668 IDirectInputDevice8W *device;
5669 IForceFeedbackMotor *motor;
5670 BOOLEAN paused, enabled;
5671 IAsyncInfo *async_info;
5672 DOUBLE gain;
5673 HSTRING str;
5674 HANDLE file;
5675 UINT32 size;
5676 HRESULT hr;
5677 DWORD ret;
5678 LONG ref;
5680 if (!load_combase_functions()) return;
5682 cleanup_registry_keys();
5684 hr = pRoInitialize( RO_INIT_MULTITHREADED );
5685 ok( hr == RPC_E_CHANGED_MODE, "RoInitialize returned %#lx\n", hr );
5687 hr = pWindowsCreateString( controller_class_name, wcslen( controller_class_name ), &str );
5688 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5689 hr = pRoGetActivationFactory( str, &IID_IRawGameControllerStatics, (void **)&controller_statics );
5690 ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "RoGetActivationFactory returned %#lx\n", hr );
5691 pWindowsDeleteString( str );
5693 if (hr == REGDB_E_CLASSNOTREG)
5695 win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( controller_class_name ) );
5696 goto done;
5699 controller_added.event = CreateEventW( NULL, FALSE, FALSE, NULL );
5700 ok( !!controller_added.event, "CreateEventW failed, error %lu\n", GetLastError() );
5702 hr = IRawGameControllerStatics_add_RawGameControllerAdded( controller_statics, &controller_added.IEventHandler_RawGameController_iface,
5703 &controller_added_token );
5704 ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
5705 ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
5707 desc.report_descriptor_len = sizeof(report_desc);
5708 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
5709 desc.expect_size = sizeof(expect_init);
5710 memcpy( desc.expect, expect_init, sizeof(expect_init) );
5711 fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
5713 if (!hid_device_start( &desc )) goto done;
5714 WaitForSingleObject( controller_added.event, INFINITE );
5715 CloseHandle( controller_added.event );
5717 if (FAILED(hr = dinput_test_create_device( 0x800, &devinst, &device ))) goto done;
5718 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &guid_path.diph );
5719 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
5720 IDirectInputDevice8_Release( device );
5722 file = CreateFileW( guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
5723 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
5724 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
5725 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
5727 hr = IRawGameControllerStatics_remove_RawGameControllerAdded( controller_statics, controller_added_token );
5728 ok( hr == S_OK, "remove_RawGameControllerAdded returned %#lx\n", hr );
5730 hr = IRawGameControllerStatics_get_RawGameControllers( controller_statics, &controllers_view );
5731 ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
5732 hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
5733 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5734 ok( size == 1, "got size %u\n", size );
5735 hr = IVectorView_RawGameController_GetAt( controllers_view, 0, &raw_controller );
5736 ok( hr == S_OK, "GetAt returned %#lx\n", hr );
5737 IVectorView_RawGameController_Release( controllers_view );
5739 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
5740 hr = IRawGameController_get_ForceFeedbackMotors( raw_controller, &motors_view );
5741 ok( hr == S_OK, "get_ForceFeedbackMotors returned %#lx\n", hr );
5742 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
5744 hr = IVectorView_ForceFeedbackMotor_get_Size( motors_view, &size );
5745 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5746 ok( size == 1, "got size %u\n", size );
5747 hr = IVectorView_ForceFeedbackMotor_GetAt( motors_view, 0, &motor );
5748 ok( hr == S_OK, "GetAt returned %#lx\n", hr );
5749 IVectorView_ForceFeedbackMotor_Release( motors_view );
5751 check_interface( motor, &IID_IUnknown, TRUE );
5752 check_interface( motor, &IID_IInspectable, TRUE );
5753 check_interface( motor, &IID_IAgileObject, TRUE );
5754 check_interface( motor, &IID_IForceFeedbackMotor, TRUE );
5755 check_runtimeclass( motor, force_feedback_motor );
5757 paused = TRUE;
5758 hr = IForceFeedbackMotor_get_AreEffectsPaused( motor, &paused );
5759 ok( hr == S_OK, "get_AreEffectsPaused returned %#lx\n", hr );
5760 ok( paused == FALSE, "got paused %u\n", paused );
5762 gain = 12345.6;
5763 hr = IForceFeedbackMotor_get_MasterGain( motor, &gain );
5764 ok( hr == S_OK, "get_MasterGain returned %#lx\n", hr );
5765 ok( gain == 1.0, "got gain %f\n", gain );
5766 set_hid_expect( file, &expect_set_gain, sizeof(expect_set_gain) );
5767 hr = IForceFeedbackMotor_put_MasterGain( motor, 0.5 );
5768 ok( hr == S_OK, "put_MasterGain returned %#lx\n", hr );
5769 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
5771 enabled = FALSE;
5772 hr = IForceFeedbackMotor_get_IsEnabled( motor, &enabled );
5773 ok( hr == S_OK, "get_IsEnabled returned %#lx\n", hr );
5774 ok( enabled == TRUE, "got enabled %u\n", enabled );
5776 supported_axes = 0xdeadbeef;
5777 hr = IForceFeedbackMotor_get_SupportedAxes( motor, &supported_axes );
5778 todo_wine
5779 ok( hr == S_OK, "get_SupportedAxes returned %#lx\n", hr );
5780 todo_wine
5781 ok( supported_axes == ForceFeedbackEffectAxes_X, "got axes %#x\n", supported_axes );
5783 set_hid_expect( file, &expect_pause, sizeof(expect_pause) );
5784 hr = IForceFeedbackMotor_PauseAllEffects( motor );
5785 ok( hr == S_OK, "PauseAllEffects returned %#lx\n", hr );
5786 set_hid_expect( file, &expect_resume, sizeof(expect_resume) );
5787 hr = IForceFeedbackMotor_ResumeAllEffects( motor );
5788 ok( hr == S_OK, "ResumeAllEffects returned %#lx\n", hr );
5789 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
5790 hr = IForceFeedbackMotor_StopAllEffects( motor );
5791 ok( hr == S_OK, "StopAllEffects returned %#lx\n", hr );
5792 set_hid_expect( file, NULL, 0 );
5795 set_hid_expect( file, &expect_disable, sizeof(expect_disable) );
5796 hr = IForceFeedbackMotor_TryDisableAsync( motor, &bool_async );
5797 ok( hr == S_OK, "TryDisableAsync returned %#lx\n", hr );
5798 wait_hid_expect( file, 100 );
5799 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
5801 check_interface( bool_async, &IID_IUnknown, TRUE );
5802 check_interface( bool_async, &IID_IInspectable, TRUE );
5803 check_interface( bool_async, &IID_IAgileObject, TRUE );
5804 check_interface( bool_async, &IID_IAsyncInfo, TRUE );
5805 check_interface( bool_async, &IID_IAsyncOperation_boolean, TRUE );
5806 check_runtimeclass( bool_async, L"Windows.Foundation.IAsyncOperation`1<Boolean>" );
5808 hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
5809 ok( hr == S_OK, "get_Completed returned %#lx\n", hr );
5810 ok( tmp_handler == NULL, "got handler %p\n", tmp_handler );
5811 bool_async_handler = default_bool_async_handler;
5812 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
5813 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
5814 ok( bool_async_handler.invoked, "handler not invoked\n" );
5815 ok( bool_async_handler.async == bool_async, "got async %p\n", bool_async_handler.async );
5816 ok( bool_async_handler.status == Completed, "got status %u\n", bool_async_handler.status );
5817 hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
5818 ok( hr == S_OK, "get_Completed returned %#lx\n", hr );
5819 ok( tmp_handler == NULL, "got handler %p\n", tmp_handler );
5820 bool_async_handler = default_bool_async_handler;
5821 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
5822 ok( hr == E_ILLEGAL_DELEGATE_ASSIGNMENT, "put_Completed returned %#lx\n", hr );
5823 ok( !bool_async_handler.invoked, "handler invoked\n" );
5824 ok( bool_async_handler.async == NULL, "got async %p\n", bool_async_handler.async );
5825 ok( bool_async_handler.status == Started, "got status %u\n", bool_async_handler.status );
5827 hr = IAsyncOperation_boolean_QueryInterface( bool_async, &IID_IAsyncInfo, (void **)&async_info );
5828 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5829 hr = IAsyncInfo_Cancel( async_info );
5830 ok( hr == S_OK, "Cancel returned %#lx\n", hr );
5831 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
5832 hr = IAsyncInfo_Close( async_info );
5833 ok( hr == S_OK, "Close returned %#lx\n", hr );
5834 check_bool_async( bool_async, 1, 4, S_OK, FALSE );
5835 IAsyncInfo_Release( async_info );
5837 IAsyncOperation_boolean_Release( bool_async );
5840 set_hid_expect( file, &expect_enable_fail, sizeof(expect_enable_fail) );
5841 hr = IForceFeedbackMotor_TryEnableAsync( motor, &bool_async );
5842 ok( hr == S_OK, "TryEnableAsync returned %#lx\n", hr );
5843 wait_hid_expect( file, 100 );
5844 check_bool_async( bool_async, 1, Error, 0x8685400d, FALSE );
5846 bool_async_handler = default_bool_async_handler;
5847 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
5848 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
5849 ok( bool_async_handler.invoked, "handler not invoked\n" );
5850 ok( bool_async_handler.async == bool_async, "got async %p\n", bool_async_handler.async );
5851 ok( bool_async_handler.status == Error, "got status %u\n", bool_async_handler.status );
5853 hr = IAsyncOperation_boolean_QueryInterface( bool_async, &IID_IAsyncInfo, (void **)&async_info );
5854 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5855 hr = IAsyncInfo_Cancel( async_info );
5856 ok( hr == S_OK, "Cancel returned %#lx\n", hr );
5857 check_bool_async( bool_async, 1, Error, 0x8685400d, FALSE );
5858 hr = IAsyncInfo_Close( async_info );
5859 ok( hr == S_OK, "Close returned %#lx\n", hr );
5860 check_bool_async( bool_async, 1, 4, 0x8685400d, FALSE );
5861 IAsyncInfo_Release( async_info );
5863 IAsyncOperation_boolean_Release( bool_async );
5866 /* canceling the async op is just ignored */
5868 set_hid_expect( file, expect_reset_delay, sizeof(expect_reset_delay) );
5869 hr = IForceFeedbackMotor_TryResetAsync( motor, &bool_async );
5870 ok( hr == S_OK, "TryResetAsync returned %#lx\n", hr );
5871 check_bool_async( bool_async, 1, Started, S_OK, FALSE );
5873 bool_async_handler = default_bool_async_handler;
5874 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
5875 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
5877 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
5878 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
5879 ok( !bool_async_handler.invoked, "handler invoked\n" );
5880 hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
5881 ok( hr == S_OK, "get_Completed returned %#lx\n", hr );
5882 ok( tmp_handler == &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface,
5883 "got handler %p\n", tmp_handler );
5885 hr = IAsyncOperation_boolean_QueryInterface( bool_async, &IID_IAsyncInfo, (void **)&async_info );
5886 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5887 hr = IAsyncInfo_Cancel( async_info );
5888 ok( hr == S_OK, "Cancel returned %#lx\n", hr );
5889 check_bool_async( bool_async, 1, Canceled, S_OK, FALSE );
5890 ok( !bool_async_handler.invoked, "handler invoked\n" );
5891 IAsyncInfo_Release( async_info );
5893 wait_hid_pending( file, 100 );
5894 ret = WaitForSingleObject( bool_async_handler.event, 500 );
5895 ok( ret == 0, "WaitForSingleObject returned %#lx\n", ret );
5896 CloseHandle( bool_async_handler.event );
5897 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
5899 ok( bool_async_handler.invoked, "handler not invoked\n" );
5900 ok( bool_async_handler.async == bool_async, "got async %p\n", bool_async_handler.async );
5901 ok( bool_async_handler.status == Completed, "got status %u\n", bool_async_handler.status );
5902 hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
5903 ok( hr == S_OK, "get_Completed returned %#lx\n", hr );
5904 ok( tmp_handler == NULL, "got handler %p\n", tmp_handler );
5906 IAsyncOperation_boolean_Release( bool_async );
5909 /* canceling then closing it calls the handler with closed state */
5911 set_hid_expect( file, expect_reset_delay, sizeof(expect_reset_delay) );
5912 hr = IForceFeedbackMotor_TryResetAsync( motor, &bool_async );
5913 ok( hr == S_OK, "TryResetAsync returned %#lx\n", hr );
5914 check_bool_async( bool_async, 1, Started, S_OK, FALSE );
5916 bool_async_handler = default_bool_async_handler;
5917 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
5918 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
5920 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
5921 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
5922 ok( !bool_async_handler.invoked, "handler invoked\n" );
5924 hr = IAsyncOperation_boolean_QueryInterface( bool_async, &IID_IAsyncInfo, (void **)&async_info );
5925 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5926 hr = IAsyncInfo_Close( async_info );
5927 ok( hr == E_ILLEGAL_STATE_CHANGE, "Close returned %#lx\n", hr );
5928 hr = IAsyncInfo_Cancel( async_info );
5929 ok( hr == S_OK, "Cancel returned %#lx\n", hr );
5930 check_bool_async( bool_async, 1, Canceled, S_OK, FALSE );
5931 ok( !bool_async_handler.invoked, "handler invoked\n" );
5932 hr = IAsyncInfo_Close( async_info );
5933 ok( hr == S_OK, "Close returned %#lx\n", hr );
5934 check_bool_async( bool_async, 1, 4, S_OK, FALSE );
5935 ok( !bool_async_handler.invoked, "handler invoked\n" );
5936 IAsyncInfo_Release( async_info );
5938 wait_hid_pending( file, 100 );
5939 ret = WaitForSingleObject( bool_async_handler.event, 500 );
5940 ok( ret == 0, "WaitForSingleObject returned %#lx\n", ret );
5941 CloseHandle( bool_async_handler.event );
5942 check_bool_async( bool_async, 1, 4, S_OK, FALSE );
5944 ok( bool_async_handler.invoked, "handler not invoked\n" );
5945 ok( bool_async_handler.async == bool_async, "got async %p\n", bool_async_handler.async );
5946 ok( bool_async_handler.status == 4, "got status %u\n", bool_async_handler.status );
5947 hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
5948 ok( hr == E_ILLEGAL_METHOD_CALL, "get_Completed returned %#lx\n", hr );
5950 IAsyncOperation_boolean_Release( bool_async );
5953 set_hid_expect( file, &expect_enable, sizeof(expect_enable) );
5954 hr = IForceFeedbackMotor_TryEnableAsync( motor, &bool_async );
5955 ok( hr == S_OK, "TryEnableAsync returned %#lx\n", hr );
5956 wait_hid_expect( file, 100 );
5957 IAsyncOperation_boolean_Release( bool_async );
5960 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
5961 hr = IForceFeedbackMotor_TryResetAsync( motor, &bool_async );
5962 ok( hr == S_OK, "TryResetAsync returned %#lx\n", hr );
5963 wait_hid_expect( file, 100 );
5964 IAsyncOperation_boolean_Release( bool_async );
5967 hr = pWindowsCreateString( force_feedback_motor, wcslen( force_feedback_motor ), &str );
5968 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5969 hr = pRoGetActivationFactory( str, &IID_IInspectable, (void **)&tmp_inspectable );
5970 ok( hr == REGDB_E_CLASSNOTREG, "RoGetActivationFactory returned %#lx\n", hr );
5971 pWindowsDeleteString( str );
5974 hr = pWindowsCreateString( periodic_effect_class_name, wcslen( periodic_effect_class_name ), &str );
5975 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5976 hr = pRoGetActivationFactory( str, &IID_IPeriodicForceEffectFactory, (void **)&periodic_factory );
5977 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
5978 pWindowsDeleteString( str );
5980 check_interface( periodic_factory, &IID_IUnknown, TRUE );
5981 check_interface( periodic_factory, &IID_IInspectable, TRUE );
5982 check_interface( periodic_factory, &IID_IAgileObject, TRUE );
5983 check_interface( periodic_factory, &IID_IActivationFactory, TRUE );
5984 check_interface( periodic_factory, &IID_IPeriodicForceEffectFactory, TRUE );
5985 check_interface( periodic_factory, &IID_IConditionForceEffectFactory, FALSE );
5987 hr = IPeriodicForceEffectFactory_QueryInterface( periodic_factory, &IID_IActivationFactory, (void **)&activation_factory );
5988 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5989 hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable );
5990 ok( hr == E_NOTIMPL, "ActivateInstance returned %#lx\n", hr );
5991 IActivationFactory_Release( activation_factory );
5993 hr = IPeriodicForceEffectFactory_CreateInstance( periodic_factory, PeriodicForceEffectKind_SawtoothWaveUp, &effect );
5994 ok( hr == S_OK, "CreateInstance returned %#lx\n", hr );
5996 check_interface( effect, &IID_IUnknown, TRUE );
5997 check_interface( effect, &IID_IInspectable, TRUE );
5998 check_interface( effect, &IID_IAgileObject, TRUE );
5999 check_interface( effect, &IID_IForceFeedbackEffect, TRUE );
6000 check_interface( effect, &IID_IPeriodicForceEffect, TRUE );
6001 check_interface( effect, &IID_IConditionForceEffect, FALSE );
6002 check_runtimeclass( effect, periodic_effect_class_name );
6004 hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IPeriodicForceEffect, (void **)&periodic_effect );
6005 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6007 hr = IPeriodicForceEffect_get_Kind( periodic_effect, &periodic_kind );
6008 ok( hr == S_OK, "get_Kind returned %#lx\n", hr );
6009 ok( periodic_kind == PeriodicForceEffectKind_SawtoothWaveUp, "got kind %u\n", periodic_kind );
6010 hr = IPeriodicForceEffect_SetParameters( periodic_effect, direction, 1.0, 0.1, 0.0, duration );
6011 ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
6012 hr = IPeriodicForceEffect_SetParametersWithEnvelope( periodic_effect, direction, 100.0, 0.1, 0.2, 0.3, 0.4, 0.5,
6013 delay, attack_duration, duration, release_duration, 1 );
6014 ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr );
6015 IPeriodicForceEffect_Release( periodic_effect );
6017 gain = 12345.6;
6018 hr = IForceFeedbackEffect_get_Gain( effect, &gain );
6019 ok( hr == S_OK, "get_Gain returned %#lx\n", hr );
6020 ok( gain == 1.0, "got gain %f\n", gain );
6021 hr = IForceFeedbackEffect_put_Gain( effect, 0.5 );
6022 ok( hr == S_FALSE, "put_Gain returned %#lx\n", hr );
6023 state = 0xdeadbeef;
6024 hr = IForceFeedbackEffect_get_State( effect, &state );
6025 todo_wine
6026 ok( hr == S_OK, "get_State returned %#lx\n", hr );
6027 todo_wine
6028 ok( state == ForceFeedbackEffectState_Stopped, "got state %#x\n", state );
6029 hr = IForceFeedbackEffect_Start( effect );
6030 todo_wine
6031 ok( hr == 0x86854003, "Start returned %#lx\n", hr );
6032 hr = IForceFeedbackEffect_Stop( effect );
6033 todo_wine
6034 ok( hr == 0x86854003, "Stop returned %#lx\n", hr );
6036 hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
6037 ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
6038 result_async_handler = default_result_async_handler;
6039 result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6040 ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6041 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
6042 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6043 ret = WaitForSingleObject( result_async_handler.event, 5000 );
6044 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6045 ret = CloseHandle( result_async_handler.event );
6046 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6047 check_result_async( result_async, 1, Error, 0x86854008, ForceFeedbackLoadEffectResult_EffectNotSupported );
6048 IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async );
6050 hr = IForceFeedbackEffect_Start( effect );
6051 todo_wine
6052 ok( hr == 0x86854003, "Start returned %#lx\n", hr );
6053 hr = IForceFeedbackEffect_Stop( effect );
6054 todo_wine
6055 ok( hr == 0x86854003, "Stop returned %#lx\n", hr );
6056 hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async );
6057 todo_wine
6058 ok( hr == 0x86854003, "TryUnloadEffectAsync returned %#lx\n", hr );
6060 ref = IForceFeedbackEffect_Release( effect );
6061 ok( ref == 0, "Release returned %lu\n", ref );
6064 hr = IPeriodicForceEffectFactory_CreateInstance( periodic_factory, PeriodicForceEffectKind_SineWave, &effect );
6065 ok( hr == S_OK, "CreateInstance returned %#lx\n", hr );
6067 check_interface( effect, &IID_IUnknown, TRUE );
6068 check_interface( effect, &IID_IInspectable, TRUE );
6069 check_interface( effect, &IID_IAgileObject, TRUE );
6070 check_interface( effect, &IID_IForceFeedbackEffect, TRUE );
6071 check_interface( effect, &IID_IPeriodicForceEffect, TRUE );
6072 check_interface( effect, &IID_IConditionForceEffect, FALSE );
6073 check_runtimeclass( effect, periodic_effect_class_name );
6075 hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IPeriodicForceEffect, (void **)&periodic_effect );
6076 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6078 hr = IPeriodicForceEffect_get_Kind( periodic_effect, &periodic_kind );
6079 ok( hr == S_OK, "get_Kind returned %#lx\n", hr );
6080 ok( periodic_kind == PeriodicForceEffectKind_SineWave, "got kind %u\n", periodic_kind );
6081 hr = IPeriodicForceEffect_SetParameters( periodic_effect, direction, 1.0, 0.1, 0.0, duration );
6082 ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
6083 hr = IPeriodicForceEffect_SetParametersWithEnvelope( periodic_effect, direction, 100.0, 0.1, 0.2, 0.3, 0.4, 0.5,
6084 delay, duration, duration, duration, 1 );
6085 ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr );
6086 IPeriodicForceEffect_Release( periodic_effect );
6088 set_hid_expect( file, expect_create_periodic, sizeof(expect_create_periodic) );
6089 hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
6090 ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
6091 result_async_handler = default_result_async_handler;
6092 result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6093 ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6094 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
6095 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6096 ret = WaitForSingleObject( result_async_handler.event, 5000 );
6097 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6098 ret = CloseHandle( result_async_handler.event );
6099 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6100 check_result_async( result_async, 1, Completed, S_OK, ForceFeedbackLoadEffectResult_Succeeded );
6101 IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async );
6102 set_hid_expect( file, NULL, 0 );
6104 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6105 hr = IForceFeedbackEffect_Start( effect );
6106 todo_wine
6107 ok( hr == S_OK, "Start returned %#lx\n", hr );
6108 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6109 hr = IForceFeedbackEffect_Start( effect );
6110 todo_wine
6111 ok( hr == S_OK, "Start returned %#lx\n", hr );
6113 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6114 hr = IForceFeedbackEffect_Stop( effect );
6115 todo_wine
6116 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6117 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6118 hr = IForceFeedbackEffect_Stop( effect );
6119 todo_wine
6120 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6122 set_hid_expect( file, expect_unload, sizeof(expect_unload) );
6123 hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async );
6124 ok( hr == S_OK, "TryUnloadEffectAsync returned %#lx\n", hr );
6125 bool_async_handler = default_bool_async_handler;
6126 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6127 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6128 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
6129 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6130 ret = WaitForSingleObject( bool_async_handler.event, 5000 );
6131 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6132 ret = CloseHandle( bool_async_handler.event );
6133 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6134 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
6135 IAsyncOperation_boolean_Release( bool_async );
6136 set_hid_expect( file, NULL, 0 );
6138 ref = IForceFeedbackEffect_Release( effect );
6139 ok( ref == 0, "Release returned %lu\n", ref );
6141 IPeriodicForceEffectFactory_Release( periodic_factory );
6144 hr = pWindowsCreateString( condition_effect_class_name, wcslen( condition_effect_class_name ), &str );
6145 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
6146 hr = pRoGetActivationFactory( str, &IID_IConditionForceEffectFactory, (void **)&condition_factory );
6147 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
6148 pWindowsDeleteString( str );
6150 check_interface( condition_factory, &IID_IUnknown, TRUE );
6151 check_interface( condition_factory, &IID_IInspectable, TRUE );
6152 check_interface( condition_factory, &IID_IAgileObject, TRUE );
6153 check_interface( condition_factory, &IID_IActivationFactory, TRUE );
6154 check_interface( condition_factory, &IID_IConditionForceEffectFactory, TRUE );
6155 check_interface( condition_factory, &IID_IPeriodicForceEffectFactory, FALSE );
6157 hr = IConditionForceEffectFactory_QueryInterface( condition_factory, &IID_IActivationFactory, (void **)&activation_factory );
6158 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6159 hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable );
6160 ok( hr == E_NOTIMPL, "ActivateInstance returned %#lx\n", hr );
6161 IActivationFactory_Release( activation_factory );
6164 hr = IConditionForceEffectFactory_CreateInstance( condition_factory, ConditionForceEffectKind_Spring, &effect );
6165 ok( hr == S_OK, "CreateInstance returned %#lx\n", hr );
6167 check_interface( effect, &IID_IUnknown, TRUE );
6168 check_interface( effect, &IID_IInspectable, TRUE );
6169 check_interface( effect, &IID_IAgileObject, TRUE );
6170 check_interface( effect, &IID_IForceFeedbackEffect, TRUE );
6171 check_interface( effect, &IID_IConditionForceEffect, TRUE );
6172 check_interface( effect, &IID_IPeriodicForceEffect, FALSE );
6173 check_runtimeclass( effect, condition_effect_class_name );
6175 hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IConditionForceEffect, (void **)&condition_effect );
6176 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6178 hr = IConditionForceEffect_get_Kind( condition_effect, &condition_kind );
6179 ok( hr == S_OK, "get_Kind returned %#lx\n", hr );
6180 ok( condition_kind == ConditionForceEffectKind_Spring, "got kind %u\n", condition_kind );
6181 hr = IConditionForceEffect_SetParameters( condition_effect, direction, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 );
6182 ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
6183 IConditionForceEffect_Release( condition_effect );
6185 set_hid_expect( file, expect_create_condition, sizeof(expect_create_condition) );
6186 hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
6187 ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
6188 result_async_handler = default_result_async_handler;
6189 result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6190 ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6191 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
6192 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6193 ret = WaitForSingleObject( result_async_handler.event, 5000 );
6194 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6195 ret = CloseHandle( result_async_handler.event );
6196 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6197 check_result_async( result_async, 1, Completed, S_OK, ForceFeedbackLoadEffectResult_Succeeded );
6198 IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async );
6199 set_hid_expect( file, NULL, 0 );
6201 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6202 hr = IForceFeedbackEffect_Start( effect );
6203 todo_wine
6204 ok( hr == S_OK, "Start returned %#lx\n", hr );
6205 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6206 hr = IForceFeedbackEffect_Start( effect );
6207 todo_wine
6208 ok( hr == S_OK, "Start returned %#lx\n", hr );
6210 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6211 hr = IForceFeedbackEffect_Stop( effect );
6212 todo_wine
6213 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6214 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6215 hr = IForceFeedbackEffect_Stop( effect );
6216 todo_wine
6217 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6219 set_hid_expect( file, expect_unload, sizeof(expect_unload) );
6220 hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async );
6221 ok( hr == S_OK, "TryUnloadEffectAsync returned %#lx\n", hr );
6222 bool_async_handler = default_bool_async_handler;
6223 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6224 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6225 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
6226 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6227 ret = WaitForSingleObject( bool_async_handler.event, 5000 );
6228 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6229 ret = CloseHandle( bool_async_handler.event );
6230 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6231 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
6232 IAsyncOperation_boolean_Release( bool_async );
6233 set_hid_expect( file, NULL, 0 );
6235 ref = IForceFeedbackEffect_Release( effect );
6236 ok( ref == 0, "Release returned %lu\n", ref );
6238 IConditionForceEffectFactory_Release( condition_factory );
6241 hr = pWindowsCreateString( constant_effect_class_name, wcslen( constant_effect_class_name ), &str );
6242 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
6243 hr = pRoGetActivationFactory( str, &IID_IActivationFactory, (void **)&activation_factory );
6244 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
6245 pWindowsDeleteString( str );
6247 hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable );
6248 ok( hr == S_OK, "ActivateInstance returned %#lx\n", hr );
6249 IActivationFactory_Release( activation_factory );
6251 hr = IInspectable_QueryInterface( tmp_inspectable, &IID_IForceFeedbackEffect, (void **)&effect );
6252 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6253 IInspectable_Release( tmp_inspectable );
6255 hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IConstantForceEffect, (void **)&constant_effect );
6256 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6258 hr = IConstantForceEffect_SetParameters( constant_effect, direction, duration );
6259 ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
6260 hr = IConstantForceEffect_SetParametersWithEnvelope( constant_effect, direction, 0.1, 0.2, 0.3,
6261 delay, attack_duration, duration, release_duration, 1 );
6262 ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr );
6263 IConstantForceEffect_Release( constant_effect );
6265 gain = 12345.6;
6266 hr = IForceFeedbackEffect_get_Gain( effect, &gain );
6267 ok( hr == S_OK, "get_Gain returned %#lx\n", hr );
6268 ok( gain == 1.0, "get_MasterGain returned %f\n", gain );
6269 hr = IForceFeedbackEffect_put_Gain( effect, 0.5 );
6270 ok( hr == S_FALSE, "put_Gain returned %#lx\n", hr );
6271 state = 0xdeadbeef;
6272 hr = IForceFeedbackEffect_get_State( effect, &state );
6273 todo_wine
6274 ok( hr == S_OK, "get_State returned %#lx\n", hr );
6275 todo_wine
6276 ok( state == ForceFeedbackEffectState_Stopped, "get_State returned %#lx\n", hr );
6277 hr = IForceFeedbackEffect_Start( effect );
6278 todo_wine
6279 ok( hr == 0x86854003, "Start returned %#lx\n", hr );
6280 hr = IForceFeedbackEffect_Stop( effect );
6281 todo_wine
6282 ok( hr == 0x86854003, "Stop returned %#lx\n", hr );
6284 set_hid_expect( file, expect_create_constant, sizeof(expect_create_constant) );
6285 hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
6286 ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
6287 result_async_handler = default_result_async_handler;
6288 result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6289 ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6290 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
6291 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6292 ret = WaitForSingleObject( result_async_handler.event, 5000 );
6293 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6294 ret = CloseHandle( result_async_handler.event );
6295 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6296 check_result_async( result_async, 1, Completed, S_OK, ForceFeedbackLoadEffectResult_Succeeded );
6297 IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async );
6298 set_hid_expect( file, NULL, 0 );
6300 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6301 hr = IForceFeedbackEffect_Start( effect );
6302 todo_wine
6303 ok( hr == S_OK, "Start returned %#lx\n", hr );
6304 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6305 hr = IForceFeedbackEffect_Start( effect );
6306 todo_wine
6307 ok( hr == S_OK, "Start returned %#lx\n", hr );
6309 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6310 hr = IForceFeedbackEffect_Stop( effect );
6311 todo_wine
6312 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6313 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6314 hr = IForceFeedbackEffect_Stop( effect );
6315 todo_wine
6316 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6318 set_hid_expect( file, expect_unload, sizeof(expect_unload) );
6319 hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async );
6320 ok( hr == S_OK, "TryUnloadEffectAsync returned %#lx\n", hr );
6321 bool_async_handler = default_bool_async_handler;
6322 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6323 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6324 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
6325 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6326 ret = WaitForSingleObject( bool_async_handler.event, 5000 );
6327 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6328 ret = CloseHandle( bool_async_handler.event );
6329 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6330 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
6331 IAsyncOperation_boolean_Release( bool_async );
6332 set_hid_expect( file, NULL, 0 );
6334 ref = IForceFeedbackEffect_Release( effect );
6335 ok( ref == 0, "Release returned %lu\n", ref );
6338 hr = pWindowsCreateString( ramp_effect_class_name, wcslen( ramp_effect_class_name ), &str );
6339 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
6340 hr = pRoGetActivationFactory( str, &IID_IActivationFactory, (void **)&activation_factory );
6341 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
6342 pWindowsDeleteString( str );
6344 hr = IActivationFactory_ActivateInstance( activation_factory, &tmp_inspectable );
6345 ok( hr == S_OK, "ActivateInstance returned %#lx\n", hr );
6346 IActivationFactory_Release( activation_factory );
6348 hr = IInspectable_QueryInterface( tmp_inspectable, &IID_IForceFeedbackEffect, (void **)&effect );
6349 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6350 IInspectable_Release( tmp_inspectable );
6352 hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IRampForceEffect, (void **)&ramp_effect );
6353 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6355 hr = IRampForceEffect_SetParameters( ramp_effect, direction, end_direction, duration );
6356 ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
6357 hr = IRampForceEffect_SetParametersWithEnvelope( ramp_effect, direction, end_direction, 0.1, 0.2, 0.3,
6358 delay, attack_duration, duration, release_duration, 1 );
6359 ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr );
6360 IRampForceEffect_Release( ramp_effect );
6362 set_hid_expect( file, expect_create_ramp, sizeof(expect_create_ramp) );
6363 hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
6364 ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
6365 result_async_handler = default_result_async_handler;
6366 result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6367 ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6368 hr = IAsyncOperation_ForceFeedbackLoadEffectResult_put_Completed( result_async, &result_async_handler.IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult_iface );
6369 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6370 ret = WaitForSingleObject( result_async_handler.event, 5000 );
6371 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6372 ret = CloseHandle( result_async_handler.event );
6373 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6374 check_result_async( result_async, 1, Completed, S_OK, ForceFeedbackLoadEffectResult_Succeeded );
6375 IAsyncOperation_ForceFeedbackLoadEffectResult_Release( result_async );
6376 set_hid_expect( file, NULL, 0 );
6378 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6379 hr = IForceFeedbackEffect_Start( effect );
6380 todo_wine
6381 ok( hr == S_OK, "Start returned %#lx\n", hr );
6382 set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) );
6383 hr = IForceFeedbackEffect_Start( effect );
6384 todo_wine
6385 ok( hr == S_OK, "Start returned %#lx\n", hr );
6387 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6388 hr = IForceFeedbackEffect_Stop( effect );
6389 todo_wine
6390 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6391 set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) );
6392 hr = IForceFeedbackEffect_Stop( effect );
6393 todo_wine
6394 ok( hr == S_OK, "Stop returned %#lx\n", hr );
6396 set_hid_expect( file, expect_unload, sizeof(expect_unload) );
6397 hr = IForceFeedbackMotor_TryUnloadEffectAsync( motor, effect, &bool_async );
6398 ok( hr == S_OK, "TryUnloadEffectAsync returned %#lx\n", hr );
6399 bool_async_handler = default_bool_async_handler;
6400 bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
6401 ok( !!bool_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
6402 hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
6403 ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
6404 ret = WaitForSingleObject( bool_async_handler.event, 5000 );
6405 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
6406 ret = CloseHandle( bool_async_handler.event );
6407 ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
6408 check_bool_async( bool_async, 1, Completed, S_OK, TRUE );
6409 IAsyncOperation_boolean_Release( bool_async );
6410 set_hid_expect( file, NULL, 0 );
6412 ref = IForceFeedbackEffect_Release( effect );
6413 ok( ref == 0, "Release returned %lu\n", ref );
6416 IForceFeedbackMotor_Release( motor );
6418 IRawGameController_Release( raw_controller );
6420 CloseHandle( file );
6421 IRawGameControllerStatics_Release( controller_statics );
6423 done:
6424 hid_device_stop( &desc );
6425 cleanup_registry_keys();
6428 START_TEST( force_feedback )
6430 if (!dinput_test_init()) return;
6431 if (!bus_device_start()) goto done;
6433 CoInitialize( NULL );
6434 if (test_force_feedback_joystick( 0x800 ))
6436 test_force_feedback_joystick( 0x500 );
6437 test_force_feedback_joystick( 0x700 );
6438 test_device_managed_effect();
6439 test_windows_gaming_input();
6441 CoUninitialize();
6443 done:
6444 bus_device_stop();
6445 dinput_test_exit();