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
*);
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)
95 DWORD controllerNum
, i
, result
, good
= XUSER_MAX_COUNT
;
97 for (i
= 0; i
< (pXInputGetStateEx
? 2 : 1); i
++)
99 for (controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
101 ZeroMemory(&state
, sizeof(state
));
104 result
= pXInputGetState(controllerNum
, &state
);
106 result
= pXInputGetStateEx(controllerNum
, &state
);
107 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
,
108 "%s failed with (%d)\n", i
== 0 ? "XInputGetState" : "XInputGetStateEx", result
);
110 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
112 skip("Controller %d is not connected\n", controllerNum
);
116 trace("-- Results for controller %d --\n", controllerNum
);
119 good
= controllerNum
;
120 trace("XInputGetState: %d\n", result
);
123 trace("XInputGetStateEx: %d\n", result
);
124 trace("State->dwPacketNumber: %d\n", state
.dwPacketNumber
);
125 dump_gamepad(&state
.Gamepad
);
129 result
= pXInputGetState(0, NULL
);
130 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
132 result
= pXInputGetState(XUSER_MAX_COUNT
, &state
);
133 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
135 result
= pXInputGetState(XUSER_MAX_COUNT
+1, &state
);
136 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
137 if (pXInputGetStateEx
)
139 result
= pXInputGetStateEx(XUSER_MAX_COUNT
, &state
);
140 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
142 result
= pXInputGetStateEx(XUSER_MAX_COUNT
+1, &state
);
143 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetState returned (%d)\n", result
);
146 if (winetest_interactive
&& good
< XUSER_MAX_COUNT
)
148 DWORD now
= GetTickCount(), packet
= 0;
149 XINPUT_GAMEPAD
*game
= &state
.Gamepad
;
151 trace("You have 20 seconds to test the joystick freely\n");
155 pXInputGetState(good
, &state
);
156 if (state
.dwPacketNumber
== packet
)
159 packet
= state
.dwPacketNumber
;
160 trace("Buttons 0x%04X Triggers %3d/%3d LT %6d/%6d RT %6d/%6d\n",
161 game
->wButtons
, game
->bLeftTrigger
, game
->bRightTrigger
,
162 game
->sThumbLX
, game
->sThumbLY
, game
->sThumbRX
, game
->sThumbRY
);
164 while(GetTickCount() - now
< 20000);
165 trace("Test over...\n");
169 static void test_get_keystroke(void)
171 XINPUT_KEYSTROKE keystroke
;
175 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
177 ZeroMemory(&keystroke
, sizeof(XINPUT_KEYSTROKE
));
179 result
= pXInputGetKeystroke(controllerNum
, XINPUT_FLAG_GAMEPAD
, &keystroke
);
180 ok(result
== ERROR_EMPTY
|| result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
,
181 "XInputGetKeystroke failed with (%d)\n", result
);
183 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
185 skip("Controller %d is not connected\n", controllerNum
);
189 ZeroMemory(&keystroke
, sizeof(XINPUT_KEYSTROKE
));
190 result
= pXInputGetKeystroke(XUSER_MAX_COUNT
+1, XINPUT_FLAG_GAMEPAD
, &keystroke
);
191 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetKeystroke returned (%d)\n", result
);
194 static void test_get_capabilities(void)
196 XINPUT_CAPABILITIES capabilities
;
200 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
202 ZeroMemory(&capabilities
, sizeof(XINPUT_CAPABILITIES
));
204 result
= pXInputGetCapabilities(controllerNum
, XINPUT_FLAG_GAMEPAD
, &capabilities
);
205 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetCapabilities failed with (%d)\n", result
);
207 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
209 skip("Controller %d is not connected\n", controllerNum
);
213 /* Important to show that the results changed between 1.3 and 1.4 XInput version */
214 dump_gamepad(&capabilities
.Gamepad
);
217 ZeroMemory(&capabilities
, sizeof(XINPUT_CAPABILITIES
));
218 result
= pXInputGetCapabilities(XUSER_MAX_COUNT
+1, XINPUT_FLAG_GAMEPAD
, &capabilities
);
219 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetCapabilities returned (%d)\n", result
);
222 static void test_get_dsoundaudiodevice(void)
226 GUID soundRender
, soundCapture
;
227 GUID testGuid
= {0xFFFFFFFF, 0xFFFF, 0xFFFF, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
228 GUID emptyGuid
= {0x0, 0x0, 0x0, {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
230 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
232 soundRender
= soundCapture
= testGuid
;
233 result
= pXInputGetDSoundAudioDeviceGuids(controllerNum
, &soundRender
, &soundCapture
);
234 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetDSoundAudioDeviceGuids failed with (%d)\n", result
);
236 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
238 skip("Controller %d is not connected\n", controllerNum
);
242 if (!IsEqualGUID(&soundRender
, &emptyGuid
))
243 ok(!IsEqualGUID(&soundRender
, &testGuid
), "Broken GUID returned for sound render device\n");
245 trace("Headset phone not attached\n");
247 if (!IsEqualGUID(&soundCapture
, &emptyGuid
))
248 ok(!IsEqualGUID(&soundCapture
, &testGuid
), "Broken GUID returned for sound capture device\n");
250 trace("Headset microphone not attached\n");
253 result
= pXInputGetDSoundAudioDeviceGuids(XUSER_MAX_COUNT
+1, &soundRender
, &soundCapture
);
254 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetDSoundAudioDeviceGuids returned (%d)\n", result
);
257 static void test_get_batteryinformation(void)
261 XINPUT_BATTERY_INFORMATION batteryInfo
;
263 for(controllerNum
= 0; controllerNum
< XUSER_MAX_COUNT
; controllerNum
++)
265 ZeroMemory(&batteryInfo
, sizeof(XINPUT_BATTERY_INFORMATION
));
267 result
= pXInputGetBatteryInformation(controllerNum
, BATTERY_DEVTYPE_GAMEPAD
, &batteryInfo
);
268 ok(result
== ERROR_SUCCESS
|| result
== ERROR_DEVICE_NOT_CONNECTED
, "XInputGetBatteryInformation failed with (%d)\n", result
);
270 if (ERROR_DEVICE_NOT_CONNECTED
== result
)
272 ok(batteryInfo
.BatteryLevel
== BATTERY_TYPE_DISCONNECTED
, "Failed to report device as being disconnected.\n");
273 skip("Controller %d is not connected\n", controllerNum
);
277 result
= pXInputGetBatteryInformation(XUSER_MAX_COUNT
+1, BATTERY_DEVTYPE_GAMEPAD
, &batteryInfo
);
278 ok(result
== ERROR_BAD_ARGUMENTS
, "XInputGetBatteryInformation returned (%d)\n", result
);
288 { "xinput1_1.dll", 1 },
289 { "xinput1_2.dll", 2 },
290 { "xinput1_3.dll", 3 },
291 { "xinput1_4.dll", 4 },
292 { "xinput9_1_0.dll", 0 } /* legacy for XP/Vista */
295 void *pXInputGetStateEx_Ordinal
;
298 for (i
= 0; i
< ARRAY_SIZE(libs
); i
++)
300 hXinput
= LoadLibraryA( libs
[i
].name
);
304 win_skip("Could not load %s\n", libs
[i
].name
);
307 trace("Testing %s\n", libs
[i
].name
);
309 pXInputEnable
= (void*)GetProcAddress(hXinput
, "XInputEnable");
310 pXInputSetState
= (void*)GetProcAddress(hXinput
, "XInputSetState");
311 pXInputGetState
= (void*)GetProcAddress(hXinput
, "XInputGetState");
312 pXInputGetStateEx
= (void*)GetProcAddress(hXinput
, "XInputGetStateEx"); /* Win >= 8 */
313 pXInputGetStateEx_Ordinal
= (void*)GetProcAddress(hXinput
, (LPCSTR
) 100);
314 pXInputGetKeystroke
= (void*)GetProcAddress(hXinput
, "XInputGetKeystroke");
315 pXInputGetCapabilities
= (void*)GetProcAddress(hXinput
, "XInputGetCapabilities");
316 pXInputGetDSoundAudioDeviceGuids
= (void*)GetProcAddress(hXinput
, "XInputGetDSoundAudioDeviceGuids");
317 pXInputGetBatteryInformation
= (void*)GetProcAddress(hXinput
, "XInputGetBatteryInformation");
319 /* XInputGetStateEx may not be present by name, use ordinal in this case */
320 if (!pXInputGetStateEx
)
321 pXInputGetStateEx
= pXInputGetStateEx_Ordinal
;
325 test_get_capabilities();
327 if (libs
[i
].version
!= 4)
328 test_get_dsoundaudiodevice();
330 ok(!pXInputGetDSoundAudioDeviceGuids
, "XInputGetDSoundAudioDeviceGuids exists in %s\n", libs
[i
].name
);
332 if (libs
[i
].version
> 2)
334 test_get_keystroke();
335 test_get_batteryinformation();
336 ok(pXInputGetStateEx
!= NULL
, "XInputGetStateEx not found in %s\n", libs
[i
].name
);
340 ok(!pXInputGetKeystroke
, "XInputGetKeystroke exists in %s\n", libs
[i
].name
);
341 ok(!pXInputGetStateEx
, "XInputGetStateEx exists in %s\n", libs
[i
].name
);
342 ok(!pXInputGetBatteryInformation
, "XInputGetBatteryInformation exists in %s\n", libs
[i
].name
);
343 if (libs
[i
].version
== 0)
344 ok(!pXInputEnable
, "XInputEnable exists in %s\n", libs
[i
].name
);
347 FreeLibrary(hXinput
);