Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /* |
2 | SDL - Simple DirectMedia Layer | |
3 | Copyright (C) 1997-2010 Sam Lantinga | |
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 | Sam Lantinga | |
20 | slouken@libsdl.org | |
21 | */ | |
22 | #include "SDL_config.h" | |
23 | ||
24 | /* This is the joystick API for Simple DirectMedia Layer */ | |
25 | #include "SDL.h" | |
26 | #include "SDL_sysjoystick.h" | |
27 | #include "SDL_joystick_c.h" | |
28 | ||
29 | /* This is used for Quake III Arena */ | |
30 | #define SDL_Lock_EventThread() | |
31 | #define SDL_Unlock_EventThread() | |
32 | ||
33 | Uint8 SDL_numjoysticks = 0; | |
34 | SDL_Joystick **SDL_joysticks = NULL; | |
35 | static SDL_Joystick *default_joystick = NULL; | |
36 | ||
37 | int | |
38 | SDL_JoystickInit(void) | |
39 | { | |
40 | int arraylen; | |
41 | int status; | |
42 | ||
43 | SDL_numjoysticks = 0; | |
44 | status = SDL_SYS_JoystickInit(); | |
45 | if (status >= 0) { | |
46 | arraylen = (status + 1) * sizeof(*SDL_joysticks); | |
47 | SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen); | |
48 | if (SDL_joysticks == NULL) { | |
49 | SDL_numjoysticks = 0; | |
50 | } else { | |
51 | SDL_memset(SDL_joysticks, 0, arraylen); | |
52 | SDL_numjoysticks = status; | |
53 | } | |
54 | status = 0; | |
55 | } | |
56 | default_joystick = NULL; | |
57 | return (status); | |
58 | } | |
59 | ||
60 | /* | |
61 | * Count the number of joysticks attached to the system | |
62 | */ | |
63 | int | |
64 | SDL_NumJoysticks(void) | |
65 | { | |
66 | return SDL_numjoysticks; | |
67 | } | |
68 | ||
69 | /* | |
70 | * Get the implementation dependent name of a joystick | |
71 | */ | |
72 | const char * | |
73 | SDL_JoystickName(int device_index) | |
74 | { | |
75 | if ((device_index < 0) || (device_index >= SDL_numjoysticks)) { | |
76 | SDL_SetError("There are %d joysticks available", SDL_numjoysticks); | |
77 | return (NULL); | |
78 | } | |
79 | return (SDL_SYS_JoystickName(device_index)); | |
80 | } | |
81 | ||
82 | /* | |
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. | |
86 | * | |
87 | * This function returns a joystick identifier, or NULL if an error occurred. | |
88 | */ | |
89 | SDL_Joystick * | |
90 | SDL_JoystickOpen(int device_index) | |
91 | { | |
92 | int i; | |
93 | SDL_Joystick *joystick; | |
94 | ||
95 | if ((device_index < 0) || (device_index >= SDL_numjoysticks)) { | |
96 | SDL_SetError("There are %d joysticks available", SDL_numjoysticks); | |
97 | return (NULL); | |
98 | } | |
99 | ||
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; | |
105 | return (joystick); | |
106 | } | |
107 | } | |
108 | ||
109 | /* Create and initialize the joystick */ | |
110 | joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick)); | |
111 | if (joystick == NULL) { | |
112 | SDL_OutOfMemory(); | |
113 | return NULL; | |
114 | } | |
115 | ||
116 | SDL_memset(joystick, 0, (sizeof *joystick)); | |
117 | joystick->index = device_index; | |
118 | if (SDL_SYS_JoystickOpen(joystick) < 0) { | |
119 | SDL_free(joystick); | |
120 | return NULL; | |
121 | } | |
122 | if (joystick->naxes > 0) { | |
123 | joystick->axes = (Sint16 *) SDL_malloc | |
124 | (joystick->naxes * sizeof(Sint16)); | |
125 | } | |
126 | if (joystick->nhats > 0) { | |
127 | joystick->hats = (Uint8 *) SDL_malloc | |
128 | (joystick->nhats * sizeof(Uint8)); | |
129 | } | |
130 | if (joystick->nballs > 0) { | |
131 | joystick->balls = (struct balldelta *) SDL_malloc | |
132 | (joystick->nballs * sizeof(*joystick->balls)); | |
133 | } | |
134 | if (joystick->nbuttons > 0) { | |
135 | joystick->buttons = (Uint8 *) SDL_malloc | |
136 | (joystick->nbuttons * sizeof(Uint8)); | |
137 | } | |
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)) { | |
142 | SDL_OutOfMemory(); | |
143 | SDL_JoystickClose(joystick); | |
144 | return NULL; | |
145 | } | |
146 | if (joystick->axes) { | |
147 | SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16)); | |
148 | } | |
149 | if (joystick->hats) { | |
150 | SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8)); | |
151 | } | |
152 | if (joystick->balls) { | |
153 | SDL_memset(joystick->balls, 0, | |
154 | joystick->nballs * sizeof(*joystick->balls)); | |
155 | } | |
156 | if (joystick->buttons) { | |
157 | SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8)); | |
158 | } | |
159 | ||
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(); | |
167 | ||
168 | return (joystick); | |
169 | } | |
170 | ||
171 | /* | |
172 | * Returns 1 if the joystick has been opened, or 0 if it has not. | |
173 | */ | |
174 | int | |
175 | SDL_JoystickOpened(int device_index) | |
176 | { | |
177 | int i, opened; | |
178 | ||
179 | opened = 0; | |
180 | for (i = 0; SDL_joysticks[i]; ++i) { | |
181 | if (SDL_joysticks[i]->index == (Uint8) device_index) { | |
182 | opened = 1; | |
183 | break; | |
184 | } | |
185 | } | |
186 | return (opened); | |
187 | } | |
188 | ||
189 | ||
190 | /* | |
191 | * Checks to make sure the joystick is valid. | |
192 | */ | |
193 | int | |
194 | SDL_PrivateJoystickValid(SDL_Joystick ** joystick) | |
195 | { | |
196 | int valid; | |
197 | ||
198 | if (*joystick == NULL) { | |
199 | *joystick = default_joystick; | |
200 | } | |
201 | if (*joystick == NULL) { | |
202 | SDL_SetError("Joystick hasn't been opened yet"); | |
203 | valid = 0; | |
204 | } else { | |
205 | valid = 1; | |
206 | } | |
207 | return valid; | |
208 | } | |
209 | ||
210 | /* | |
211 | * Get the device index of an opened joystick. | |
212 | */ | |
213 | int | |
214 | SDL_JoystickIndex(SDL_Joystick * joystick) | |
215 | { | |
216 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
217 | return (-1); | |
218 | } | |
219 | return (joystick->index); | |
220 | } | |
221 | ||
222 | /* | |
223 | * Get the number of multi-dimensional axis controls on a joystick | |
224 | */ | |
225 | int | |
226 | SDL_JoystickNumAxes(SDL_Joystick * joystick) | |
227 | { | |
228 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
229 | return (-1); | |
230 | } | |
231 | return (joystick->naxes); | |
232 | } | |
233 | ||
234 | /* | |
235 | * Get the number of hats on a joystick | |
236 | */ | |
237 | int | |
238 | SDL_JoystickNumHats(SDL_Joystick * joystick) | |
239 | { | |
240 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
241 | return (-1); | |
242 | } | |
243 | return (joystick->nhats); | |
244 | } | |
245 | ||
246 | /* | |
247 | * Get the number of trackballs on a joystick | |
248 | */ | |
249 | int | |
250 | SDL_JoystickNumBalls(SDL_Joystick * joystick) | |
251 | { | |
252 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
253 | return (-1); | |
254 | } | |
255 | return (joystick->nballs); | |
256 | } | |
257 | ||
258 | /* | |
259 | * Get the number of buttons on a joystick | |
260 | */ | |
261 | int | |
262 | SDL_JoystickNumButtons(SDL_Joystick * joystick) | |
263 | { | |
264 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
265 | return (-1); | |
266 | } | |
267 | return (joystick->nbuttons); | |
268 | } | |
269 | ||
270 | /* | |
271 | * Get the current state of an axis control on a joystick | |
272 | */ | |
273 | Sint16 | |
274 | SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis) | |
275 | { | |
276 | Sint16 state; | |
277 | ||
278 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
279 | return (0); | |
280 | } | |
281 | if (axis < joystick->naxes) { | |
282 | state = joystick->axes[axis]; | |
283 | } else { | |
284 | SDL_SetError("Joystick only has %d axes", joystick->naxes); | |
285 | state = 0; | |
286 | } | |
287 | return (state); | |
288 | } | |
289 | ||
290 | /* | |
291 | * Get the current state of a hat on a joystick | |
292 | */ | |
293 | Uint8 | |
294 | SDL_JoystickGetHat(SDL_Joystick * joystick, int hat) | |
295 | { | |
296 | Uint8 state; | |
297 | ||
298 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
299 | return (0); | |
300 | } | |
301 | if (hat < joystick->nhats) { | |
302 | state = joystick->hats[hat]; | |
303 | } else { | |
304 | SDL_SetError("Joystick only has %d hats", joystick->nhats); | |
305 | state = 0; | |
306 | } | |
307 | return (state); | |
308 | } | |
309 | ||
310 | /* | |
311 | * Get the ball axis change since the last poll | |
312 | */ | |
313 | int | |
314 | SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy) | |
315 | { | |
316 | int retval; | |
317 | ||
318 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
319 | return (-1); | |
320 | } | |
321 | ||
322 | retval = 0; | |
323 | if (ball < joystick->nballs) { | |
324 | if (dx) { | |
325 | *dx = joystick->balls[ball].dx; | |
326 | } | |
327 | if (dy) { | |
328 | *dy = joystick->balls[ball].dy; | |
329 | } | |
330 | joystick->balls[ball].dx = 0; | |
331 | joystick->balls[ball].dy = 0; | |
332 | } else { | |
333 | SDL_SetError("Joystick only has %d balls", joystick->nballs); | |
334 | retval = -1; | |
335 | } | |
336 | return (retval); | |
337 | } | |
338 | ||
339 | /* | |
340 | * Get the current state of a button on a joystick | |
341 | */ | |
342 | Uint8 | |
343 | SDL_JoystickGetButton(SDL_Joystick * joystick, int button) | |
344 | { | |
345 | Uint8 state; | |
346 | ||
347 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
348 | return (0); | |
349 | } | |
350 | if (button < joystick->nbuttons) { | |
351 | state = joystick->buttons[button]; | |
352 | } else { | |
353 | SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); | |
354 | state = 0; | |
355 | } | |
356 | return (state); | |
357 | } | |
358 | ||
359 | /* | |
360 | * Close a joystick previously opened with SDL_JoystickOpen() | |
361 | */ | |
362 | void | |
363 | SDL_JoystickClose(SDL_Joystick * joystick) | |
364 | { | |
365 | int i; | |
366 | ||
367 | if (!SDL_PrivateJoystickValid(&joystick)) { | |
368 | return; | |
369 | } | |
370 | ||
371 | /* First decrement ref count */ | |
372 | if (--joystick->ref_count > 0) { | |
373 | return; | |
374 | } | |
375 | ||
376 | /* Lock the event queue - prevent joystick polling */ | |
377 | SDL_Lock_EventThread(); | |
378 | ||
379 | if (joystick == default_joystick) { | |
380 | default_joystick = NULL; | |
381 | } | |
382 | SDL_SYS_JoystickClose(joystick); | |
383 | ||
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)); | |
389 | break; | |
390 | } | |
391 | } | |
392 | ||
393 | /* Let the event thread keep running */ | |
394 | SDL_Unlock_EventThread(); | |
395 | ||
396 | /* Free the data associated with this joystick */ | |
397 | if (joystick->axes) { | |
398 | SDL_free(joystick->axes); | |
399 | } | |
400 | if (joystick->hats) { | |
401 | SDL_free(joystick->hats); | |
402 | } | |
403 | if (joystick->balls) { | |
404 | SDL_free(joystick->balls); | |
405 | } | |
406 | if (joystick->buttons) { | |
407 | SDL_free(joystick->buttons); | |
408 | } | |
409 | SDL_free(joystick); | |
410 | } | |
411 | ||
412 | void | |
413 | SDL_JoystickQuit(void) | |
414 | { | |
415 | /* Stop the event polling */ | |
416 | SDL_Lock_EventThread(); | |
417 | SDL_numjoysticks = 0; | |
418 | SDL_Unlock_EventThread(); | |
419 | ||
420 | /* Quit the joystick setup */ | |
421 | SDL_SYS_JoystickQuit(); | |
422 | if (SDL_joysticks) { | |
423 | SDL_free(SDL_joysticks); | |
424 | SDL_joysticks = NULL; | |
425 | } | |
426 | } | |
427 | ||
428 | ||
429 | /* These are global for SDL_sysjoystick.c and SDL_events.c */ | |
430 | ||
431 | int | |
432 | SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value) | |
433 | { | |
434 | int posted; | |
435 | ||
436 | /* Update internal joystick state */ | |
437 | joystick->axes[axis] = value; | |
438 | ||
439 | /* Post the event, if desired */ | |
440 | posted = 0; | |
441 | ||
442 | return (posted); | |
443 | } | |
444 | ||
445 | int | |
446 | SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value) | |
447 | { | |
448 | int posted; | |
449 | ||
450 | /* Update internal joystick state */ | |
451 | joystick->hats[hat] = value; | |
452 | ||
453 | /* Post the event, if desired */ | |
454 | posted = 0; | |
455 | ||
456 | return (posted); | |
457 | } | |
458 | ||
459 | int | |
460 | SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, | |
461 | Sint16 xrel, Sint16 yrel) | |
462 | { | |
463 | int posted; | |
464 | ||
465 | /* Update internal mouse state */ | |
466 | joystick->balls[ball].dx += xrel; | |
467 | joystick->balls[ball].dy += yrel; | |
468 | ||
469 | /* Post the event, if desired */ | |
470 | posted = 0; | |
471 | ||
472 | return (posted); | |
473 | } | |
474 | ||
475 | int | |
476 | SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state) | |
477 | { | |
478 | int posted; | |
479 | ||
480 | /* Update internal joystick state */ | |
481 | joystick->buttons[button] = state; | |
482 | ||
483 | /* Post the event, if desired */ | |
484 | posted = 0; | |
485 | ||
486 | return (posted); | |
487 | } | |
488 | ||
489 | void | |
490 | SDL_JoystickUpdate(void) | |
491 | { | |
492 | int i; | |
493 | ||
494 | for (i = 0; SDL_joysticks[i]; ++i) { | |
495 | SDL_SYS_JoystickUpdate(SDL_joysticks[i]); | |
496 | } | |
497 | } | |
498 | ||
499 | int | |
500 | SDL_JoystickEventState(int state) | |
501 | { | |
502 | return SDL_IGNORE; | |
503 | } |