2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
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
22 #include "SDL_config.h"
24 /* This is the joystick API for Simple DirectMedia Layer */
26 #include "SDL_sysjoystick.h"
27 #include "SDL_joystick_c.h"
29 /* This is used for Quake III Arena */
30 #define SDL_Lock_EventThread()
31 #define SDL_Unlock_EventThread()
33 Uint8 SDL_numjoysticks = 0;
34 SDL_Joystick **SDL_joysticks = NULL;
35 static SDL_Joystick *default_joystick = NULL;
38 SDL_JoystickInit(void)
44 status = SDL_SYS_JoystickInit();
46 arraylen = (status + 1) * sizeof(*SDL_joysticks);
47 SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen);
48 if (SDL_joysticks == NULL) {
51 SDL_memset(SDL_joysticks, 0, arraylen);
52 SDL_numjoysticks = status;
56 default_joystick = NULL;
61 * Count the number of joysticks attached to the system
64 SDL_NumJoysticks(void)
66 return SDL_numjoysticks;
70 * Get the implementation dependent name of a joystick
73 SDL_JoystickName(int device_index)
75 if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
76 SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
79 return (SDL_SYS_JoystickName(device_index));
83 * Open a joystick for use - the index passed as an argument refers to
84 * the N'th joystick on the system. This index is the value which will
85 * identify this joystick in future joystick events.
87 * This function returns a joystick identifier, or NULL if an error occurred.
90 SDL_JoystickOpen(int device_index)
93 SDL_Joystick *joystick;
95 if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
96 SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
100 /* If the joystick is already open, return it */
101 for (i = 0; SDL_joysticks[i]; ++i) {
102 if (device_index == SDL_joysticks[i]->index) {
103 joystick = SDL_joysticks[i];
104 ++joystick->ref_count;
109 /* Create and initialize the joystick */
110 joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
111 if (joystick == NULL) {
116 SDL_memset(joystick, 0, (sizeof *joystick));
117 joystick->index = device_index;
118 if (SDL_SYS_JoystickOpen(joystick) < 0) {
122 if (joystick->naxes > 0) {
123 joystick->axes = (Sint16 *) SDL_malloc
124 (joystick->naxes * sizeof(Sint16));
126 if (joystick->nhats > 0) {
127 joystick->hats = (Uint8 *) SDL_malloc
128 (joystick->nhats * sizeof(Uint8));
130 if (joystick->nballs > 0) {
131 joystick->balls = (struct balldelta *) SDL_malloc
132 (joystick->nballs * sizeof(*joystick->balls));
134 if (joystick->nbuttons > 0) {
135 joystick->buttons = (Uint8 *) SDL_malloc
136 (joystick->nbuttons * sizeof(Uint8));
138 if (((joystick->naxes > 0) && !joystick->axes)
139 || ((joystick->nhats > 0) && !joystick->hats)
140 || ((joystick->nballs > 0) && !joystick->balls)
141 || ((joystick->nbuttons > 0) && !joystick->buttons)) {
143 SDL_JoystickClose(joystick);
146 if (joystick->axes) {
147 SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
149 if (joystick->hats) {
150 SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
152 if (joystick->balls) {
153 SDL_memset(joystick->balls, 0,
154 joystick->nballs * sizeof(*joystick->balls));
156 if (joystick->buttons) {
157 SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
160 /* Add joystick to list */
161 ++joystick->ref_count;
162 SDL_Lock_EventThread();
163 for (i = 0; SDL_joysticks[i]; ++i)
164 /* Skip to next joystick */ ;
165 SDL_joysticks[i] = joystick;
166 SDL_Unlock_EventThread();
172 * Returns 1 if the joystick has been opened, or 0 if it has not.
175 SDL_JoystickOpened(int device_index)
180 for (i = 0; SDL_joysticks[i]; ++i) {
181 if (SDL_joysticks[i]->index == (Uint8) device_index) {
191 * Checks to make sure the joystick is valid.
194 SDL_PrivateJoystickValid(SDL_Joystick ** joystick)
198 if (*joystick == NULL) {
199 *joystick = default_joystick;
201 if (*joystick == NULL) {
202 SDL_SetError("Joystick hasn't been opened yet");
211 * Get the device index of an opened joystick.
214 SDL_JoystickIndex(SDL_Joystick * joystick)
216 if (!SDL_PrivateJoystickValid(&joystick)) {
219 return (joystick->index);
223 * Get the number of multi-dimensional axis controls on a joystick
226 SDL_JoystickNumAxes(SDL_Joystick * joystick)
228 if (!SDL_PrivateJoystickValid(&joystick)) {
231 return (joystick->naxes);
235 * Get the number of hats on a joystick
238 SDL_JoystickNumHats(SDL_Joystick * joystick)
240 if (!SDL_PrivateJoystickValid(&joystick)) {
243 return (joystick->nhats);
247 * Get the number of trackballs on a joystick
250 SDL_JoystickNumBalls(SDL_Joystick * joystick)
252 if (!SDL_PrivateJoystickValid(&joystick)) {
255 return (joystick->nballs);
259 * Get the number of buttons on a joystick
262 SDL_JoystickNumButtons(SDL_Joystick * joystick)
264 if (!SDL_PrivateJoystickValid(&joystick)) {
267 return (joystick->nbuttons);
271 * Get the current state of an axis control on a joystick
274 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
278 if (!SDL_PrivateJoystickValid(&joystick)) {
281 if (axis < joystick->naxes) {
282 state = joystick->axes[axis];
284 SDL_SetError("Joystick only has %d axes", joystick->naxes);
291 * Get the current state of a hat on a joystick
294 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
298 if (!SDL_PrivateJoystickValid(&joystick)) {
301 if (hat < joystick->nhats) {
302 state = joystick->hats[hat];
304 SDL_SetError("Joystick only has %d hats", joystick->nhats);
311 * Get the ball axis change since the last poll
314 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
318 if (!SDL_PrivateJoystickValid(&joystick)) {
323 if (ball < joystick->nballs) {
325 *dx = joystick->balls[ball].dx;
328 *dy = joystick->balls[ball].dy;
330 joystick->balls[ball].dx = 0;
331 joystick->balls[ball].dy = 0;
333 SDL_SetError("Joystick only has %d balls", joystick->nballs);
340 * Get the current state of a button on a joystick
343 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
347 if (!SDL_PrivateJoystickValid(&joystick)) {
350 if (button < joystick->nbuttons) {
351 state = joystick->buttons[button];
353 SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
360 * Close a joystick previously opened with SDL_JoystickOpen()
363 SDL_JoystickClose(SDL_Joystick * joystick)
367 if (!SDL_PrivateJoystickValid(&joystick)) {
371 /* First decrement ref count */
372 if (--joystick->ref_count > 0) {
376 /* Lock the event queue - prevent joystick polling */
377 SDL_Lock_EventThread();
379 if (joystick == default_joystick) {
380 default_joystick = NULL;
382 SDL_SYS_JoystickClose(joystick);
384 /* Remove joystick from list */
385 for (i = 0; SDL_joysticks[i]; ++i) {
386 if (joystick == SDL_joysticks[i]) {
387 SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1],
388 (SDL_numjoysticks - i) * sizeof(joystick));
393 /* Let the event thread keep running */
394 SDL_Unlock_EventThread();
396 /* Free the data associated with this joystick */
397 if (joystick->axes) {
398 SDL_free(joystick->axes);
400 if (joystick->hats) {
401 SDL_free(joystick->hats);
403 if (joystick->balls) {
404 SDL_free(joystick->balls);
406 if (joystick->buttons) {
407 SDL_free(joystick->buttons);
413 SDL_JoystickQuit(void)
415 /* Stop the event polling */
416 SDL_Lock_EventThread();
417 SDL_numjoysticks = 0;
418 SDL_Unlock_EventThread();
420 /* Quit the joystick setup */
421 SDL_SYS_JoystickQuit();
423 SDL_free(SDL_joysticks);
424 SDL_joysticks = NULL;
429 /* These are global for SDL_sysjoystick.c and SDL_events.c */
432 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
436 /* Update internal joystick state */
437 joystick->axes[axis] = value;
439 /* Post the event, if desired */
446 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
450 /* Update internal joystick state */
451 joystick->hats[hat] = value;
453 /* Post the event, if desired */
460 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
461 Sint16 xrel, Sint16 yrel)
465 /* Update internal mouse state */
466 joystick->balls[ball].dx += xrel;
467 joystick->balls[ball].dy += yrel;
469 /* Post the event, if desired */
476 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
480 /* Update internal joystick state */
481 joystick->buttons[button] = state;
483 /* Post the event, if desired */
490 SDL_JoystickUpdate(void)
494 for (i = 0; SDL_joysticks[i]; ++i) {
495 SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
500 SDL_JoystickEventState(int state)