ReactOS  0.4.14-dev-49-gfb4591c
joystick.c
Go to the documentation of this file.
1 /*
2  * Unit tests for joystick APIs
3  *
4  * Copyright 2014 Bruno Jesus
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "mmsystem.h"
27 #include "wine/test.h"
28 
29 static HWND window;
30 
32 {
33  return DefWindowProcA(hwnd, msg, wparam, lparam);
34 }
35 
36 static void create_window(void)
37 {
38  const char name[] = "Joystick Test";
39  WNDCLASSA wc;
40 
41  memset(&wc, 0, sizeof(wc));
43  wc.hInstance = 0;
44  wc.lpszClassName = name;
45  RegisterClassA(&wc);
48  NULL, NULL, NULL, NULL);
49  ok(window != NULL, "Expected CreateWindowEx to work, error %d\n", GetLastError());
50 }
51 
52 static void destroy_window(void)
53 {
55  window = NULL;
56 }
57 
58 static void test_api(void)
59 {
60  MMRESULT ret;
61  JOYCAPSA jc;
62  JOYCAPSW jcw;
63  JOYINFO info;
64  union _infoex
65  {
66  JOYINFOEX ex;
67  char buffer[sizeof(JOYINFOEX) * 2];
68  } infoex;
69  UINT i, par, devices, joyid, win98 = 0, win8 = 0;
70  UINT period[] = {0, 1, 9, 10, 100, 1000, 1001, 10000, 65535, 65536, 0xFFFFFFFF};
71  UINT threshold_error = 0x600, period_win8_error = 0x7CE;
75 
77  joyid = -1;
78  /* joyGetNumDevs does NOT return the number of joysticks connected, only slots in the OS */
79  for (i = 0; i < devices; i++)
80  {
81  memset(&jc, 0, sizeof(jc));
82  ret = joyGetDevCapsA(JOYSTICKID1 + i, &jc, sizeof(jc));
83  if (ret == JOYERR_NOERROR)
84  {
85  if (joyid == -1) /* Cache the first found joystick to run advanced tests below */
86  joyid = JOYSTICKID1 + i;
87 
88  trace("Joystick[%d] - name: '%s', axes: %d, buttons: %d, period range: %d - %d\n",
90  ret = joyGetDevCapsW(JOYSTICKID1 + i, &jcw, sizeof(jcw));
91  if (ret != MMSYSERR_NOTSUPPORTED) /* Win 98 */
92  {
93  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
94  ok(jc.wNumAxes == jcw.wNumAxes, "Expected %d == %d\n", jc.wNumAxes, jcw.wNumAxes);
95  ok(jc.wNumButtons == jcw.wNumButtons, "Expected %d == %d\n", jc.wNumButtons, jcw.wNumButtons);
96  }
97  else win98++;
98  }
99  else
100  {
101  ok(ret == JOYERR_PARMS, "Expected %d, got %d\n", JOYERR_PARMS, ret);
102  ret = joyGetDevCapsW(JOYSTICKID1 + i, &jcw, sizeof(jcw));
103  ok(ret == JOYERR_PARMS || (ret == MMSYSERR_NOTSUPPORTED) /* Win 98 */,
104  "Expected %d, got %d\n", JOYERR_PARMS, ret);
105  }
106  }
107  /* Test invalid joystick - If no joystick is present the driver is not initialized,
108  * so a NODRIVER error is returned, if at least one joystick is present the error is
109  * about invalid parameters. */
110  ret = joyGetDevCapsA(joyid + devices, &jc, sizeof(jc));
112  "Expected %d or %d, got %d\n", MMSYSERR_NODRIVER, JOYERR_PARMS, ret);
113 
114  if (joyid == -1)
115  {
116  skip("This test requires a real joystick.\n");
117  return;
118  }
119 
120  /* Capture tests */
121  ret = joySetCapture(NULL, joyid, 100, FALSE);
122  ok(ret == JOYERR_PARMS || broken(win98 && ret == MMSYSERR_INVALPARAM) /* Win 98 */,
123  "Expected %d, got %d\n", JOYERR_PARMS, ret);
124  ret = joySetCapture(window, joyid, 100, FALSE);
125  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
126  ret = joySetCapture(window, joyid, 100, FALSE); /* double capture */
127  if (ret == JOYERR_NOCANDO)
128  {
129  todo_wine
130  ok(broken(1), "Expected double capture using joySetCapture to work\n");
131  if (!win98 && broken(1)) win8++; /* Windows 98 or 8 cannot cope with that */
132  }
133  else ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
134  ret = joyReleaseCapture(joyid);
135  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
136  ret = joyReleaseCapture(joyid);
137  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret); /* double release */
138 
139  /* Try some unusual period values for joySetCapture and unusual threshold values for joySetThreshold.
140  * Windows XP allows almost all test values, Windows 8 will return error on most test values, Windows
141  * 98 allows anything but cuts the values to their maximum supported values internally. */
142  for (i = 0; i < sizeof(period) / sizeof(period[0]); i++)
143  {
144  ret = joySetCapture(window, joyid, period[i], FALSE);
145  if (win8 && ((1 << i) & period_win8_error))
146  ok(ret == JOYERR_NOCANDO, "Test [%d]: Expected %d, got %d\n", i, JOYERR_NOCANDO, ret);
147  else
148  ok(ret == JOYERR_NOERROR, "Test [%d]: Expected %d, got %d\n", i, JOYERR_NOERROR, ret);
149  ret = joyReleaseCapture(joyid);
150  ok(ret == JOYERR_NOERROR, "Test [%d]: Expected %d, got %d\n", i, JOYERR_NOERROR, ret);
151  /* Reuse the periods to test the threshold */
152  ret = joySetThreshold(joyid, period[i]);
153  if (!win98 && (1 << i) & threshold_error)
154  ok(ret == MMSYSERR_INVALPARAM, "Test [%d]: Expected %d, got %d\n", i, MMSYSERR_INVALPARAM, ret);
155  else
156  ok(ret == JOYERR_NOERROR, "Test [%d]: Expected %d, got %d\n", i, JOYERR_NOERROR, ret);
157  par = 0xdead;
158  ret = joyGetThreshold(joyid, &par);
159  ok(ret == JOYERR_NOERROR, "Test [%d]: Expected %d, got %d\n", i, JOYERR_NOERROR, ret);
160  if (!win98 || i < 8)
161  {
162  if ((1 << i) & threshold_error)
163  ok(par == period[8], "Test [%d]: Expected %d, got %d\n", i, period[8], par);
164  else
165  ok(par == period[i], "Test [%d]: Expected %d, got %d\n", i, period[i], par);
166  }
167  }
168 
169  /* Position tests */
170  ret = joyGetPos(joyid, NULL);
171  ok(ret == MMSYSERR_INVALPARAM, "Expected %d, got %d\n", MMSYSERR_INVALPARAM, ret);
172  ret = joyGetPos(joyid, &info);
173  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
174  ret = joyGetPosEx(joyid, NULL);
175  ok(ret == MMSYSERR_INVALPARAM || broken(win8 && ret == JOYERR_PARMS) /* Win 8 */,
176  "Expected %d, got %d\n", MMSYSERR_INVALPARAM, ret);
177  memset(&infoex, 0, sizeof(infoex));
178  ret = joyGetPosEx(joyid, &infoex.ex);
179  ok(ret == JOYERR_PARMS || broken(win98 && ret == MMSYSERR_INVALPARAM),
180  "Expected %d, got %d\n", JOYERR_PARMS, ret);
181  infoex.ex.dwSize = sizeof(infoex.ex);
182  ret = joyGetPosEx(joyid, &infoex.ex);
183  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
184  infoex.ex.dwSize = sizeof(infoex.ex) - 1;
185  ret = joyGetPosEx(joyid, &infoex.ex);
186  ok(ret == JOYERR_PARMS || broken(win98 && ret == MMSYSERR_INVALPARAM),
187  "Expected %d, got %d\n", JOYERR_PARMS, ret);
188  infoex.ex.dwSize = sizeof(infoex);
189  ret = joyGetPosEx(joyid, &infoex.ex);
190  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
191 
192  infoex.ex.dwSize = sizeof(infoex.ex);
193  for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
194  {
195  infoex.ex.dwFlags = flags[i];
196  ret = joyGetPosEx(joyid, &infoex.ex);
197  ok(ret == JOYERR_NOERROR, "Expected %d, got %d\n", JOYERR_NOERROR, ret);
198  }
199 
200  /* the interactive tests spans for 15 seconds, a 500ms polling is used to get
201  * changes in the joystick. */
203  {
204 #define MAX_TIME 15000
205  DWORD tick = GetTickCount(), spent;
206  infoex.ex.dwSize = sizeof(infoex.ex);
207  infoex.ex.dwFlags = JOY_RETURNALL;
208  do
209  {
210  spent = GetTickCount() - tick;
211  ret = joyGetPosEx(joyid, &infoex.ex);
212  if (ret == JOYERR_NOERROR)
213  {
214  trace("X: %5d, Y: %5d, Z: %5d, POV: %5d\n",
215  infoex.ex.dwXpos, infoex.ex.dwYpos, infoex.ex.dwZpos, infoex.ex.dwPOV);
216  trace("R: %5d, U: %5d, V: %5d\n",
217  infoex.ex.dwRpos, infoex.ex.dwUpos, infoex.ex.dwVpos);
218  trace("BUTTONS: 0x%04X, BUTTON_COUNT: %2d, REMAINING: %d ms\n\n",
219  infoex.ex.dwButtons, infoex.ex.dwButtonNumber, MAX_TIME - spent);
220  }
221  Sleep(500);
222  }
223  while (spent < MAX_TIME);
224 #undef MAX_TIME
225  }
226  else
227  skip("Skipping interactive tests for the joystick\n");
228 }
229 
230 START_TEST(joystick)
231 {
232  create_window();
233  test_api();
234  destroy_window();
235 }
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold)
Definition: joystick.c:257
MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold)
Definition: joystick.c:314
#define JOYERR_PARMS
Definition: mmsystem.h:430
Definition: comerr.c:44
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static void test_api(void)
Definition: joystick.c:58
#define JOYERR_NOCANDO
Definition: mmsystem.h:431
MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo)
Definition: joystick.c:214
#define JOYERR_NOERROR
Definition: mmsystem.h:429
const char * devices
Definition: diskspace.c:793
#define CALLBACK
Definition: compat.h:27
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
UINT wNumButtons
Definition: mmsystem.h:1408
#define MAX_TIME
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
UINT MMRESULT
Definition: mmsystem.h:962
GLuint buffer
Definition: glext.h:5915
struct joyinfoex_tag JOYINFOEX
UINT_PTR WPARAM
Definition: windef.h:207
#define JOY_RETURNCENTERED
Definition: mmsystem.h:484
int winetest_interactive
BOOL WINAPI DestroyWindow(_In_ HWND)
UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void)
Definition: joystick.c:135
MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo)
Definition: joystick.c:239
struct _test_info info[]
Definition: SetCursorPos.c:19
UINT wNumAxes
Definition: mmsystem.h:1419
#define JOY_RETURNY
Definition: mmsystem.h:475
static void destroy_window(void)
Definition: joystick.c:52
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
#define MMSYSERR_NODRIVER
Definition: mmsystem.h:102
#define JOY_RETURNRAWDATA
Definition: mmsystem.h:482
CHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1401
#define JOY_RETURNV
Definition: mmsystem.h:479
UINT wPeriodMin
Definition: mmsystem.h:1409
#define JOY_RETURNX
Definition: mmsystem.h:474
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
#define CW_USEDEFAULT
Definition: winuser.h:225
UINT wNumAxes
Definition: mmsystem.h:1446
smooth NULL
Definition: ftsmooth.c:416
LONG_PTR LPARAM
Definition: windef.h:208
UINT wNumButtons
Definition: mmsystem.h:1435
#define trace
Definition: atltest.h:70
MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW(UINT_PTR wID, LPJOYCAPSW lpCaps, UINT wSize)
Definition: joystick.c:151
START_TEST(joystick)
Definition: joystick.c:873
unsigned long DWORD
Definition: ntddk_ex.h:95
static LRESULT CALLBACK proc_window(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: joystick.c:31
MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA(UINT_PTR wID, LPJOYCAPSA lpCaps, UINT wSize)
Definition: joystick.c:165
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
GLbitfield flags
Definition: glext.h:7161
int ret
static void create_window(void)
Definition: joystick.c:36
#define todo_wine
Definition: test.h:154
MMRESULT WINAPI joyReleaseCapture(UINT wID)
Definition: joystick.c:270
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LPCSTR lpszClassName
Definition: winuser.h:3146
#define broken(x)
Definition: _sntprintf.h:21
#define JOY_RETURNPOVCTS
Definition: mmsystem.h:483
HINSTANCE hInstance
Definition: winuser.h:3141
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
static HWND window
Definition: joystick.c:29
#define JOY_RETURNR
Definition: mmsystem.h:477
#define ok(value,...)
Definition: atltest.h:57
#define JOY_RETURNU
Definition: mmsystem.h:478
unsigned int UINT
Definition: ndis.h:50
WNDPROC lpfnWndProc
Definition: winuser.h:3138
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
Definition: name.c:36
#define JOY_RETURNALL
Definition: mmsystem.h:486
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define JOYSTICKID1
Definition: mmsystem.h:499
LONG_PTR LRESULT
Definition: windef.h:209
MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged)
Definition: joystick.c:288
#define memset(x, y, z)
Definition: compat.h:39
#define JOY_RETURNPOV
Definition: mmsystem.h:480
UINT wPeriodMax
Definition: mmsystem.h:1410
#define JOY_RETURNZ
Definition: mmsystem.h:476
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
static UINT WPARAM wparam
Definition: combo.c:716
#define JOY_RETURNBUTTONS
Definition: mmsystem.h:481
GLuint const GLchar * name
Definition: glext.h:6031