ReactOS  0.4.15-dev-425-gc40b086
xinput.c
Go to the documentation of this file.
1 /*
2  * The Wine project - Xinput Joystick Library
3  * Copyright 2008 Andrew Fenn
4  *
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.
9  *
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.
14  *
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
18  */
19 
20 #include <windows.h>
21 #include <stdio.h>
22 
23 #include "xinput.h"
24 #include "wine/test.h"
25 
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*);
34 
36 {
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);
45 }
46 
47 static void test_set_state(void)
48 {
49  XINPUT_VIBRATION vibrator;
50  DWORD controllerNum;
51  DWORD result;
52 
53  for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
54  {
55  ZeroMemory(&vibrator, sizeof(XINPUT_VIBRATION));
56 
57  vibrator.wLeftMotorSpeed = 32767;
58  vibrator.wRightMotorSpeed = 32767;
59  result = pXInputSetState(controllerNum, &vibrator);
60  if (result == ERROR_DEVICE_NOT_CONNECTED) continue;
61 
62  Sleep(250);
63  vibrator.wLeftMotorSpeed = 0;
64  vibrator.wRightMotorSpeed = 0;
65  result = pXInputSetState(controllerNum, &vibrator);
66  ok(result == ERROR_SUCCESS, "XInputSetState failed with (%d)\n", result);
67 
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);
72 
73  Sleep(250);
74  vibrator.wLeftMotorSpeed = 65535;
75  vibrator.wRightMotorSpeed = 65535;
76  result = pXInputSetState(controllerNum, &vibrator);
77  ok(result == ERROR_SUCCESS, "XInputSetState failed with (%d)\n", result);
78 
79  if (pXInputEnable) pXInputEnable(1);
80  Sleep(250);
81 
82  vibrator.wLeftMotorSpeed = 0;
83  vibrator.wRightMotorSpeed = 0;
84  result = pXInputSetState(controllerNum, &vibrator);
85  ok(result == ERROR_SUCCESS, "XInputSetState failed with (%d)\n", result);
86  }
87 
88  result = pXInputSetState(XUSER_MAX_COUNT+1, &vibrator);
89  ok(result == ERROR_BAD_ARGUMENTS, "XInputSetState returned (%d)\n", result);
90 }
91 
92 static void test_get_state(void)
93 {
95  DWORD controllerNum, i, result, good = XUSER_MAX_COUNT;
96 
97  for (i = 0; i < (pXInputGetStateEx ? 2 : 1); i++)
98  {
99  for (controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
100  {
101  ZeroMemory(&state, sizeof(state));
102 
103  if (i == 0)
104  result = pXInputGetState(controllerNum, &state);
105  else
106  result = pXInputGetStateEx(controllerNum, &state);
108  "%s failed with (%d)\n", i == 0 ? "XInputGetState" : "XInputGetStateEx", result);
109 
111  {
112  skip("Controller %d is not connected\n", controllerNum);
113  continue;
114  }
115 
116  trace("-- Results for controller %d --\n", controllerNum);
117  if (i == 0)
118  {
119  good = controllerNum;
120  trace("XInputGetState: %d\n", result);
121  }
122  else
123  trace("XInputGetStateEx: %d\n", result);
124  trace("State->dwPacketNumber: %d\n", state.dwPacketNumber);
125  dump_gamepad(&state.Gamepad);
126  }
127  }
128 
129  result = pXInputGetState(0, NULL);
130  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned (%d)\n", result);
131 
132  result = pXInputGetState(XUSER_MAX_COUNT, &state);
133  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned (%d)\n", result);
134 
135  result = pXInputGetState(XUSER_MAX_COUNT+1, &state);
136  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned (%d)\n", result);
137  if (pXInputGetStateEx)
138  {
139  result = pXInputGetStateEx(XUSER_MAX_COUNT, &state);
140  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned (%d)\n", result);
141 
142  result = pXInputGetStateEx(XUSER_MAX_COUNT+1, &state);
143  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetState returned (%d)\n", result);
144  }
145 
147  {
148  DWORD now = GetTickCount(), packet = 0;
149  XINPUT_GAMEPAD *game = &state.Gamepad;
150 
151  trace("You have 20 seconds to test the joystick freely\n");
152  do
153  {
154  Sleep(100);
155  pXInputGetState(good, &state);
156  if (state.dwPacketNumber == packet)
157  continue;
158 
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);
163  }
164  while(GetTickCount() - now < 20000);
165  trace("Test over...\n");
166  }
167 }
168 
169 static void test_get_keystroke(void)
170 {
171  XINPUT_KEYSTROKE keystroke;
172  DWORD controllerNum;
173  DWORD result;
174 
175  for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
176  {
177  ZeroMemory(&keystroke, sizeof(XINPUT_KEYSTROKE));
178 
179  result = pXInputGetKeystroke(controllerNum, XINPUT_FLAG_GAMEPAD, &keystroke);
181  "XInputGetKeystroke failed with (%d)\n", result);
182 
184  {
185  skip("Controller %d is not connected\n", controllerNum);
186  }
187  }
188 
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);
192 }
193 
194 static void test_get_capabilities(void)
195 {
196  XINPUT_CAPABILITIES capabilities;
197  DWORD controllerNum;
198  DWORD result;
199 
200  for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
201  {
202  ZeroMemory(&capabilities, sizeof(XINPUT_CAPABILITIES));
203 
204  result = pXInputGetCapabilities(controllerNum, XINPUT_FLAG_GAMEPAD, &capabilities);
205  ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED, "XInputGetCapabilities failed with (%d)\n", result);
206 
208  {
209  skip("Controller %d is not connected\n", controllerNum);
210  continue;
211  }
212 
213  /* Important to show that the results changed between 1.3 and 1.4 XInput version */
214  dump_gamepad(&capabilities.Gamepad);
215  }
216 
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);
220 }
221 
222 static void test_get_dsoundaudiodevice(void)
223 {
224  DWORD controllerNum;
225  DWORD result;
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}};
229 
230  for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
231  {
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);
235 
237  {
238  skip("Controller %d is not connected\n", controllerNum);
239  continue;
240  }
241 
242  if (!IsEqualGUID(&soundRender, &emptyGuid))
243  ok(!IsEqualGUID(&soundRender, &testGuid), "Broken GUID returned for sound render device\n");
244  else
245  trace("Headset phone not attached\n");
246 
247  if (!IsEqualGUID(&soundCapture, &emptyGuid))
248  ok(!IsEqualGUID(&soundCapture, &testGuid), "Broken GUID returned for sound capture device\n");
249  else
250  trace("Headset microphone not attached\n");
251  }
252 
253  result = pXInputGetDSoundAudioDeviceGuids(XUSER_MAX_COUNT+1, &soundRender, &soundCapture);
254  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetDSoundAudioDeviceGuids returned (%d)\n", result);
255 }
256 
258 {
259  DWORD controllerNum;
260  DWORD result;
261  XINPUT_BATTERY_INFORMATION batteryInfo;
262 
263  for(controllerNum = 0; controllerNum < XUSER_MAX_COUNT; controllerNum++)
264  {
265  ZeroMemory(&batteryInfo, sizeof(XINPUT_BATTERY_INFORMATION));
266 
267  result = pXInputGetBatteryInformation(controllerNum, BATTERY_DEVTYPE_GAMEPAD, &batteryInfo);
268  ok(result == ERROR_SUCCESS || result == ERROR_DEVICE_NOT_CONNECTED, "XInputGetBatteryInformation failed with (%d)\n", result);
269 
271  {
272  ok(batteryInfo.BatteryLevel == BATTERY_TYPE_DISCONNECTED, "Failed to report device as being disconnected.\n");
273  skip("Controller %d is not connected\n", controllerNum);
274  }
275  }
276 
277  result = pXInputGetBatteryInformation(XUSER_MAX_COUNT+1, BATTERY_DEVTYPE_GAMEPAD, &batteryInfo);
278  ok(result == ERROR_BAD_ARGUMENTS, "XInputGetBatteryInformation returned (%d)\n", result);
279 }
280 
281 START_TEST(xinput)
282 {
283  struct
284  {
285  const char *name;
286  int version;
287  } libs[] = {
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 */
293  };
294  HMODULE hXinput;
295  void *pXInputGetStateEx_Ordinal;
296  int i;
297 
298  for (i = 0; i < ARRAY_SIZE(libs); i++)
299  {
300  hXinput = LoadLibraryA( libs[i].name );
301 
302  if (!hXinput)
303  {
304  win_skip("Could not load %s\n", libs[i].name);
305  continue;
306  }
307  trace("Testing %s\n", libs[i].name);
308 
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");
318 
319  /* XInputGetStateEx may not be present by name, use ordinal in this case */
320  if (!pXInputGetStateEx)
321  pXInputGetStateEx = pXInputGetStateEx_Ordinal;
322 
323  test_set_state();
324  test_get_state();
326 
327  if (libs[i].version != 4)
329  else
330  ok(!pXInputGetDSoundAudioDeviceGuids, "XInputGetDSoundAudioDeviceGuids exists in %s\n", libs[i].name);
331 
332  if (libs[i].version > 2)
333  {
336  ok(pXInputGetStateEx != NULL, "XInputGetStateEx not found in %s\n", libs[i].name);
337  }
338  else
339  {
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);
345  }
346 
347  FreeLibrary(hXinput);
348  }
349 }
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static XINPUT_STATE *static XINPUT_STATE *static XINPUT_CAPABILITIES *static XINPUT_VIBRATION *static void(WINAPI *pXInputEnable)(BOOL)
#define XUSER_MAX_COUNT
Definition: xinput.h:156
SHORT sThumbLX
Definition: xinput.h:167
#define ERROR_SUCCESS
Definition: deptool.c:10
static void test_get_keystroke(void)
Definition: xinput.c:169
#define ERROR_BAD_ARGUMENTS
Definition: winerror.h:232
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
#define ZeroMemory
Definition: winbase.h:1648
static void test_get_state(void)
Definition: xinput.c:92
static void test_get_dsoundaudiodevice(void)
Definition: xinput.c:222
int winetest_interactive
#define BOOL
Definition: nt_native.h:43
#define ERROR_DEVICE_NOT_CONNECTED
Definition: winerror.h:689
XINPUT_GAMEPAD Gamepad
Definition: xinput.h:217
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
time_t now
Definition: finger.c:65
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:66
BYTE bRightTrigger
Definition: xinput.h:166
#define BATTERY_DEVTYPE_GAMEPAD
Definition: xinput.h:139
static void test_get_batteryinformation(void)
Definition: xinput.c:257
const char * LPCSTR
Definition: xmlstorage.h:183
static GUID GUID *static XINPUT_BATTERY_INFORMATION *static void dump_gamepad(XINPUT_GAMEPAD *data)
Definition: xinput.c:35
static XINPUT_STATE *static XINPUT_STATE *static DWORD
Definition: xinput.c:28
Definition: dhcpd.h:135
WORD wRightMotorSpeed
Definition: xinput.h:202
#define XINPUT_FLAG_GAMEPAD
Definition: xinput.h:129
#define FreeLibrary(x)
Definition: compat.h:414
WORD wButtons
Definition: xinput.h:164
#define trace
Definition: atltest.h:70
static void test_get_capabilities(void)
Definition: xinput.c:194
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static int state
Definition: maze.c:121
START_TEST(xinput)
Definition: xinput.c:281
SHORT sThumbRY
Definition: xinput.h:170
#define BATTERY_TYPE_DISCONNECTED
Definition: xinput.h:141
static GUID GUID *static BYTE
Definition: xinput.c:33
SHORT sThumbLY
Definition: xinput.h:168
#define ARRAY_SIZE(a)
Definition: main.h:24
#define ERROR_EMPTY
Definition: winerror.h:1250
#define ok(value,...)
Definition: atltest.h:57
SHORT sThumbRX
Definition: xinput.h:169
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
static PXINPUT_KEYSTROKE
Definition: xinput.c:31
static void test_set_state(void)
Definition: xinput.c:47
#define skip(...)
Definition: atltest.h:64
Definition: name.c:38
#define GetProcAddress(x, y)
Definition: compat.h:419
GLuint64EXT * result
Definition: glext.h:11304
BYTE bLeftTrigger
Definition: xinput.h:165
#define win_skip
Definition: test.h:149
WORD wLeftMotorSpeed
Definition: xinput.h:201
GLuint const GLchar * name
Definition: glext.h:6031