zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_mmjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #ifdef SDL_JOYSTICK_WINMM
24 
25 /* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */
26 
27 #include "../../core/windows/SDL_windows.h"
28 #include <mmsystem.h>
29 #include <regstr.h>
30 
31 #include "SDL_events.h"
32 #include "SDL_joystick.h"
33 #include "../SDL_sysjoystick.h"
34 #include "../SDL_joystick_c.h"
35 
36 #define MAX_JOYSTICKS 16
37 #define MAX_AXES 6 /* each joystick can have up to 6 axes */
38 #define MAX_BUTTONS 32 /* and 32 buttons */
39 #define AXIS_MIN -32768 /* minimum value for axis coordinate */
40 #define AXIS_MAX 32767 /* maximum value for axis coordinate */
41 /* limit axis to 256 possible positions to filter out noise */
42 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
43 #define JOY_BUTTON_FLAG(n) (1<<n)
44 
45 
46 /* array to hold joystick ID values */
47 static UINT SYS_JoystickID[MAX_JOYSTICKS];
48 static JOYCAPS SYS_Joystick[MAX_JOYSTICKS];
49 static char *SYS_JoystickName[MAX_JOYSTICKS];
50 
51 /* The private structure used to keep track of a joystick */
52 struct joystick_hwdata
53 {
54  /* joystick ID */
55  UINT id;
56 
57  /* values used to translate device-specific coordinates into
58  SDL-standard ranges */
59  struct _transaxis
60  {
61  int offset;
62  float scale;
63  } transaxis[6];
64 };
65 
66 /* Convert a Windows Multimedia API return code to a text message */
67 static void SetMMerror(char *function, int code);
68 
69 
70 static char *
71 GetJoystickName(int index, const char *szRegKey)
72 {
73  /* added 7/24/2004 by Eckhard Stolberg */
74  /*
75  see if there is a joystick for the current
76  index (1-16) listed in the registry
77  */
78  char *name = NULL;
79  HKEY hTopKey;
80  HKEY hKey;
81  DWORD regsize;
82  LONG regresult;
83  char regkey[256];
84  char regvalue[256];
85  char regname[256];
86 
87  SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s\\%s",
88  REGSTR_PATH_JOYCONFIG, szRegKey, REGSTR_KEY_JOYCURR);
89  hTopKey = HKEY_LOCAL_MACHINE;
90  regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
91  if (regresult != ERROR_SUCCESS) {
92  hTopKey = HKEY_CURRENT_USER;
93  regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
94  }
95  if (regresult != ERROR_SUCCESS) {
96  return NULL;
97  }
98 
99  /* find the registry key name for the joystick's properties */
100  regsize = sizeof(regname);
101  SDL_snprintf(regvalue, SDL_arraysize(regvalue), "Joystick%d%s", index + 1,
102  REGSTR_VAL_JOYOEMNAME);
103  regresult =
104  RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE) regname, &regsize);
105  RegCloseKey(hKey);
106 
107  if (regresult != ERROR_SUCCESS) {
108  return NULL;
109  }
110 
111  /* open that registry key */
112  SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM,
113  regname);
114  regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
115  if (regresult != ERROR_SUCCESS) {
116  return NULL;
117  }
118 
119  /* find the size for the OEM name text */
120  regsize = sizeof(regvalue);
121  regresult =
122  RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, &regsize);
123  if (regresult == ERROR_SUCCESS) {
124  /* allocate enough memory for the OEM name text ... */
125  name = (char *) SDL_malloc(regsize);
126  if (name) {
127  /* ... and read it from the registry */
128  regresult = RegQueryValueExA(hKey,
129  REGSTR_VAL_JOYOEMNAME, 0, 0,
130  (LPBYTE) name, &regsize);
131  }
132  }
133  RegCloseKey(hKey);
134 
135  return (name);
136 }
137 
138 static int SDL_SYS_numjoysticks = 0;
139 
140 /* Function to scan the system for joysticks.
141  * This function should set SDL_numjoysticks to the number of available
142  * joysticks. Joystick 0 should be the system default joystick.
143  * It should return 0, or -1 on an unrecoverable fatal error.
144  */
145 int
147 {
148  int i;
149  int maxdevs;
150  JOYINFOEX joyinfo;
151  JOYCAPS joycaps;
152  MMRESULT result;
153 
154  /* Reset the joystick ID & name mapping tables */
155  for (i = 0; i < MAX_JOYSTICKS; ++i) {
156  SYS_JoystickID[i] = 0;
157  SYS_JoystickName[i] = NULL;
158  }
159 
160  /* Loop over all potential joystick devices */
161  SDL_SYS_numjoysticks = 0;
162  maxdevs = joyGetNumDevs();
163  for (i = JOYSTICKID1; i < maxdevs && SDL_SYS_numjoysticks < MAX_JOYSTICKS; ++i) {
164 
165  joyinfo.dwSize = sizeof(joyinfo);
166  joyinfo.dwFlags = JOY_RETURNALL;
167  result = joyGetPosEx(i, &joyinfo);
168  if (result == JOYERR_NOERROR) {
169  result = joyGetDevCaps(i, &joycaps, sizeof(joycaps));
170  if (result == JOYERR_NOERROR) {
171  SYS_JoystickID[SDL_SYS_numjoysticks] = i;
172  SYS_Joystick[SDL_SYS_numjoysticks] = joycaps;
173  SYS_JoystickName[SDL_SYS_numjoysticks] =
174  GetJoystickName(i, joycaps.szRegKey);
175  SDL_SYS_numjoysticks++;
176  }
177  }
178  }
179  return (SDL_SYS_numjoysticks);
180 }
181 
183 {
184  return SDL_SYS_numjoysticks;
185 }
186 
188 {
189 }
190 
192 {
193  return SDL_FALSE;
194 }
195 
196 /* Function to get the device-dependent name of a joystick */
197 const char *
198 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
199 {
200  if (SYS_JoystickName[device_index] != NULL) {
201  return (SYS_JoystickName[device_index]);
202  } else {
203  return (SYS_Joystick[device_index].szPname);
204  }
205 }
206 
207 /* Function to perform the mapping from device index to the instance id for this index */
209 {
210  return device_index;
211 }
212 
213 /* Function to open a joystick for use.
214  The joystick to open is specified by the index field of the joystick.
215  This should fill the nbuttons and naxes fields of the joystick structure.
216  It returns 0, or -1 if there is an error.
217  */
218 int
219 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
220 {
221  int index, i;
222  int caps_flags[MAX_AXES - 2] =
223  { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV };
224  int axis_min[MAX_AXES], axis_max[MAX_AXES];
225 
226 
227  /* shortcut */
228  index = device_index;
229  axis_min[0] = SYS_Joystick[index].wXmin;
230  axis_max[0] = SYS_Joystick[index].wXmax;
231  axis_min[1] = SYS_Joystick[index].wYmin;
232  axis_max[1] = SYS_Joystick[index].wYmax;
233  axis_min[2] = SYS_Joystick[index].wZmin;
234  axis_max[2] = SYS_Joystick[index].wZmax;
235  axis_min[3] = SYS_Joystick[index].wRmin;
236  axis_max[3] = SYS_Joystick[index].wRmax;
237  axis_min[4] = SYS_Joystick[index].wUmin;
238  axis_max[4] = SYS_Joystick[index].wUmax;
239  axis_min[5] = SYS_Joystick[index].wVmin;
240  axis_max[5] = SYS_Joystick[index].wVmax;
241 
242  /* allocate memory for system specific hardware data */
243  joystick->instance_id = device_index;
244  joystick->hwdata =
245  (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
246  if (joystick->hwdata == NULL) {
247  return SDL_OutOfMemory();
248  }
249  SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
250 
251  /* set hardware data */
252  joystick->hwdata->id = SYS_JoystickID[index];
253  for (i = 0; i < MAX_AXES; ++i) {
254  if ((i < 2) || (SYS_Joystick[index].wCaps & caps_flags[i - 2])) {
255  joystick->hwdata->transaxis[i].offset = AXIS_MIN - axis_min[i];
256  joystick->hwdata->transaxis[i].scale =
257  (float) (AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]);
258  } else {
259  joystick->hwdata->transaxis[i].offset = 0;
260  joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */
261  }
262  }
263 
264  /* fill nbuttons, naxes, and nhats fields */
265  joystick->nbuttons = SYS_Joystick[index].wNumButtons;
266  joystick->naxes = SYS_Joystick[index].wNumAxes;
267  if (SYS_Joystick[index].wCaps & JOYCAPS_HASPOV) {
268  joystick->nhats = 1;
269  } else {
270  joystick->nhats = 0;
271  }
272  return (0);
273 }
274 
275 /* Function to determine is this joystick is attached to the system right now */
277 {
278  return SDL_TRUE;
279 }
280 
281 static Uint8
282 TranslatePOV(DWORD value)
283 {
284  Uint8 pos;
285 
286  pos = SDL_HAT_CENTERED;
287  if (value != JOY_POVCENTERED) {
288  if ((value > JOY_POVLEFT) || (value < JOY_POVRIGHT)) {
289  pos |= SDL_HAT_UP;
290  }
291  if ((value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD)) {
292  pos |= SDL_HAT_RIGHT;
293  }
294  if ((value > JOY_POVRIGHT) && (value < JOY_POVLEFT)) {
295  pos |= SDL_HAT_DOWN;
296  }
297  if (value > JOY_POVBACKWARD) {
298  pos |= SDL_HAT_LEFT;
299  }
300  }
301  return (pos);
302 }
303 
304 /* Function to update the state of a joystick - called as a device poll.
305  * This function shouldn't update the joystick structure directly,
306  * but instead should call SDL_PrivateJoystick*() to deliver events
307  * and update joystick device state.
308  */
309 void
311 {
312  MMRESULT result;
313  int i;
314  DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ,
315  JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
316  };
317  DWORD pos[MAX_AXES];
318  struct _transaxis *transaxis;
319  int value, change;
320  JOYINFOEX joyinfo;
321 
322  joyinfo.dwSize = sizeof(joyinfo);
323  joyinfo.dwFlags = JOY_RETURNALL | JOY_RETURNPOVCTS;
324  if (!joystick->hats) {
325  joyinfo.dwFlags &= ~(JOY_RETURNPOV | JOY_RETURNPOVCTS);
326  }
327  result = joyGetPosEx(joystick->hwdata->id, &joyinfo);
328  if (result != JOYERR_NOERROR) {
329  SetMMerror("joyGetPosEx", result);
330  return;
331  }
332 
333  /* joystick motion events */
334  pos[0] = joyinfo.dwXpos;
335  pos[1] = joyinfo.dwYpos;
336  pos[2] = joyinfo.dwZpos;
337  pos[3] = joyinfo.dwRpos;
338  pos[4] = joyinfo.dwUpos;
339  pos[5] = joyinfo.dwVpos;
340 
341  transaxis = joystick->hwdata->transaxis;
342  for (i = 0; i < joystick->naxes; i++) {
343  if (joyinfo.dwFlags & flags[i]) {
344  value =
345  (int) (((float) pos[i] +
346  transaxis[i].offset) * transaxis[i].scale);
347  change = (value - joystick->axes[i]);
348  if ((change < -JOY_AXIS_THRESHOLD)
349  || (change > JOY_AXIS_THRESHOLD)) {
350  SDL_PrivateJoystickAxis(joystick, (Uint8) i, (Sint16) value);
351  }
352  }
353  }
354 
355  /* joystick button events */
356  if (joyinfo.dwFlags & JOY_RETURNBUTTONS) {
357  for (i = 0; i < joystick->nbuttons; ++i) {
358  if (joyinfo.dwButtons & JOY_BUTTON_FLAG(i)) {
359  if (!joystick->buttons[i]) {
360  SDL_PrivateJoystickButton(joystick, (Uint8) i,
361  SDL_PRESSED);
362  }
363  } else {
364  if (joystick->buttons[i]) {
365  SDL_PrivateJoystickButton(joystick, (Uint8) i,
366  SDL_RELEASED);
367  }
368  }
369  }
370  }
371 
372  /* joystick hat events */
373  if (joyinfo.dwFlags & JOY_RETURNPOV) {
374  Uint8 pos;
375 
376  pos = TranslatePOV(joyinfo.dwPOV);
377  if (pos != joystick->hats[0]) {
378  SDL_PrivateJoystickHat(joystick, 0, pos);
379  }
380  }
381 }
382 
383 /* Function to close a joystick after use */
384 void
386 {
387  /* free system specific hardware data */
388  SDL_free(joystick->hwdata);
389  joystick->hwdata = NULL;
390 }
391 
392 /* Function to perform any system-specific joystick related cleanup */
393 void
395 {
396  int i;
397  for (i = 0; i < MAX_JOYSTICKS; i++) {
398  SDL_free(SYS_JoystickName[i]);
399  SYS_JoystickName[i] = NULL;
400  }
401 }
402 
404 {
405  SDL_JoystickGUID guid;
406  /* the GUID is just the first 16 chars of the name for now */
407  const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
408  SDL_zero( guid );
409  SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
410  return guid;
411 }
412 
414 {
415  SDL_JoystickGUID guid;
416  /* the GUID is just the first 16 chars of the name for now */
417  const char *name = joystick->name;
418  SDL_zero( guid );
419  SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
420  return guid;
421 }
422 
423 
424 /* implementation functions */
425 void
426 SetMMerror(char *function, int code)
427 {
428  static char *error;
429  static char errbuf[1024];
430 
431  errbuf[0] = 0;
432  switch (code) {
433  case MMSYSERR_NODRIVER:
434  error = "Joystick driver not present";
435  break;
436 
437  case MMSYSERR_INVALPARAM:
438  case JOYERR_PARMS:
439  error = "Invalid parameter(s)";
440  break;
441 
442  case MMSYSERR_BADDEVICEID:
443  error = "Bad device ID";
444  break;
445 
446  case JOYERR_UNPLUGGED:
447  error = "Joystick not attached";
448  break;
449 
450  case JOYERR_NOCANDO:
451  error = "Can't capture joystick input";
452  break;
453 
454  default:
455  SDL_snprintf(errbuf, SDL_arraysize(errbuf),
456  "%s: Unknown Multimedia system error: 0x%x",
457  function, code);
458  break;
459  }
460 
461  if (!errbuf[0]) {
462  SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
463  error);
464  }
465  SDL_SetError("%s", errbuf);
466 }
467 
468 #endif /* SDL_JOYSTICK_WINMM */
469 
470 /* vi: set ts=4 sw=4 expandtab: */
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:536
int SDL_SYS_NumJoysticks()
#define NULL
Definition: ftobjs.h:61
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
SDL_bool
Definition: SDL_stdinc.h:116
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:72
DECLSPEC void SDLCALL SDL_free(void *mem)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:610
EGLImageKHR EGLint * name
Definition: eglext.h:284
void SDL_SYS_JoystickQuit(void)
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
GLuint id
Definition: gl2ext.h:1142
struct joystick_hwdata * hwdata
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:496
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:193
GLuint64EXT * result
Definition: glew.h:12708
int
Definition: SDL_systhread.c:37
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:195
FT_Error error
Definition: cffdrivr.c:407
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
void SDL_SYS_JoystickDetect()
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
GLuint index
Definition: glew.h:1800
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:12632
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
SDL_bool SDL_SYS_JoystickNeedsPolling()
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
Definition: SDL_string.c:389
int SDL_SYS_JoystickInit(void)
Definition: inftrees.h:24
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
EGLSurface EGLint void ** value
Definition: eglext.h:301
GLintptr offset
Definition: glew.h:1668
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:133
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
#define SDL_min(x, y)
Definition: SDL_stdinc.h:244
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:191
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_HAT_UP
Definition: SDL_joystick.h:192
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:194
SDL_JoystickID instance_id
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)