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
24 #include "wine/test.h"
26 static DWORD (WINAPI
*pXInputGetState
)(DWORD
, XINPUT_STATE
*);
27 static DWORD (WINAPI
*pXInputGetStateEx
)(DWORD
, XINPUT_STATE_EX
*);
28 static DWORD (WINAPI
*pXInputGetCapabilities
)(DWORD
,DWORD
,XINPUT_CAPABILITIES
*);
29 static DWORD (WINAPI
*pXInputSetState
)(DWORD
, XINPUT_VIBRATION
*);
30 static void (WINAPI
*pXInputEnable
)(BOOL
);
31 static DWORD (WINAPI
*pXInputGetKeystroke
)(DWORD
, DWORD
, PXINPUT_KEYSTROKE
);
32 static DWORD (WINAPI
*pXInputGetDSoundAudioDeviceGuids
)(DWORD
, GUID
*, GUID
*);
33 static DWORD (WINAPI
*pXInputGetBatteryInformation
)(DWORD
, BYTE
, XINPUT_BATTERY_INFORMATION
*);
35 static void dump_gamepad(XINPUT_GAMEPAD
*data
)
37 trace("-- Gamepad Variables --\n");
38 trace("Gamepad.wButtons: %#x\n", data
->wButtons
);
39 trace("Gamepad.bLeftTrigger: %d\n", data
->bLeftTrigger
);
40 trace("Gamepad.bRightTrigger: %d\n", data
->bRightTrigger
);
41 trace("Gamepad.sThumbLX: %d\n", data
->sThumbLX
);
42 trace("Gamepad.sThumbLY: %d\n", data
->sThumbLY
);
43 trace("Gamepad.sThumbRX: %d\n", data
->sThumbRX
);
44 trace("Gamepad.sThumbRY: %d\n\n", data
->sThumbRY
);
47 static void test_set_state(void)
49 XINPUT_VIBRATION vibrator
;
53 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
55 ZeroMemory(&vibrator
, sizeof(XINPUT_VIBRATION
));
57 vibrator
.wLeftMotorSpeed
= 32767;
58 vibrator
.wRightMotorSpeed
= 32767;
59 result
= pXInputSetState(controllerNum
, &vibrator
);
60 if (result
== ERROR_DEVICE_NOT_CONNECTED
) continue;
63 vibrator
.wLeftMotorSpeed
= 0;
64 vibrator
.wRightMotorSpeed
= 0;
65 result
= pXInputSetState(controllerNum
, &vibrator
);
66 ok(result
== ERROR_SUCCESS
, "XInputSetState failed with (%d)\n", result
);
68 /* Disabling XInput here, queueing a vibration and then re-enabling XInput
69 * is used to prove that vibrations are auto enabled when resuming XInput.
70 * If XInputEnable(1) is removed below the vibration will never play. */
71 if (pXInputEnable
) pXInputEnable(0);
74 vibrator
.wLeftMotorSpeed
= 65535;
75 vibrator
.wRightMotorSpeed
= 65535;
76 result
= pXInputSetState(controllerNum
, &vibrator
);
77 ok(result
== ERROR_SUCCESS
, "XInputSetState failed with (%d)\n", result
);
79 if (pXInputEnable
) pXInputEnable(1);
82 vibrator
.wLeftMotorSpeed
= 0;
83 vibrator
.wRightMotorSpeed
= 0;
84 result
= pXInputSetState(controllerNum
, &vibrator
);
85 ok(result
== ERROR_SUCCESS
, "XInputSetState failed with (%d)\n", result
);
88 result
= pXInputSetState(XUSER_MAX_COUNT
+1, &vibrator
);
89 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputSetState returned (%d)\n", result
);
92 static void test_get_state(void)
97 XINPUT_STATE_EX state_ex
;
99 DWORD controllerNum
, i
, result
, good
= XUSER_MAX_COUNT
;
101 for (i
= 0; i
< (pXInputGetStateEx
? 2 : 1); i
++)
103 for (controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
105 ZeroMemory(&xinput
, sizeof(xinput
));
108 result
= pXInputGetState(controllerNum
, &xinput
.state
);
110 result
= pXInputGetStateEx(controllerNum
, &xinput
.state_ex
);
111 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
,
112 "%s failed with (%d)\n", i
== 0 ? "XInputGetState" : "XInputGetStateEx", result
);
114 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
116 skip("Controller %d is not connected\n", controllerNum
);
120 trace("-- Results for controller %d --\n", controllerNum
);
123 good
= controllerNum
;
124 trace("XInputGetState: %d\n", result
);
127 trace("XInputGetStateEx: %d\n", result
);
128 trace("State->dwPacketNumber: %d\n", xinput
.state
.dwPacketNumber
);
129 dump_gamepad(&xinput
.state
.Gamepad
);
133 result
= pXInputGetState(XUSER_MAX_COUNT
, &xinput
.state
);
134 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
136 result
= pXInputGetState(XUSER_MAX_COUNT
+1, &xinput
.state
);
137 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
138 if (pXInputGetStateEx
)
140 result
= pXInputGetStateEx(XUSER_MAX_COUNT
, &xinput
.state_ex
);
141 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
143 result
= pXInputGetStateEx(XUSER_MAX_COUNT
+1, &xinput
.state_ex
);
144 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
147 if (winetest_interactive
&& good
< XUSER_MAX_COUNT
)
149 DWORD now
= GetTickCount(), packet
= 0;
150 XINPUT_GAMEPAD
*game
= &xinput
.state
.Gamepad
;
152 trace("You have 20 seconds to test the joystick freely\n");
156 pXInputGetState(good
, &xinput
.state
);
157 if (xinput
.state
.dwPacketNumber
== packet
)
160 packet
= xinput
.state
.dwPacketNumber
;
161 trace("Buttons 0x%04X Triggers %3d/%3d LT %6d/%6d RT %6d/%6d\n",
162 game
->wButtons
, game
->bLeftTrigger
, game
->bRightTrigger
,
163 game
->sThumbLX
, game
->sThumbLY
, game
->sThumbRX
, game
->sThumbRY
);
165 while(GetTickCount() - now
< 20000);
166 trace("Test over...\n");
170 static void test_get_keystroke(void)
172 XINPUT_KEYSTROKE keystroke
;
176 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
178 ZeroMemory(&keystroke
, sizeof(XINPUT_KEYSTROKE
));
180 result
= pXInputGetKeystroke(controllerNum
, XINPUT_FLAG_GAMEPAD
, &keystroke
);
181 ok(result
== ERROR_EMPTY
|| result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
,
182 "XInputGetKeystroke failed with (%d)\n", result
);
184 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
186 skip("Controller %d is not connected\n", controllerNum
);
190 ZeroMemory(&keystroke
, sizeof(XINPUT_KEYSTROKE
));
191 result
= pXInputGetKeystroke(XUSER_MAX_COUNT
+1, XINPUT_FLAG_GAMEPAD
, &keystroke
);
192 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetKeystroke returned (%d)\n", result
);
195 static void test_get_capabilities(void)
197 XINPUT_CAPABILITIES capabilities
;
201 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
203 ZeroMemory(&capabilities
, sizeof(XINPUT_CAPABILITIES
));
205 result
= pXInputGetCapabilities(controllerNum
, XINPUT_FLAG_GAMEPAD
, &capabilities
);
206 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetCapabilities failed with (%d)\n", result
);
208 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
210 skip("Controller %d is not connected\n", controllerNum
);
214 /* Important to show that the results changed between 1.3 and 1.4 XInput version */
215 dump_gamepad(&capabilities
.Gamepad
);
218 ZeroMemory(&capabilities
, sizeof(XINPUT_CAPABILITIES
));
219 result
= pXInputGetCapabilities(XUSER_MAX_COUNT
+1, XINPUT_FLAG_GAMEPAD
, &capabilities
);
220 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetCapabilities returned (%d)\n", result
);
223 static void test_get_dsoundaudiodevice(void)
227 GUID soundRender
, soundCapture
;
228 GUID testGuid
= {0xFFFFFFFF, 0xFFFF, 0xFFFF, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
229 GUID emptyGuid
= {0x0, 0x0, 0x0, {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
231 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
233 soundRender
= soundCapture
= testGuid
;
234 result
= pXInputGetDSoundAudioDeviceGuids(controllerNum
, &soundRender
, &soundCapture
);
235 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetDSoundAudioDeviceGuids failed with (%d)\n", result
);
237 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
239 skip("Controller %d is not connected\n", controllerNum
);
243 if (!IsEqualGUID(&soundRender
, &emptyGuid
))
244 ok(!IsEqualGUID(&soundRender
, &testGuid
), "Broken GUID returned for sound render device\n");
246 trace("Headset phone not attached\n");
248 if (!IsEqualGUID(&soundCapture
, &emptyGuid
))
249 ok(!IsEqualGUID(&soundCapture
, &testGuid
), "Broken GUID returned for sound capture device\n");
251 trace("Headset microphone not attached\n");
254 result
= pXInputGetDSoundAudioDeviceGuids(XUSER_MAX_COUNT
+1, &soundRender
, &soundCapture
);
255 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetDSoundAudioDeviceGuids returned (%d)\n", result
);
258 static void test_get_batteryinformation(void)
262 XINPUT_BATTERY_INFORMATION batteryInfo
;
264 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
266 ZeroMemory(&batteryInfo
, sizeof(XINPUT_BATTERY_INFORMATION
));
268 result
= pXInputGetBatteryInformation(controllerNum
, BATTERY_DEVTYPE_GAMEPAD
, &batteryInfo
);
269 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetBatteryInformation failed with (%d)\n", result
);
271 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
273 ok(batteryInfo
.BatteryLevel
== BATTERY_TYPE_DISCONNECTED
, "Failed to report device as being disconnected.\n");
274 skip("Controller %d is not connected\n", controllerNum
);
278 result
= pXInputGetBatteryInformation(XUSER_MAX_COUNT
+1, BATTERY_DEVTYPE_GAMEPAD
, &batteryInfo
);
279 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetBatteryInformation returned (%d)\n", result
);
289 { "xinput1_1.dll", 1 },
290 { "xinput1_2.dll", 2 },
291 { "xinput1_3.dll", 3 },
292 { "xinput1_4.dll", 4 },
293 { "xinput9_1_0.dll", 0 } /* legacy for XP/Vista */
296 void *pXInputGetStateEx_Ordinal
;
299 for (i
= 0; i
< sizeof(libs
) / sizeof(libs
[0]); i
++)
301 hXinput
= LoadLibraryA( libs
[i
].name
);
305 win_skip("Could not load %s\n", libs
[i
].name
);
308 trace("Testing %s\n", libs
[i
].name
);
310 pXInputEnable
= (void*)GetProcAddress(hXinput
, "XInputEnable");
311 pXInputSetState
= (void*)GetProcAddress(hXinput
, "XInputSetState");
312 pXInputGetState
= (void*)GetProcAddress(hXinput
, "XInputGetState");
313 pXInputGetStateEx
= (void*)GetProcAddress(hXinput
, "XInputGetStateEx"); /* Win >= 8 */
314 pXInputGetStateEx_Ordinal
= (void*)GetProcAddress(hXinput
, (LPCSTR
) 100);
315 pXInputGetKeystroke
= (void*)GetProcAddress(hXinput
, "XInputGetKeystroke");
316 pXInputGetCapabilities
= (void*)GetProcAddress(hXinput
, "XInputGetCapabilities");
317 pXInputGetDSoundAudioDeviceGuids
= (void*)GetProcAddress(hXinput
, "XInputGetDSoundAudioDeviceGuids");
318 pXInputGetBatteryInformation
= (void*)GetProcAddress(hXinput
, "XInputGetBatteryInformation");
320 /* XInputGetStateEx may not be present by name, use ordinal in this case */
321 if (!pXInputGetStateEx
)
322 pXInputGetStateEx
= pXInputGetStateEx_Ordinal
;
326 test_get_capabilities();
328 if (libs
[i
].version
!= 4)
329 test_get_dsoundaudiodevice();
331 ok(!pXInputGetDSoundAudioDeviceGuids
, "XInputGetDSoundAudioDeviceGuids exists in %s\n", libs
[i
].name
);
333 if (libs
[i
].version
> 2)
335 test_get_keystroke();
336 test_get_batteryinformation();
337 ok(pXInputGetStateEx
!= NULL
, "XInputGetStateEx not found in %s\n", libs
[i
].name
);
341 ok(!pXInputGetKeystroke
, "XInputGetKeystroke exists in %s\n", libs
[i
].name
);
342 ok(!pXInputGetStateEx
, "XInputGetStateEx exists in %s\n", libs
[i
].name
);
343 ok(!pXInputGetBatteryInformation
, "XInputGetBatteryInformation exists in %s\n", libs
[i
].name
);
344 if (libs
[i
].version
== 0)
345 ok(!pXInputEnable
, "XInputEnable exists in %s\n", libs
[i
].name
);
348 FreeLibrary(hXinput
);