comctl32/tests: Use CRT allocation functions.
[wine.git] / dlls / xinput1_3 / tests / xinput.c
blob5c31f0be1fe251559f5ed48587598e6e53e900b6
1 /*
2 * The Wine project - Xinput Joystick Library
3 * Copyright 2008 Andrew Fenn
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <windows.h>
21 #include <stdio.h>
23 #include "winioctl.h"
24 #include "xinput.h"
25 #include "shlwapi.h"
26 #include "setupapi.h"
27 #include "ddk/hidsdi.h"
28 #include "ddk/hidclass.h"
29 #include "wine/test.h"
31 static DWORD (WINAPI *pXInputGetState)(DWORD, XINPUT_STATE*);
32 static DWORD (WINAPI *pXInputGetStateEx)(DWORD, XINPUT_STATE*);
33 static DWORD (WINAPI *pXInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
34 static DWORD (WINAPI *pXInputSetState)(DWORD, XINPUT_VIBRATION*);
35 static void (WINAPI *pXInputEnable)(BOOL);
36 static DWORD (WINAPI *pXInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);
37 static DWORD (WINAPI *pXInputGetDSoundAudioDeviceGuids)(DWORD, GUID*, GUID*);
38 static DWORD (WINAPI *pXInputGetBatteryInformation)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*);
40 static void dump_gamepad(XINPUT_GAMEPAD *data)
42 trace("-- Gamepad Variables --\n");
43 trace("Gamepad.wButtons: %#x\n", data->wButtons);
44 trace("Gamepad.bLeftTrigger: %d\n", data->bLeftTrigger);
45 trace("Gamepad.bRightTrigger: %d\n", data->bRightTrigger);
46 trace("Gamepad.sThumbLX: %d\n", data->sThumbLX);
47 trace("Gamepad.sThumbLY: %d\n", data->sThumbLY);
48 trace("Gamepad.sThumbRX: %d\n", data->sThumbRX);
49 trace("Gamepad.sThumbRY: %d\n\n", data->sThumbRY);
52 static void test_set_state(void)
54 XINPUT_VIBRATION vibrator;
55 DWORD controllerNum;
56 DWORD result;
58 for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
60 ZeroMemory(&vibrator, sizeof(XINPUT_VIBRATION));
62 vibrator.wLeftMotorSpeed = 32767;
63 vibrator.wRightMotorSpeed = 32767;
64 result = pXInputSetState(controllerNum, &vibrator);
65 if (result == ERROR_DEVICE_NOT_CONNECTED) continue;
67 Sleep(250);
68 vibrator.wLeftMotorSpeed = 0;
69 vibrator.wRightMotorSpeed = 0;
70 result = pXInputSetState(controllerNum, &vibrator);
71 ok(result == ERROR_SUCCESS, "XInputSetState returned %lu\n", result);
73 /* Disabling XInput here, queueing a vibration and then re-enabling XInput
74 * is used to prove that vibrations are auto enabled when resuming XInput.
75 * If XInputEnable(1) is removed below the vibration will never play. */
76 if (pXInputEnable) pXInputEnable(0);
78 Sleep(250);
79 vibrator.wLeftMotorSpeed = 65535;
80 vibrator.wRightMotorSpeed = 65535;
81 result = pXInputSetState(controllerNum, &vibrator);
82 ok(result == ERROR_SUCCESS, "XInputSetState returned %lu\n", result);
84 if (pXInputEnable) pXInputEnable(1);
85 Sleep(250);
87 vibrator.wLeftMotorSpeed = 0;
88 vibrator.wRightMotorSpeed = 0;
89 result = pXInputSetState(controllerNum, &vibrator);
90 ok(result == ERROR_SUCCESS, "XInputSetState returned %lu\n", result);
93 result = pXInputSetState(XUSER_MAX_COUNT+1, &vibrator);
94 ok(result == ERROR_BAD_ARGUMENTS, "XInputSetState returned %lu\n", result);
97 static void test_get_state(void)
99 XINPUT_STATE state;
100 DWORD controllerNum, i, result, good = XUSER_MAX_COUNT;
102 for (i = 0; i < (pXInputGetStateEx ? 2 : 1); i++)
104 for (controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
106 ZeroMemory(&state, sizeof(state));
108 if (i == 0)
109 result = pXInputGetState(controllerNum, &state);
110 else
111 result = pXInputGetStateEx(controllerNum, &state);
112 ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED,
113 "%s returned %lu\n", i == 0 ? "XInputGetState" : "XInputGetStateEx", result);
115 if (ERROR_DEVICE_NOT_CONNECTED == result)
117 skip("Controller %lu is not connected\n", controllerNum);
118 continue;
121 trace("-- Results for controller %lu --\n", controllerNum);
122 if (i == 0)
124 good = controllerNum;
125 trace("XInputGetState: %lu\n", result);
127 else
128 trace("XInputGetStateEx: %lu\n", result);
129 trace("State->dwPacketNumber: %lu\n", state.dwPacketNumber);
130 dump_gamepad(&state.Gamepad);
134 result = pXInputGetState(0, NULL);
135 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned %lu\n", result);
137 result = pXInputGetState(XUSER_MAX_COUNT, &state);
138 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned %lu\n", result);
140 result = pXInputGetState(XUSER_MAX_COUNT+1, &state);
141 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned %lu\n", result);
142 if (pXInputGetStateEx)
144 result = pXInputGetStateEx(XUSER_MAX_COUNT, &state);
145 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned %lu\n", result);
147 result = pXInputGetStateEx(XUSER_MAX_COUNT+1, &state);
148 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned %lu\n", result);
151 if (winetest_interactive && good < XUSER_MAX_COUNT)
153 DWORD now = GetTickCount(), packet = 0;
154 XINPUT_GAMEPAD *game = &state.Gamepad;
156 trace("You have 20 seconds to test the joystick freely\n");
159 Sleep(100);
160 pXInputGetState(good, &state);
161 if (state.dwPacketNumber == packet)
162 continue;
164 packet = state.dwPacketNumber;
165 trace("Buttons 0x%04X Triggers %3d/%3d LT %6d/%6d RT %6d/%6d\n",
166 game->wButtons, game->bLeftTrigger, game->bRightTrigger,
167 game->sThumbLX, game->sThumbLY, game->sThumbRX, game->sThumbRY);
169 while(GetTickCount() - now < 20000);
170 trace("Test over...\n");
174 static void test_get_keystroke(void)
176 XINPUT_KEYSTROKE keystroke;
177 DWORD controllerNum;
178 DWORD result;
180 for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
182 ZeroMemory(&keystroke, sizeof(XINPUT_KEYSTROKE));
184 result = pXInputGetKeystroke(controllerNum, XINPUT_FLAG_GAMEPAD, &keystroke);
185 ok(result == ERROR_EMPTY || result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED,
186 "XInputGetKeystroke returned %lu\n", result);
188 if (ERROR_DEVICE_NOT_CONNECTED == result)
190 skip("Controller %lu is not connected\n", controllerNum);
194 ZeroMemory(&keystroke, sizeof(XINPUT_KEYSTROKE));
195 result = pXInputGetKeystroke(XUSER_MAX_COUNT+1, XINPUT_FLAG_GAMEPAD, &keystroke);
196 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetKeystroke returned %lu\n", result);
199 static void test_get_capabilities(void)
201 XINPUT_CAPABILITIES capabilities;
202 DWORD controllerNum;
203 DWORD result;
205 for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
207 ZeroMemory(&capabilities, sizeof(XINPUT_CAPABILITIES));
209 result = pXInputGetCapabilities(controllerNum, XINPUT_FLAG_GAMEPAD, &capabilities);
210 ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED, "XInputGetCapabilities returned %lu\n", result);
212 if (ERROR_DEVICE_NOT_CONNECTED == result)
214 skip("Controller %lu is not connected\n", controllerNum);
215 continue;
218 /* Important to show that the results changed between 1.3 and 1.4 XInput version */
219 dump_gamepad(&capabilities.Gamepad);
222 ZeroMemory(&capabilities, sizeof(XINPUT_CAPABILITIES));
223 result = pXInputGetCapabilities(XUSER_MAX_COUNT+1, XINPUT_FLAG_GAMEPAD, &capabilities);
224 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetCapabilities returned %lu\n", result);
227 static void test_get_dsoundaudiodevice(void)
229 DWORD controllerNum;
230 DWORD result;
231 GUID soundRender, soundCapture;
232 GUID testGuid = {0xFFFFFFFF, 0xFFFF, 0xFFFF, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
233 GUID emptyGuid = {0x0, 0x0, 0x0, {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
235 for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
237 soundRender = soundCapture = testGuid;
238 result = pXInputGetDSoundAudioDeviceGuids(controllerNum, &soundRender, &soundCapture);
239 ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED, "XInputGetDSoundAudioDeviceGuids returned %lu\n", result);
241 if (ERROR_DEVICE_NOT_CONNECTED == result)
243 skip("Controller %lu is not connected\n", controllerNum);
244 continue;
247 if (!IsEqualGUID(&soundRender, &emptyGuid))
248 ok(!IsEqualGUID(&soundRender, &testGuid), "Broken GUID returned for sound render device\n");
249 else
250 trace("Headset phone not attached\n");
252 if (!IsEqualGUID(&soundCapture, &emptyGuid))
253 ok(!IsEqualGUID(&soundCapture, &testGuid), "Broken GUID returned for sound capture device\n");
254 else
255 trace("Headset microphone not attached\n");
258 result = pXInputGetDSoundAudioDeviceGuids(XUSER_MAX_COUNT+1, &soundRender, &soundCapture);
259 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetDSoundAudioDeviceGuids returned %lu\n", result);
262 static void test_get_batteryinformation(void)
264 DWORD controllerNum;
265 DWORD result;
266 XINPUT_BATTERY_INFORMATION batteryInfo;
268 for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
270 ZeroMemory(&batteryInfo, sizeof(XINPUT_BATTERY_INFORMATION));
272 result = pXInputGetBatteryInformation(controllerNum, BATTERY_DEVTYPE_GAMEPAD, &batteryInfo);
273 ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED, "XInputGetBatteryInformation returned %lu\n", result);
275 if (ERROR_DEVICE_NOT_CONNECTED == result)
277 ok(batteryInfo.BatteryLevel == BATTERY_TYPE_DISCONNECTED, "Failed to report device as being disconnected.\n");
278 skip("Controller %lu is not connected\n", controllerNum);
282 result = pXInputGetBatteryInformation(XUSER_MAX_COUNT+1, BATTERY_DEVTYPE_GAMEPAD, &batteryInfo);
283 ok(result == ERROR_BAD_ARGUMENTS, "XInputGetBatteryInformation returned %lu\n", result);
286 #define check_member_(file, line, val, exp, fmt, member) \
287 ok_(file, line)((val).member == (exp).member, \
288 "got " #member " " fmt ", expected " fmt "\n", \
289 (val).member, (exp).member)
290 #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
292 static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA preparsed,
293 HIDD_ATTRIBUTES *attrs, HIDP_CAPS *hid_caps)
295 const HIDP_CAPS expect_hid_caps =
297 .Usage = HID_USAGE_GENERIC_GAMEPAD,
298 .UsagePage = HID_USAGE_PAGE_GENERIC,
299 .InputReportByteLength =
300 attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff ? 16 :
302 .OutputReportByteLength = 0,
303 .FeatureReportByteLength = 0,
304 .NumberLinkCollectionNodes = 4,
305 .NumberInputButtonCaps = 1,
306 .NumberInputValueCaps = 6,
307 .NumberInputDataIndices =
308 attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff ? 22 :
310 .NumberFeatureButtonCaps = 0,
311 .NumberFeatureValueCaps = 0,
312 .NumberFeatureDataIndices = 0,
314 const HIDP_BUTTON_CAPS expect_button_caps[] =
317 .UsagePage = HID_USAGE_PAGE_BUTTON,
318 .BitField = 2,
319 .LinkUsage = HID_USAGE_GENERIC_GAMEPAD,
320 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
321 .IsRange = TRUE,
322 .IsAbsolute = TRUE,
323 .Range.UsageMin = 0x01,
324 .Range.UsageMax =
325 attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff ? 0x10 :
326 0x0a,
327 .Range.DataIndexMin = 5,
328 .Range.DataIndexMax =
329 attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff ? 20 :
333 const HIDP_VALUE_CAPS expect_value_caps[] =
336 .UsagePage = HID_USAGE_PAGE_GENERIC,
337 .BitField = 2,
338 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
339 .LinkCollection = 1,
340 .IsAbsolute = TRUE,
341 .BitSize = 16,
342 .ReportCount = 1,
343 .LogicalMax = -1,
344 .PhysicalMax = -1,
345 .NotRange.Usage = HID_USAGE_GENERIC_Y,
346 .NotRange.DataIndex = 0,
349 .UsagePage = HID_USAGE_PAGE_GENERIC,
350 .BitField = 2,
351 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
352 .LinkCollection = 1,
353 .IsAbsolute = TRUE,
354 .BitSize = 16,
355 .ReportCount = 1,
356 .LogicalMax = -1,
357 .PhysicalMax = -1,
358 .NotRange.Usage = HID_USAGE_GENERIC_X,
359 .NotRange.DataIndex = 1,
362 .UsagePage = HID_USAGE_PAGE_GENERIC,
363 .BitField = 2,
364 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
365 .LinkCollection = 2,
366 .IsAbsolute = TRUE,
367 .BitSize = 16,
368 .ReportCount = 1,
369 .LogicalMax = -1,
370 .PhysicalMax = -1,
371 .NotRange.Usage = HID_USAGE_GENERIC_RY,
372 .NotRange.DataIndex = 2,
375 .UsagePage = HID_USAGE_PAGE_GENERIC,
376 .BitField = 2,
377 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
378 .LinkCollection = 2,
379 .IsAbsolute = TRUE,
380 .BitSize = 16,
381 .ReportCount = 1,
382 .LogicalMax = -1,
383 .PhysicalMax = -1,
384 .NotRange.Usage = HID_USAGE_GENERIC_RX,
385 .NotRange.DataIndex = 3,
388 .UsagePage = HID_USAGE_PAGE_GENERIC,
389 .BitField = 2,
390 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
391 .LinkCollection = 3,
392 .IsAbsolute = TRUE,
393 .BitSize = 16,
394 .ReportCount = 1,
395 .LogicalMax = -1,
396 .PhysicalMax = -1,
397 .NotRange.Usage = HID_USAGE_GENERIC_Z,
398 .NotRange.DataIndex = 4,
401 .UsagePage = HID_USAGE_PAGE_GENERIC,
402 .BitField = 66,
403 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
404 .LinkUsage = HID_USAGE_GENERIC_GAMEPAD,
405 .IsAbsolute = TRUE,
406 .HasNull = TRUE,
407 .BitSize = 4,
408 .Units = 14,
409 .ReportCount = 1,
410 .LogicalMin = 1,
411 .LogicalMax = 8,
412 .PhysicalMin = 0x0000,
413 .PhysicalMax = 0x103b,
414 .NotRange.Usage = HID_USAGE_GENERIC_HATSWITCH,
415 .NotRange.DataIndex =
416 attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff ? 21 :
420 static const HIDP_LINK_COLLECTION_NODE expect_collections[] =
423 .LinkUsage = HID_USAGE_GENERIC_GAMEPAD,
424 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
425 .CollectionType = 1,
426 .NumberOfChildren = 3,
427 .FirstChild = 3,
429 { .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .NextSibling = 0, },
430 { .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .NextSibling = 1, },
431 { .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .NextSibling = 2, },
434 HIDP_LINK_COLLECTION_NODE collections[16];
435 HIDP_BUTTON_CAPS button_caps[16];
436 HIDP_VALUE_CAPS value_caps[16];
437 XINPUT_STATE last_state, state;
438 XINPUT_CAPABILITIES xi_caps;
439 char buffer[200] = {0};
440 ULONG length, value;
441 USAGE usages[15];
442 NTSTATUS status;
443 USHORT count;
444 DWORD res;
445 BOOL ret;
446 int i;
448 res = pXInputGetCapabilities(index, 0, &xi_caps);
449 ok(res == ERROR_SUCCESS, "XInputGetCapabilities %lu returned %lu\n", index, res);
451 res = pXInputGetState(index, &state);
452 ok(res == ERROR_SUCCESS, "XInputGetState %lu returned %lu\n", index, res);
454 ok(hid_caps->UsagePage == HID_USAGE_PAGE_GENERIC, "unexpected usage page %04x\n", hid_caps->UsagePage);
455 ok(hid_caps->Usage == HID_USAGE_GENERIC_GAMEPAD, "unexpected usage %04x\n", hid_caps->Usage);
457 check_member(*hid_caps, expect_hid_caps, "%04x", Usage);
458 check_member(*hid_caps, expect_hid_caps, "%04x", UsagePage);
459 check_member(*hid_caps, expect_hid_caps, "%d", InputReportByteLength);
460 check_member(*hid_caps, expect_hid_caps, "%d", OutputReportByteLength);
461 check_member(*hid_caps, expect_hid_caps, "%d", FeatureReportByteLength);
462 check_member(*hid_caps, expect_hid_caps, "%d", NumberLinkCollectionNodes);
463 check_member(*hid_caps, expect_hid_caps, "%d", NumberInputButtonCaps);
464 check_member(*hid_caps, expect_hid_caps, "%d", NumberInputValueCaps);
465 check_member(*hid_caps, expect_hid_caps, "%d", NumberInputDataIndices);
466 check_member(*hid_caps, expect_hid_caps, "%d", NumberOutputButtonCaps);
467 check_member(*hid_caps, expect_hid_caps, "%d", NumberOutputValueCaps);
468 check_member(*hid_caps, expect_hid_caps, "%d", NumberOutputDataIndices);
469 check_member(*hid_caps, expect_hid_caps, "%d", NumberFeatureButtonCaps);
470 check_member(*hid_caps, expect_hid_caps, "%d", NumberFeatureValueCaps);
471 check_member(*hid_caps, expect_hid_caps, "%d", NumberFeatureDataIndices);
473 length = hid_caps->NumberLinkCollectionNodes;
474 status = HidP_GetLinkCollectionNodes(collections, &length, preparsed);
475 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetLinkCollectionNodes returned %#lx\n", status);
476 ok(length == ARRAY_SIZE(expect_collections), "got %lu collections\n", length);
478 for (i = 0; i < min(length, ARRAY_SIZE(expect_collections)); ++i)
480 winetest_push_context("collections[%d]", i);
481 check_member(collections[i], expect_collections[i], "%04x", LinkUsage);
482 check_member(collections[i], expect_collections[i], "%04x", LinkUsagePage);
483 check_member(collections[i], expect_collections[i], "%d", Parent);
484 check_member(collections[i], expect_collections[i], "%d", NumberOfChildren);
485 check_member(collections[i], expect_collections[i], "%d", NextSibling);
486 check_member(collections[i], expect_collections[i], "%d", FirstChild);
487 check_member(collections[i], expect_collections[i], "%d", CollectionType);
488 check_member(collections[i], expect_collections[i], "%d", IsAlias);
489 winetest_pop_context();
492 count = hid_caps->NumberInputButtonCaps;
493 status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, preparsed);
494 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetButtonCaps returned %#lx\n", status);
495 ok(count == ARRAY_SIZE(expect_button_caps), "got %d button caps\n", count);
497 for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i)
499 winetest_push_context("button_caps[%d]", i);
500 check_member(button_caps[i], expect_button_caps[i], "%04x", UsagePage);
501 check_member(button_caps[i], expect_button_caps[i], "%d", ReportID);
502 check_member(button_caps[i], expect_button_caps[i], "%d", IsAlias);
503 check_member(button_caps[i], expect_button_caps[i], "%d", BitField);
504 check_member(button_caps[i], expect_button_caps[i], "%d", LinkCollection);
505 check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsage);
506 check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsagePage);
507 check_member(button_caps[i], expect_button_caps[i], "%d", IsRange);
508 check_member(button_caps[i], expect_button_caps[i], "%d", IsStringRange);
509 check_member(button_caps[i], expect_button_caps[i], "%d", IsDesignatorRange);
510 check_member(button_caps[i], expect_button_caps[i], "%d", IsAbsolute);
512 if (!button_caps[i].IsRange && !expect_button_caps[i].IsRange)
514 check_member(button_caps[i], expect_button_caps[i], "%04x", NotRange.Usage);
515 check_member(button_caps[i], expect_button_caps[i], "%d", NotRange.DataIndex);
517 else if (button_caps[i].IsRange && expect_button_caps[i].IsRange)
519 check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMin);
520 check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMax);
521 check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMin);
522 check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMax);
525 if (!button_caps[i].IsRange && !expect_button_caps[i].IsRange)
526 check_member(button_caps[i], expect_button_caps[i], "%d", NotRange.StringIndex);
527 else if (button_caps[i].IsStringRange && expect_button_caps[i].IsStringRange)
529 check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMin);
530 check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMax);
533 if (!button_caps[i].IsDesignatorRange && !expect_button_caps[i].IsDesignatorRange)
534 check_member(button_caps[i], expect_button_caps[i], "%d", NotRange.DesignatorIndex);
535 else if (button_caps[i].IsDesignatorRange && expect_button_caps[i].IsDesignatorRange)
537 check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMin);
538 check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMax);
540 winetest_pop_context();
543 count = hid_caps->NumberInputValueCaps;
544 status = HidP_GetValueCaps(HidP_Input, value_caps, &count, preparsed);
545 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetValueCaps returned %#lx\n", status);
546 ok(count == ARRAY_SIZE(expect_value_caps), "got %d value caps\n", count);
548 for (i = 0; i < min(count, ARRAY_SIZE(expect_value_caps)); ++i)
550 winetest_push_context("value_caps[%d]", i);
551 check_member(value_caps[i], expect_value_caps[i], "%04x", UsagePage);
552 check_member(value_caps[i], expect_value_caps[i], "%d", ReportID);
553 check_member(value_caps[i], expect_value_caps[i], "%d", IsAlias);
554 check_member(value_caps[i], expect_value_caps[i], "%d", BitField);
555 check_member(value_caps[i], expect_value_caps[i], "%d", LinkCollection);
556 check_member(value_caps[i], expect_value_caps[i], "%d", LinkUsage);
557 check_member(value_caps[i], expect_value_caps[i], "%d", LinkUsagePage);
558 check_member(value_caps[i], expect_value_caps[i], "%d", IsRange);
559 check_member(value_caps[i], expect_value_caps[i], "%d", IsStringRange);
560 check_member(value_caps[i], expect_value_caps[i], "%d", IsDesignatorRange);
561 check_member(value_caps[i], expect_value_caps[i], "%d", IsAbsolute);
563 check_member(value_caps[i], expect_value_caps[i], "%d", HasNull);
564 check_member(value_caps[i], expect_value_caps[i], "%d", BitSize);
565 check_member(value_caps[i], expect_value_caps[i], "%d", ReportCount);
566 check_member(value_caps[i], expect_value_caps[i], "%#lx", UnitsExp);
567 check_member(value_caps[i], expect_value_caps[i], "%#lx", Units);
568 check_member(value_caps[i], expect_value_caps[i], "%+ld", LogicalMin);
569 check_member(value_caps[i], expect_value_caps[i], "%+ld", LogicalMax);
570 check_member(value_caps[i], expect_value_caps[i], "%+ld", PhysicalMin);
571 check_member(value_caps[i], expect_value_caps[i], "%+ld", PhysicalMax);
573 if (!value_caps[i].IsRange && !expect_value_caps[i].IsRange)
575 check_member(value_caps[i], expect_value_caps[i], "%04x", NotRange.Usage);
576 check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DataIndex);
578 else if (value_caps[i].IsRange && expect_value_caps[i].IsRange)
580 check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMin);
581 check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMax);
582 check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMin);
583 check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMax);
586 if (!value_caps[i].IsRange && !expect_value_caps[i].IsRange)
587 check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.StringIndex);
588 else if (value_caps[i].IsStringRange && expect_value_caps[i].IsStringRange)
590 check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMin);
591 check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMax);
594 if (!value_caps[i].IsDesignatorRange && !expect_value_caps[i].IsDesignatorRange)
595 check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DesignatorIndex);
596 else if (value_caps[i].IsDesignatorRange && expect_value_caps[i].IsDesignatorRange)
598 check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMin);
599 check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMax);
601 winetest_pop_context();
604 status = HidP_InitializeReportForID(HidP_Input, 0, preparsed, buffer, hid_caps->InputReportByteLength);
605 ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#lx\n", status);
607 SetLastError(0xdeadbeef);
608 memset(buffer, 0, sizeof(buffer));
609 ret = HidD_GetInputReport(device, buffer, hid_caps->InputReportByteLength);
610 ok(!ret, "HidD_GetInputReport succeeded\n");
611 ok(GetLastError() == ERROR_INVALID_PARAMETER, "HidD_GetInputReport returned error %lu\n", GetLastError());
613 if (!winetest_interactive) skip("skipping interactive tests\n");
614 /* ReadFile on Xbox One For Windows controller seems to never succeed */
615 else if (attrs->VendorID == 0x045e && attrs->ProductID == 0x02ff) skip("skipping interactive tests (Xbox One For Windows)\n");
616 else
618 res = pXInputGetState(index, &last_state);
619 ok(res == ERROR_SUCCESS, "XInputGetState returned %#lx\n", res);
621 trace("press A button on gamepad %lu\n", index);
625 Sleep(5);
626 res = pXInputGetState(index, &state);
627 ok(res == ERROR_SUCCESS, "XInputGetState returned %#lx\n", res);
628 } while (res == ERROR_SUCCESS && state.dwPacketNumber == last_state.dwPacketNumber);
629 ok(state.Gamepad.wButtons & XINPUT_GAMEPAD_A, "unexpected button state %#x\n", state.Gamepad.wButtons);
631 /* now read as many reports from the device to get a consistent final state */
632 for (i = 0; i < (state.dwPacketNumber - last_state.dwPacketNumber); ++i)
634 SetLastError(0xdeadbeef);
635 memset(buffer, 0, sizeof(buffer));
636 length = hid_caps->InputReportByteLength;
637 ret = ReadFile(device, buffer, hid_caps->InputReportByteLength, &length, NULL);
638 ok(ret, "ReadFile failed, last error %lu\n", GetLastError());
639 ok(length == hid_caps->InputReportByteLength, "ReadFile returned length %lu\n", length);
641 last_state = state;
643 length = ARRAY_SIZE(usages);
644 status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &length, preparsed, buffer, hid_caps->InputReportByteLength);
645 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#lx\n", status);
646 ok(length == 1, "got length %lu\n", length);
647 ok(usages[0] == 1, "got usages[0] %u\n", usages[0]);
649 trace("release A on gamepad %lu\n", index);
653 Sleep(5);
654 res = pXInputGetState(index, &state);
655 ok(res == ERROR_SUCCESS, "XInputGetState returned %#lx\n", res);
656 } while (res == ERROR_SUCCESS && state.dwPacketNumber == last_state.dwPacketNumber);
657 ok(!state.Gamepad.wButtons, "unexpected button state %#x\n", state.Gamepad.wButtons);
659 /* now read as many reports from the device to get a consistent final state */
660 for (i = 0; i < (state.dwPacketNumber - last_state.dwPacketNumber); ++i)
662 SetLastError(0xdeadbeef);
663 memset(buffer, 0, sizeof(buffer));
664 length = hid_caps->InputReportByteLength;
665 ret = ReadFile(device, buffer, hid_caps->InputReportByteLength, &length, NULL);
666 ok(ret, "ReadFile failed, last error %lu\n", GetLastError());
667 ok(length == hid_caps->InputReportByteLength, "ReadFile returned length %lu\n", length);
669 last_state = state;
671 length = ARRAY_SIZE(usages);
672 status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &length, preparsed, buffer, hid_caps->InputReportByteLength);
673 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#lx\n", status);
674 ok(length == 0, "got length %lu\n", length);
676 trace("press both LT and RT on gamepad %lu\n", index);
682 Sleep(5);
683 res = pXInputGetState(index, &state);
684 ok(res == ERROR_SUCCESS, "XInputGetState returned %#lx\n", res);
685 } while (res == ERROR_SUCCESS && state.dwPacketNumber == last_state.dwPacketNumber);
687 /* now read as many reports from the device to get a consistent final state */
688 for (i = 0; i < (state.dwPacketNumber - last_state.dwPacketNumber); ++i)
690 SetLastError(0xdeadbeef);
691 memset(buffer, 0, sizeof(buffer));
692 length = hid_caps->InputReportByteLength;
693 ret = ReadFile(device, buffer, hid_caps->InputReportByteLength, &length, NULL);
694 ok(ret, "ReadFile failed, last error %lu\n", GetLastError());
695 ok(length == hid_caps->InputReportByteLength, "ReadFile returned length %lu\n", length);
697 last_state = state;
699 value = 0;
700 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, preparsed, buffer, hid_caps->InputReportByteLength);
701 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#lx\n", status);
702 ok(value == state.Gamepad.sThumbLX + 32768, "got LX value %lu\n", value);
703 value = 0;
704 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, preparsed, buffer, hid_caps->InputReportByteLength);
705 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#lx\n", status);
706 ok(value == 32767 - state.Gamepad.sThumbLY, "got LY value %lu\n", value);
707 value = 0;
708 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, preparsed, buffer, hid_caps->InputReportByteLength);
709 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#lx\n", status);
710 ok(value == state.Gamepad.sThumbRX + 32768, "got LX value %lu\n", value);
711 value = 0;
712 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, preparsed, buffer, hid_caps->InputReportByteLength);
713 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#lx\n", status);
714 ok(value == 32767 - state.Gamepad.sThumbRY, "got LY value %lu\n", value);
715 value = 0;
716 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, preparsed, buffer, hid_caps->InputReportByteLength);
717 ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#lx\n", status);
718 ok(value == 32768 + (state.Gamepad.bLeftTrigger - state.Gamepad.bRightTrigger) * 128, "got Z value %lu (RT %d, LT %d)\n",
719 value, state.Gamepad.bRightTrigger, state.Gamepad.bLeftTrigger);
720 value = 0;
721 status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, preparsed, buffer, hid_caps->InputReportByteLength);
722 ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#lx\n", status);
723 } while (ret && (state.Gamepad.bRightTrigger != 255 || state.Gamepad.bLeftTrigger != 255));
727 static BOOL try_open_hid_device(const WCHAR *path, HANDLE *device, PHIDP_PREPARSED_DATA *preparsed,
728 HIDD_ATTRIBUTES *attrs, HIDP_CAPS *caps)
730 PHIDP_PREPARSED_DATA preparsed_data = NULL;
731 HANDLE device_file;
733 device_file = CreateFileW(path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE,
734 NULL, OPEN_EXISTING, 0, NULL);
735 if (device_file == INVALID_HANDLE_VALUE) return FALSE;
737 if (!HidD_GetPreparsedData(device_file, &preparsed_data)) goto failed;
738 if (!HidD_GetAttributes(device_file, attrs)) goto failed;
739 if (HidP_GetCaps(preparsed_data, caps) != HIDP_STATUS_SUCCESS) goto failed;
741 *device = device_file;
742 *preparsed = preparsed_data;
743 return TRUE;
745 failed:
746 CloseHandle(device_file);
747 HidD_FreePreparsedData(preparsed_data);
748 return FALSE;
751 static void test_hid_reports(void)
753 static const WCHAR prefix[] = L"\\\\?\\HID#VID_0000&PID_0000";
754 char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
755 SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer;
756 SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
757 SP_DEVINFO_DATA devinfo = {sizeof(devinfo)};
758 PHIDP_PREPARSED_DATA preparsed;
759 HIDD_ATTRIBUTES attrs;
760 HIDP_CAPS caps;
761 HDEVINFO set;
762 HANDLE device;
763 UINT32 i = 0, cnt = 0;
764 GUID hid;
766 HidD_GetHidGuid(&hid);
768 set = SetupDiGetClassDevsW(&hid, NULL, NULL, DIGCF_DEVICEINTERFACE);
769 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed, error %lu\n", GetLastError());
771 while (SetupDiEnumDeviceInterfaces(set, NULL, &hid, i++, &iface))
773 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
774 if (!SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, sizeof(buffer), NULL, &devinfo))
775 continue;
777 if (!try_open_hid_device(detail->DevicePath, &device, &preparsed, &attrs, &caps))
778 continue;
780 if (wcslen(detail->DevicePath) <= wcslen(prefix) ||
781 wcsnicmp(detail->DevicePath + wcslen(prefix), L"&IG_", 4 ))
782 continue;
784 trace("found xinput HID device %s\n", wine_dbgstr_w(detail->DevicePath));
785 check_hid_caps(cnt++, device, preparsed, &attrs, &caps);
787 CloseHandle(device);
788 HidD_FreePreparsedData(preparsed);
791 SetupDiDestroyDeviceInfoList(set);
794 START_TEST(xinput)
796 struct
798 const char *name;
799 int version;
800 } libs[] = {
801 { "xinput1_1.dll", 1 },
802 { "xinput1_2.dll", 2 },
803 { "xinput1_3.dll", 3 },
804 { "xinput1_4.dll", 4 },
805 { "xinput9_1_0.dll", 0 } /* legacy for XP/Vista */
807 HMODULE hXinput;
808 void *pXInputGetStateEx_Ordinal;
809 int i;
811 for (i = 0; i < ARRAY_SIZE(libs); i++)
813 hXinput = LoadLibraryA( libs[i].name );
815 if (!hXinput)
817 win_skip("Could not load %s\n", libs[i].name);
818 continue;
820 trace("Testing %s\n", libs[i].name);
822 pXInputEnable = (void*)GetProcAddress(hXinput, "XInputEnable");
823 pXInputSetState = (void*)GetProcAddress(hXinput, "XInputSetState");
824 pXInputGetState = (void*)GetProcAddress(hXinput, "XInputGetState");
825 pXInputGetStateEx = (void*)GetProcAddress(hXinput, "XInputGetStateEx"); /* Win >= 8 */
826 pXInputGetStateEx_Ordinal = (void*)GetProcAddress(hXinput, (LPCSTR) 100);
827 pXInputGetKeystroke = (void*)GetProcAddress(hXinput, "XInputGetKeystroke");
828 pXInputGetCapabilities = (void*)GetProcAddress(hXinput, "XInputGetCapabilities");
829 pXInputGetDSoundAudioDeviceGuids = (void*)GetProcAddress(hXinput, "XInputGetDSoundAudioDeviceGuids");
830 pXInputGetBatteryInformation = (void*)GetProcAddress(hXinput, "XInputGetBatteryInformation");
832 /* XInputGetStateEx may not be present by name, use ordinal in this case */
833 if (!pXInputGetStateEx)
834 pXInputGetStateEx = pXInputGetStateEx_Ordinal;
836 test_hid_reports();
837 test_set_state();
838 test_get_state();
839 test_get_capabilities();
841 if (libs[i].version != 4)
842 test_get_dsoundaudiodevice();
843 else
844 ok(!pXInputGetDSoundAudioDeviceGuids, "XInputGetDSoundAudioDeviceGuids exists in %s\n", libs[i].name);
846 if (libs[i].version > 2)
848 test_get_keystroke();
849 test_get_batteryinformation();
850 ok(pXInputGetStateEx != NULL, "XInputGetStateEx not found in %s\n", libs[i].name);
852 else
854 ok(!pXInputGetKeystroke, "XInputGetKeystroke exists in %s\n", libs[i].name);
855 ok(!pXInputGetStateEx, "XInputGetStateEx exists in %s\n", libs[i].name);
856 ok(!pXInputGetBatteryInformation, "XInputGetBatteryInformation exists in %s\n", libs[i].name);
857 if (libs[i].version == 0)
858 ok(!pXInputEnable, "XInputEnable exists in %s\n", libs[i].name);
861 FreeLibrary(hXinput);