diff options
Diffstat (limited to 'apps/plugins/sdl/src/joystick')
-rw-r--r-- | apps/plugins/sdl/src/joystick/SDL_joystick.c | 606 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/SDL_joystick_c.h | 38 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/SDL_sysjoystick.h | 82 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/beos/SDL_bejoystick.cc | 237 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/bsd/SDL_sysjoystick.c | 608 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/darwin/SDL_sysjoystick.c | 842 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/dc/SDL_sysjoystick.c | 193 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/dummy/SDL_sysjoystick.c | 83 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/linux/SDL_sysjoystick.c | 1218 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/macos/SDL_sysjoystick.c | 320 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c | 826 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/nds/SDL_sysjoystick.c | 150 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/riscos/SDL_sysjoystick.c | 176 | ||||
-rw-r--r-- | apps/plugins/sdl/src/joystick/win32/SDL_mmjoystick.c | 407 |
14 files changed, 5786 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/joystick/SDL_joystick.c b/apps/plugins/sdl/src/joystick/SDL_joystick.c new file mode 100644 index 0000000000..083b01701d --- /dev/null +++ b/apps/plugins/sdl/src/joystick/SDL_joystick.c | |||
@@ -0,0 +1,606 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | |||
26 | #include "SDL_events.h" | ||
27 | #include "SDL_sysjoystick.h" | ||
28 | #include "SDL_joystick_c.h" | ||
29 | #if !SDL_EVENTS_DISABLED | ||
30 | #include "../events/SDL_events_c.h" | ||
31 | #endif | ||
32 | |||
33 | /* This is used for Quake III Arena */ | ||
34 | #if SDL_EVENTS_DISABLED | ||
35 | #define SDL_Lock_EventThread() | ||
36 | #define SDL_Unlock_EventThread() | ||
37 | #endif | ||
38 | |||
39 | Uint8 SDL_numjoysticks = 0; | ||
40 | int SDL_allocatedjoysticks = 0; | ||
41 | SDL_Joystick **SDL_joysticks = NULL; | ||
42 | |||
43 | int SDL_JoystickInit(void) | ||
44 | { | ||
45 | int arraylen; | ||
46 | int status; | ||
47 | |||
48 | SDL_numjoysticks = 0; | ||
49 | status = SDL_SYS_JoystickInit(); | ||
50 | if ( status >= 0 ) { | ||
51 | SDL_allocatedjoysticks = status; | ||
52 | arraylen = (SDL_allocatedjoysticks+1)*sizeof(*SDL_joysticks); | ||
53 | SDL_joysticks = (SDL_Joystick **)SDL_malloc(arraylen); | ||
54 | if ( SDL_joysticks == NULL ) { | ||
55 | SDL_numjoysticks = 0; | ||
56 | SDL_allocatedjoysticks = 0; | ||
57 | } else { | ||
58 | SDL_memset(SDL_joysticks, 0, arraylen); | ||
59 | SDL_numjoysticks = status; | ||
60 | } | ||
61 | status = 0; | ||
62 | } | ||
63 | return(status); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Count the number of joysticks attached to the system | ||
68 | */ | ||
69 | int SDL_NumJoysticks(void) | ||
70 | { | ||
71 | return SDL_numjoysticks; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Get the implementation dependent name of a joystick | ||
76 | */ | ||
77 | const char *SDL_JoystickName(int device_index) | ||
78 | { | ||
79 | if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { | ||
80 | SDL_SetError("There are %d joysticks available", | ||
81 | SDL_numjoysticks); | ||
82 | return(NULL); | ||
83 | } | ||
84 | return(SDL_SYS_JoystickName(device_index)); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Open a joystick for use - the index passed as an argument refers to | ||
89 | * the N'th joystick on the system. This index is the value which will | ||
90 | * identify this joystick in future joystick events. | ||
91 | * | ||
92 | * This function returns a joystick identifier, or NULL if an error occurred. | ||
93 | */ | ||
94 | SDL_Joystick *SDL_JoystickOpen(int device_index) | ||
95 | { | ||
96 | int i; | ||
97 | SDL_Joystick *joystick; | ||
98 | |||
99 | if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { | ||
100 | SDL_SetError("There are %d joysticks available", | ||
101 | SDL_numjoysticks); | ||
102 | return(NULL); | ||
103 | } | ||
104 | |||
105 | /* If the joystick is already open, return it */ | ||
106 | for ( i=0; SDL_joysticks[i]; ++i ) { | ||
107 | if ( device_index == SDL_joysticks[i]->index ) { | ||
108 | joystick = SDL_joysticks[i]; | ||
109 | ++joystick->ref_count; | ||
110 | return(joystick); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /* Create and initialize the joystick */ | ||
115 | joystick = (SDL_Joystick *)SDL_malloc((sizeof *joystick)); | ||
116 | if ( !joystick ) { | ||
117 | SDL_OutOfMemory(); | ||
118 | return(NULL); | ||
119 | } | ||
120 | |||
121 | SDL_memset(joystick, 0, (sizeof *joystick)); | ||
122 | joystick->index = device_index; | ||
123 | if ( SDL_SYS_JoystickOpen(joystick) < 0 ) { | ||
124 | SDL_free(joystick); | ||
125 | return(NULL); | ||
126 | } | ||
127 | |||
128 | if ( joystick->naxes > 0 ) { | ||
129 | joystick->axes = (Sint16 *)SDL_malloc | ||
130 | (joystick->naxes*sizeof(Sint16)); | ||
131 | } | ||
132 | if ( joystick->nhats > 0 ) { | ||
133 | joystick->hats = (Uint8 *)SDL_malloc | ||
134 | (joystick->nhats*sizeof(Uint8)); | ||
135 | } | ||
136 | if ( joystick->nballs > 0 ) { | ||
137 | joystick->balls = (struct balldelta *)SDL_malloc | ||
138 | (joystick->nballs*sizeof(*joystick->balls)); | ||
139 | } | ||
140 | if ( joystick->nbuttons > 0 ) { | ||
141 | joystick->buttons = (Uint8 *)SDL_malloc | ||
142 | (joystick->nbuttons*sizeof(Uint8)); | ||
143 | } | ||
144 | if ( ((joystick->naxes > 0) && !joystick->axes) | ||
145 | || ((joystick->nhats > 0) && !joystick->hats) | ||
146 | || ((joystick->nballs > 0) && !joystick->balls) | ||
147 | || ((joystick->nbuttons > 0) && !joystick->buttons)) { | ||
148 | SDL_OutOfMemory(); | ||
149 | SDL_JoystickClose(joystick); | ||
150 | return(NULL); | ||
151 | } | ||
152 | |||
153 | if ( joystick->axes ) { | ||
154 | SDL_memset(joystick->axes, 0, | ||
155 | joystick->naxes*sizeof(Sint16)); | ||
156 | } | ||
157 | if ( joystick->hats ) { | ||
158 | SDL_memset(joystick->hats, 0, | ||
159 | joystick->nhats*sizeof(Uint8)); | ||
160 | } | ||
161 | if ( joystick->balls ) { | ||
162 | SDL_memset(joystick->balls, 0, | ||
163 | joystick->nballs*sizeof(*joystick->balls)); | ||
164 | } | ||
165 | if ( joystick->buttons ) { | ||
166 | SDL_memset(joystick->buttons, 0, | ||
167 | joystick->nbuttons*sizeof(Uint8)); | ||
168 | } | ||
169 | |||
170 | /* Add joystick to list */ | ||
171 | ++joystick->ref_count; | ||
172 | SDL_Lock_EventThread(); | ||
173 | for ( i=0; SDL_joysticks[i]; ++i ) | ||
174 | /* Skip to next joystick */ ; | ||
175 | SDL_joysticks[i] = joystick; | ||
176 | SDL_Unlock_EventThread(); | ||
177 | |||
178 | return(joystick); | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Returns 1 if the joystick has been opened, or 0 if it has not. | ||
183 | */ | ||
184 | int SDL_JoystickOpened(int device_index) | ||
185 | { | ||
186 | int i, opened; | ||
187 | |||
188 | opened = 0; | ||
189 | for ( i=0; SDL_joysticks[i]; ++i ) { | ||
190 | if ( SDL_joysticks[i]->index == (Uint8)device_index ) { | ||
191 | opened = 1; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | return(opened); | ||
196 | } | ||
197 | |||
198 | static int ValidJoystick(SDL_Joystick **joystick) | ||
199 | { | ||
200 | int valid; | ||
201 | |||
202 | if ( *joystick == NULL ) { | ||
203 | SDL_SetError("Joystick hasn't been opened yet"); | ||
204 | valid = 0; | ||
205 | } else { | ||
206 | valid = 1; | ||
207 | } | ||
208 | return valid; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Get the device index of an opened joystick. | ||
213 | */ | ||
214 | int SDL_JoystickIndex(SDL_Joystick *joystick) | ||
215 | { | ||
216 | if ( ! ValidJoystick(&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 SDL_JoystickNumAxes(SDL_Joystick *joystick) | ||
226 | { | ||
227 | if ( ! ValidJoystick(&joystick) ) { | ||
228 | return(-1); | ||
229 | } | ||
230 | return(joystick->naxes); | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Get the number of hats on a joystick | ||
235 | */ | ||
236 | int SDL_JoystickNumHats(SDL_Joystick *joystick) | ||
237 | { | ||
238 | if ( ! ValidJoystick(&joystick) ) { | ||
239 | return(-1); | ||
240 | } | ||
241 | return(joystick->nhats); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Get the number of trackballs on a joystick | ||
246 | */ | ||
247 | int SDL_JoystickNumBalls(SDL_Joystick *joystick) | ||
248 | { | ||
249 | if ( ! ValidJoystick(&joystick) ) { | ||
250 | return(-1); | ||
251 | } | ||
252 | return(joystick->nballs); | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Get the number of buttons on a joystick | ||
257 | */ | ||
258 | int SDL_JoystickNumButtons(SDL_Joystick *joystick) | ||
259 | { | ||
260 | if ( ! ValidJoystick(&joystick) ) { | ||
261 | return(-1); | ||
262 | } | ||
263 | return(joystick->nbuttons); | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Get the current state of an axis control on a joystick | ||
268 | */ | ||
269 | Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) | ||
270 | { | ||
271 | Sint16 state; | ||
272 | |||
273 | if ( ! ValidJoystick(&joystick) ) { | ||
274 | return(0); | ||
275 | } | ||
276 | if ( axis < joystick->naxes ) { | ||
277 | state = joystick->axes[axis]; | ||
278 | } else { | ||
279 | SDL_SetError("Joystick only has %d axes", joystick->naxes); | ||
280 | state = 0; | ||
281 | } | ||
282 | return(state); | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Get the current state of a hat on a joystick | ||
287 | */ | ||
288 | Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) | ||
289 | { | ||
290 | Uint8 state; | ||
291 | |||
292 | if ( ! ValidJoystick(&joystick) ) { | ||
293 | return(0); | ||
294 | } | ||
295 | if ( hat < joystick->nhats ) { | ||
296 | state = joystick->hats[hat]; | ||
297 | } else { | ||
298 | SDL_SetError("Joystick only has %d hats", joystick->nhats); | ||
299 | state = 0; | ||
300 | } | ||
301 | return(state); | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Get the ball axis change since the last poll | ||
306 | */ | ||
307 | int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) | ||
308 | { | ||
309 | int retval; | ||
310 | |||
311 | if ( ! ValidJoystick(&joystick) ) { | ||
312 | return(-1); | ||
313 | } | ||
314 | |||
315 | retval = 0; | ||
316 | if ( ball < joystick->nballs ) { | ||
317 | if ( dx ) { | ||
318 | *dx = joystick->balls[ball].dx; | ||
319 | } | ||
320 | if ( dy ) { | ||
321 | *dy = joystick->balls[ball].dy; | ||
322 | } | ||
323 | joystick->balls[ball].dx = 0; | ||
324 | joystick->balls[ball].dy = 0; | ||
325 | } else { | ||
326 | SDL_SetError("Joystick only has %d balls", joystick->nballs); | ||
327 | retval = -1; | ||
328 | } | ||
329 | return(retval); | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * Get the current state of a button on a joystick | ||
334 | */ | ||
335 | Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) | ||
336 | { | ||
337 | Uint8 state; | ||
338 | |||
339 | if ( ! ValidJoystick(&joystick) ) { | ||
340 | return(0); | ||
341 | } | ||
342 | if ( button < joystick->nbuttons ) { | ||
343 | state = joystick->buttons[button]; | ||
344 | } else { | ||
345 | SDL_SetError("Joystick only has %d buttons",joystick->nbuttons); | ||
346 | state = 0; | ||
347 | } | ||
348 | return(state); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * Close a joystick previously opened with SDL_JoystickOpen() | ||
353 | */ | ||
354 | void SDL_JoystickClose(SDL_Joystick *joystick) | ||
355 | { | ||
356 | int i; | ||
357 | |||
358 | if ( ! ValidJoystick(&joystick) ) { | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | /* First decrement ref count */ | ||
363 | if ( --joystick->ref_count > 0 ) { | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | /* Lock the event queue - prevent joystick polling */ | ||
368 | SDL_Lock_EventThread(); | ||
369 | |||
370 | SDL_SYS_JoystickClose(joystick); | ||
371 | |||
372 | /* Remove joystick from list */ | ||
373 | for ( i=0; SDL_joysticks[i]; ++i ) { | ||
374 | if ( joystick == SDL_joysticks[i] ) { | ||
375 | SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i+1], | ||
376 | (SDL_allocatedjoysticks-i)*sizeof(joystick)); | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* Let the event thread keep running */ | ||
382 | SDL_Unlock_EventThread(); | ||
383 | |||
384 | /* Free the data associated with this joystick */ | ||
385 | if ( joystick->axes ) { | ||
386 | SDL_free(joystick->axes); | ||
387 | } | ||
388 | if ( joystick->hats ) { | ||
389 | SDL_free(joystick->hats); | ||
390 | } | ||
391 | if ( joystick->balls ) { | ||
392 | SDL_free(joystick->balls); | ||
393 | } | ||
394 | if ( joystick->buttons ) { | ||
395 | SDL_free(joystick->buttons); | ||
396 | } | ||
397 | SDL_free(joystick); | ||
398 | } | ||
399 | |||
400 | void SDL_JoystickQuit(void) | ||
401 | { | ||
402 | const int numsticks = SDL_numjoysticks; | ||
403 | int i; | ||
404 | |||
405 | /* Stop the event polling */ | ||
406 | SDL_Lock_EventThread(); | ||
407 | SDL_numjoysticks = 0; | ||
408 | SDL_Unlock_EventThread(); | ||
409 | |||
410 | if (SDL_joysticks != NULL) { | ||
411 | for (i = 0; i < numsticks; i++) { | ||
412 | SDL_Joystick *stick = SDL_joysticks[i]; | ||
413 | if (stick && (stick->ref_count >= 1)) { | ||
414 | stick->ref_count = 1; | ||
415 | SDL_JoystickClose(stick); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | |||
420 | /* Quit the joystick setup */ | ||
421 | SDL_SYS_JoystickQuit(); | ||
422 | if ( SDL_joysticks ) { | ||
423 | SDL_free(SDL_joysticks); | ||
424 | SDL_joysticks = NULL; | ||
425 | SDL_allocatedjoysticks = 0; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | |||
430 | /* These are global for SDL_sysjoystick.c and SDL_events.c */ | ||
431 | |||
432 | int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value) | ||
433 | { | ||
434 | int posted; | ||
435 | |||
436 | /* Make sure we're not getting garbage events */ | ||
437 | if (axis >= joystick->naxes) { | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /* Update internal joystick state */ | ||
442 | joystick->axes[axis] = value; | ||
443 | |||
444 | /* Post the event, if desired */ | ||
445 | posted = 0; | ||
446 | #if !SDL_EVENTS_DISABLED | ||
447 | if ( SDL_ProcessEvents[SDL_JOYAXISMOTION] == SDL_ENABLE ) { | ||
448 | SDL_Event event; | ||
449 | event.type = SDL_JOYAXISMOTION; | ||
450 | event.jaxis.which = joystick->index; | ||
451 | event.jaxis.axis = axis; | ||
452 | event.jaxis.value = value; | ||
453 | if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | ||
454 | posted = 1; | ||
455 | SDL_PushEvent(&event); | ||
456 | } | ||
457 | } | ||
458 | #endif /* !SDL_EVENTS_DISABLED */ | ||
459 | return(posted); | ||
460 | } | ||
461 | |||
462 | int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) | ||
463 | { | ||
464 | int posted; | ||
465 | |||
466 | /* Make sure we're not getting garbage events */ | ||
467 | if (hat >= joystick->nhats) { | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | /* Update internal joystick state */ | ||
472 | joystick->hats[hat] = value; | ||
473 | |||
474 | /* Post the event, if desired */ | ||
475 | posted = 0; | ||
476 | #if !SDL_EVENTS_DISABLED | ||
477 | if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) { | ||
478 | SDL_Event event; | ||
479 | event.jhat.type = SDL_JOYHATMOTION; | ||
480 | event.jhat.which = joystick->index; | ||
481 | event.jhat.hat = hat; | ||
482 | event.jhat.value = value; | ||
483 | if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | ||
484 | posted = 1; | ||
485 | SDL_PushEvent(&event); | ||
486 | } | ||
487 | } | ||
488 | #endif /* !SDL_EVENTS_DISABLED */ | ||
489 | return(posted); | ||
490 | } | ||
491 | |||
492 | int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, | ||
493 | Sint16 xrel, Sint16 yrel) | ||
494 | { | ||
495 | int posted; | ||
496 | |||
497 | /* Make sure we're not getting garbage events */ | ||
498 | if (ball >= joystick->nballs) { | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /* Update internal mouse state */ | ||
503 | joystick->balls[ball].dx += xrel; | ||
504 | joystick->balls[ball].dy += yrel; | ||
505 | |||
506 | /* Post the event, if desired */ | ||
507 | posted = 0; | ||
508 | #if !SDL_EVENTS_DISABLED | ||
509 | if ( SDL_ProcessEvents[SDL_JOYBALLMOTION] == SDL_ENABLE ) { | ||
510 | SDL_Event event; | ||
511 | event.jball.type = SDL_JOYBALLMOTION; | ||
512 | event.jball.which = joystick->index; | ||
513 | event.jball.ball = ball; | ||
514 | event.jball.xrel = xrel; | ||
515 | event.jball.yrel = yrel; | ||
516 | if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | ||
517 | posted = 1; | ||
518 | SDL_PushEvent(&event); | ||
519 | } | ||
520 | } | ||
521 | #endif /* !SDL_EVENTS_DISABLED */ | ||
522 | return(posted); | ||
523 | } | ||
524 | |||
525 | int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) | ||
526 | { | ||
527 | int posted; | ||
528 | #if !SDL_EVENTS_DISABLED | ||
529 | SDL_Event event; | ||
530 | |||
531 | switch ( state ) { | ||
532 | case SDL_PRESSED: | ||
533 | event.type = SDL_JOYBUTTONDOWN; | ||
534 | break; | ||
535 | case SDL_RELEASED: | ||
536 | event.type = SDL_JOYBUTTONUP; | ||
537 | break; | ||
538 | default: | ||
539 | /* Invalid state -- bail */ | ||
540 | return(0); | ||
541 | } | ||
542 | #endif /* !SDL_EVENTS_DISABLED */ | ||
543 | |||
544 | /* Make sure we're not getting garbage events */ | ||
545 | if (button >= joystick->nbuttons) { | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | /* Update internal joystick state */ | ||
550 | joystick->buttons[button] = state; | ||
551 | |||
552 | /* Post the event, if desired */ | ||
553 | posted = 0; | ||
554 | #if !SDL_EVENTS_DISABLED | ||
555 | if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { | ||
556 | event.jbutton.which = joystick->index; | ||
557 | event.jbutton.button = button; | ||
558 | event.jbutton.state = state; | ||
559 | if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | ||
560 | posted = 1; | ||
561 | SDL_PushEvent(&event); | ||
562 | } | ||
563 | } | ||
564 | #endif /* !SDL_EVENTS_DISABLED */ | ||
565 | return(posted); | ||
566 | } | ||
567 | |||
568 | void SDL_JoystickUpdate(void) | ||
569 | { | ||
570 | int i; | ||
571 | |||
572 | for ( i=0; SDL_joysticks[i]; ++i ) { | ||
573 | SDL_SYS_JoystickUpdate(SDL_joysticks[i]); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | int SDL_JoystickEventState(int state) | ||
578 | { | ||
579 | #if SDL_EVENTS_DISABLED | ||
580 | return SDL_IGNORE; | ||
581 | #else | ||
582 | const Uint8 event_list[] = { | ||
583 | SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, | ||
584 | SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, | ||
585 | }; | ||
586 | unsigned int i; | ||
587 | |||
588 | switch (state) { | ||
589 | case SDL_QUERY: | ||
590 | state = SDL_IGNORE; | ||
591 | for ( i=0; i<SDL_arraysize(event_list); ++i ) { | ||
592 | state = SDL_EventState(event_list[i],SDL_QUERY); | ||
593 | if ( state == SDL_ENABLE ) { | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | break; | ||
598 | default: | ||
599 | for ( i=0; i<SDL_arraysize(event_list); ++i ) { | ||
600 | SDL_EventState(event_list[i], state); | ||
601 | } | ||
602 | break; | ||
603 | } | ||
604 | return(state); | ||
605 | #endif /* SDL_EVENTS_DISABLED */ | ||
606 | } | ||
diff --git a/apps/plugins/sdl/src/joystick/SDL_joystick_c.h b/apps/plugins/sdl/src/joystick/SDL_joystick_c.h new file mode 100644 index 0000000000..9a9d130862 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/SDL_joystick_c.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | /* Useful functions and variables from SDL_joystick.c */ | ||
25 | #include "SDL_joystick.h" | ||
26 | |||
27 | /* The number of available joysticks on the system */ | ||
28 | extern Uint8 SDL_numjoysticks; | ||
29 | |||
30 | /* Internal event queueing functions */ | ||
31 | extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, | ||
32 | Uint8 axis, Sint16 value); | ||
33 | extern int SDL_PrivateJoystickBall(SDL_Joystick *joystick, | ||
34 | Uint8 ball, Sint16 xrel, Sint16 yrel); | ||
35 | extern int SDL_PrivateJoystickHat(SDL_Joystick *joystick, | ||
36 | Uint8 hat, Uint8 value); | ||
37 | extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick, | ||
38 | Uint8 button, Uint8 state); | ||
diff --git a/apps/plugins/sdl/src/joystick/SDL_sysjoystick.h b/apps/plugins/sdl/src/joystick/SDL_sysjoystick.h new file mode 100644 index 0000000000..6a1b76a62f --- /dev/null +++ b/apps/plugins/sdl/src/joystick/SDL_sysjoystick.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is SDL_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 system specific header for the SDL joystick API */ | ||
25 | |||
26 | #include "SDL_joystick.h" | ||
27 | |||
28 | /* The SDL joystick structure */ | ||
29 | struct _SDL_Joystick { | ||
30 | Uint8 index; /* Device index */ | ||
31 | const char *name; /* Joystick name - system dependent */ | ||
32 | |||
33 | int naxes; /* Number of axis controls on the joystick */ | ||
34 | Sint16 *axes; /* Current axis states */ | ||
35 | |||
36 | int nhats; /* Number of hats on the joystick */ | ||
37 | Uint8 *hats; /* Current hat states */ | ||
38 | |||
39 | int nballs; /* Number of trackballs on the joystick */ | ||
40 | struct balldelta { | ||
41 | int dx; | ||
42 | int dy; | ||
43 | } *balls; /* Current ball motion deltas */ | ||
44 | |||
45 | int nbuttons; /* Number of buttons on the joystick */ | ||
46 | Uint8 *buttons; /* Current button states */ | ||
47 | |||
48 | struct joystick_hwdata *hwdata; /* Driver dependent information */ | ||
49 | |||
50 | int ref_count; /* Reference count for multiple opens */ | ||
51 | }; | ||
52 | |||
53 | /* Function to scan the system for joysticks. | ||
54 | * Joystick 0 should be the system default joystick. | ||
55 | * This function should return the number of available joysticks, or -1 | ||
56 | * on an unrecoverable fatal error. | ||
57 | */ | ||
58 | extern int SDL_SYS_JoystickInit(void); | ||
59 | |||
60 | /* Function to get the device-dependent name of a joystick */ | ||
61 | extern const char *SDL_SYS_JoystickName(int index); | ||
62 | |||
63 | /* Function to open a joystick for use. | ||
64 | The joystick to open is specified by the index field of the joystick. | ||
65 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
66 | It returns 0, or -1 if there is an error. | ||
67 | */ | ||
68 | extern int SDL_SYS_JoystickOpen(SDL_Joystick *joystick); | ||
69 | |||
70 | /* Function to update the state of a joystick - called as a device poll. | ||
71 | * This function shouldn't update the joystick structure directly, | ||
72 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
73 | * and update joystick device state. | ||
74 | */ | ||
75 | extern void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick); | ||
76 | |||
77 | /* Function to close a joystick after use */ | ||
78 | extern void SDL_SYS_JoystickClose(SDL_Joystick *joystick); | ||
79 | |||
80 | /* Function to perform any system-specific joystick related cleanup */ | ||
81 | extern void SDL_SYS_JoystickQuit(void); | ||
82 | |||
diff --git a/apps/plugins/sdl/src/joystick/beos/SDL_bejoystick.cc b/apps/plugins/sdl/src/joystick/beos/SDL_bejoystick.cc new file mode 100644 index 0000000000..af8a34164b --- /dev/null +++ b/apps/plugins/sdl/src/joystick/beos/SDL_bejoystick.cc | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_BEOS | ||
25 | |||
26 | /* This is the system specific header for the SDL joystick API */ | ||
27 | |||
28 | #include <be/support/String.h> | ||
29 | #include <be/device/Joystick.h> | ||
30 | |||
31 | extern "C" { | ||
32 | |||
33 | #include "SDL_joystick.h" | ||
34 | #include "../SDL_sysjoystick.h" | ||
35 | #include "../SDL_joystick_c.h" | ||
36 | |||
37 | |||
38 | /* The maximum number of joysticks we'll detect */ | ||
39 | #define MAX_JOYSTICKS 16 | ||
40 | |||
41 | /* A list of available joysticks */ | ||
42 | static char *SDL_joyport[MAX_JOYSTICKS]; | ||
43 | static char *SDL_joyname[MAX_JOYSTICKS]; | ||
44 | |||
45 | /* The private structure used to keep track of a joystick */ | ||
46 | struct joystick_hwdata { | ||
47 | BJoystick *stick; | ||
48 | uint8 *new_hats; | ||
49 | int16 *new_axes; | ||
50 | }; | ||
51 | |||
52 | /* Function to scan the system for joysticks. | ||
53 | * This function should set SDL_numjoysticks to the number of available | ||
54 | * joysticks. Joystick 0 should be the system default joystick. | ||
55 | * It should return 0, or -1 on an unrecoverable fatal error. | ||
56 | */ | ||
57 | int SDL_SYS_JoystickInit(void) | ||
58 | { | ||
59 | BJoystick joystick; | ||
60 | int numjoysticks; | ||
61 | int i; | ||
62 | int32 nports; | ||
63 | char name[B_OS_NAME_LENGTH]; | ||
64 | |||
65 | /* Search for attached joysticks */ | ||
66 | nports = joystick.CountDevices(); | ||
67 | numjoysticks = 0; | ||
68 | SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport)); | ||
69 | SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname)); | ||
70 | for ( i=0; (SDL_numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i ) { | ||
71 | if ( joystick.GetDeviceName(i, name) == B_OK ) { | ||
72 | if ( joystick.Open(name) != B_ERROR ) { | ||
73 | BString stick_name; | ||
74 | joystick.GetControllerName(&stick_name); | ||
75 | SDL_joyport[numjoysticks] = strdup(name); | ||
76 | SDL_joyname[numjoysticks] = | ||
77 | strdup(stick_name.String()); | ||
78 | numjoysticks++; | ||
79 | joystick.Close(); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | return(numjoysticks); | ||
84 | } | ||
85 | |||
86 | /* Function to get the device-dependent name of a joystick */ | ||
87 | const char *SDL_SYS_JoystickName(int index) | ||
88 | { | ||
89 | return SDL_joyname[index]; | ||
90 | } | ||
91 | |||
92 | /* Function to open a joystick for use. | ||
93 | The joystick to open is specified by the index field of the joystick. | ||
94 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
95 | It returns 0, or -1 if there is an error. | ||
96 | */ | ||
97 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
98 | { | ||
99 | BJoystick *stick; | ||
100 | |||
101 | /* Create the joystick data structure */ | ||
102 | joystick->hwdata = (struct joystick_hwdata *) | ||
103 | SDL_malloc(sizeof(*joystick->hwdata)); | ||
104 | if ( joystick->hwdata == NULL ) { | ||
105 | SDL_OutOfMemory(); | ||
106 | return(-1); | ||
107 | } | ||
108 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | ||
109 | stick = new BJoystick; | ||
110 | joystick->hwdata->stick = stick; | ||
111 | |||
112 | /* Open the requested joystick for use */ | ||
113 | if ( stick->Open(SDL_joyport[joystick->index]) == B_ERROR ) { | ||
114 | SDL_SetError("Unable to open joystick"); | ||
115 | SDL_SYS_JoystickClose(joystick); | ||
116 | return(-1); | ||
117 | } | ||
118 | |||
119 | /* Set the joystick to calibrated mode */ | ||
120 | stick->EnableCalibration(); | ||
121 | |||
122 | /* Get the number of buttons, hats, and axes on the joystick */ | ||
123 | joystick->nbuttons = stick->CountButtons(); | ||
124 | joystick->naxes = stick->CountAxes(); | ||
125 | joystick->nhats = stick->CountHats(); | ||
126 | |||
127 | joystick->hwdata->new_axes = (int16 *) | ||
128 | SDL_malloc(joystick->naxes*sizeof(int16)); | ||
129 | joystick->hwdata->new_hats = (uint8 *) | ||
130 | SDL_malloc(joystick->nhats*sizeof(uint8)); | ||
131 | if ( ! joystick->hwdata->new_hats || ! joystick->hwdata->new_axes ) { | ||
132 | SDL_OutOfMemory(); | ||
133 | SDL_SYS_JoystickClose(joystick); | ||
134 | return(-1); | ||
135 | } | ||
136 | |||
137 | /* We're done! */ | ||
138 | return(0); | ||
139 | } | ||
140 | |||
141 | /* Function to update the state of a joystick - called as a device poll. | ||
142 | * This function shouldn't update the joystick structure directly, | ||
143 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
144 | * and update joystick device state. | ||
145 | */ | ||
146 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
147 | { | ||
148 | static const Uint8 hat_map[9] = { | ||
149 | SDL_HAT_CENTERED, | ||
150 | SDL_HAT_UP, | ||
151 | SDL_HAT_RIGHTUP, | ||
152 | SDL_HAT_RIGHT, | ||
153 | SDL_HAT_RIGHTDOWN, | ||
154 | SDL_HAT_DOWN, | ||
155 | SDL_HAT_LEFTDOWN, | ||
156 | SDL_HAT_LEFT, | ||
157 | SDL_HAT_LEFTUP | ||
158 | }; | ||
159 | const int JITTER = (32768/10); /* 10% jitter threshold (ok?) */ | ||
160 | |||
161 | BJoystick *stick; | ||
162 | int i, change; | ||
163 | int16 *axes; | ||
164 | uint8 *hats; | ||
165 | uint32 buttons; | ||
166 | |||
167 | /* Set up data pointers */ | ||
168 | stick = joystick->hwdata->stick; | ||
169 | axes = joystick->hwdata->new_axes; | ||
170 | hats = joystick->hwdata->new_hats; | ||
171 | |||
172 | /* Get the new joystick state */ | ||
173 | stick->Update(); | ||
174 | stick->GetAxisValues(axes); | ||
175 | stick->GetHatValues(hats); | ||
176 | buttons = stick->ButtonValues(); | ||
177 | |||
178 | /* Generate axis motion events */ | ||
179 | for ( i=0; i<joystick->naxes; ++i ) { | ||
180 | change = ((int32)axes[i] - joystick->axes[i]); | ||
181 | if ( (change > JITTER) || (change < -JITTER) ) { | ||
182 | SDL_PrivateJoystickAxis(joystick, i, axes[i]); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* Generate hat change events */ | ||
187 | for ( i=0; i<joystick->nhats; ++i ) { | ||
188 | if ( hats[i] != joystick->hats[i] ) { | ||
189 | SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* Generate button events */ | ||
194 | for ( i=0; i<joystick->nbuttons; ++i ) { | ||
195 | if ( (buttons&0x01) != joystick->buttons[i] ) { | ||
196 | SDL_PrivateJoystickButton(joystick, i, (buttons&0x01)); | ||
197 | } | ||
198 | buttons >>= 1; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* Function to close a joystick after use */ | ||
203 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
204 | { | ||
205 | if ( joystick->hwdata ) { | ||
206 | joystick->hwdata->stick->Close(); | ||
207 | delete joystick->hwdata->stick; | ||
208 | if ( joystick->hwdata->new_hats ) { | ||
209 | SDL_free(joystick->hwdata->new_hats); | ||
210 | } | ||
211 | if ( joystick->hwdata->new_axes ) { | ||
212 | SDL_free(joystick->hwdata->new_axes); | ||
213 | } | ||
214 | SDL_free(joystick->hwdata); | ||
215 | joystick->hwdata = NULL; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* Function to perform any system-specific joystick related cleanup */ | ||
220 | void SDL_SYS_JoystickQuit(void) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | for ( i=0; SDL_joyport[i]; ++i ) { | ||
225 | SDL_free(SDL_joyport[i]); | ||
226 | } | ||
227 | SDL_joyport[0] = NULL; | ||
228 | |||
229 | for ( i=0; SDL_joyname[i]; ++i ) { | ||
230 | SDL_free(SDL_joyname[i]); | ||
231 | } | ||
232 | SDL_joyname[0] = NULL; | ||
233 | } | ||
234 | |||
235 | }; // extern "C" | ||
236 | |||
237 | #endif /* SDL_JOYSTICK_BEOS */ | ||
diff --git a/apps/plugins/sdl/src/joystick/bsd/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/bsd/SDL_sysjoystick.c new file mode 100644 index 0000000000..500fc62951 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/bsd/SDL_sysjoystick.c | |||
@@ -0,0 +1,608 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_USBHID | ||
25 | |||
26 | /* | ||
27 | * Joystick driver for the uhid(4) interface found in OpenBSD, | ||
28 | * NetBSD and FreeBSD. | ||
29 | * | ||
30 | * Maintainer: <vedge at csoft.org> | ||
31 | */ | ||
32 | |||
33 | #include <sys/param.h> | ||
34 | |||
35 | #include <unistd.h> | ||
36 | #include <fcntl.h> | ||
37 | #include <errno.h> | ||
38 | |||
39 | #ifndef __FreeBSD_kernel_version | ||
40 | #define __FreeBSD_kernel_version __FreeBSD_version | ||
41 | #endif | ||
42 | |||
43 | #if defined(HAVE_USB_H) | ||
44 | #include <usb.h> | ||
45 | #endif | ||
46 | #ifdef __DragonFly__ | ||
47 | #include <bus/usb/usb.h> | ||
48 | #include <bus/usb/usbhid.h> | ||
49 | #else | ||
50 | #include <dev/usb/usb.h> | ||
51 | #include <dev/usb/usbhid.h> | ||
52 | #endif | ||
53 | |||
54 | #if defined(HAVE_USBHID_H) | ||
55 | #include <usbhid.h> | ||
56 | #elif defined(HAVE_LIBUSB_H) | ||
57 | #include <libusb.h> | ||
58 | #elif defined(HAVE_LIBUSBHID_H) | ||
59 | #include <libusbhid.h> | ||
60 | #endif | ||
61 | |||
62 | #if defined(__FREEBSD__) || defined(__FreeBSD_kernel__) | ||
63 | #ifndef __DragonFly__ | ||
64 | #include <osreldate.h> | ||
65 | #endif | ||
66 | #if __FreeBSD_kernel_version > 800063 | ||
67 | #include <dev/usb/usb_ioctl.h> | ||
68 | #endif | ||
69 | #include <sys/joystick.h> | ||
70 | #endif | ||
71 | |||
72 | #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H | ||
73 | #include <machine/joystick.h> | ||
74 | #endif | ||
75 | |||
76 | #include "SDL_joystick.h" | ||
77 | #include "../SDL_sysjoystick.h" | ||
78 | #include "../SDL_joystick_c.h" | ||
79 | |||
80 | #define MAX_UHID_JOYS 4 | ||
81 | #define MAX_JOY_JOYS 2 | ||
82 | #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) | ||
83 | |||
84 | struct report { | ||
85 | #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) | ||
86 | struct usb_gen_descriptor *buf; /* Buffer */ | ||
87 | #else | ||
88 | struct usb_ctl_report *buf; /* Buffer */ | ||
89 | #endif | ||
90 | size_t size; /* Buffer size */ | ||
91 | int rid; /* Report ID */ | ||
92 | enum { | ||
93 | SREPORT_UNINIT, | ||
94 | SREPORT_CLEAN, | ||
95 | SREPORT_DIRTY | ||
96 | } status; | ||
97 | }; | ||
98 | |||
99 | static struct { | ||
100 | int uhid_report; | ||
101 | hid_kind_t kind; | ||
102 | const char *name; | ||
103 | } const repinfo[] = { | ||
104 | { UHID_INPUT_REPORT, hid_input, "input" }, | ||
105 | { UHID_OUTPUT_REPORT, hid_output, "output" }, | ||
106 | { UHID_FEATURE_REPORT, hid_feature, "feature" } | ||
107 | }; | ||
108 | |||
109 | enum { | ||
110 | REPORT_INPUT = 0, | ||
111 | REPORT_OUTPUT = 1, | ||
112 | REPORT_FEATURE = 2 | ||
113 | }; | ||
114 | |||
115 | enum { | ||
116 | JOYAXE_X, | ||
117 | JOYAXE_Y, | ||
118 | JOYAXE_Z, | ||
119 | JOYAXE_SLIDER, | ||
120 | JOYAXE_WHEEL, | ||
121 | JOYAXE_RX, | ||
122 | JOYAXE_RY, | ||
123 | JOYAXE_RZ, | ||
124 | JOYAXE_count | ||
125 | }; | ||
126 | |||
127 | struct joystick_hwdata { | ||
128 | int fd; | ||
129 | char *path; | ||
130 | enum { | ||
131 | BSDJOY_UHID, /* uhid(4) */ | ||
132 | BSDJOY_JOY /* joy(4) */ | ||
133 | } type; | ||
134 | struct report_desc *repdesc; | ||
135 | struct report inreport; | ||
136 | int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,..*/ | ||
137 | int x; | ||
138 | int y; | ||
139 | int xmin; | ||
140 | int ymin; | ||
141 | int xmax; | ||
142 | int ymax; | ||
143 | }; | ||
144 | |||
145 | static char *joynames[MAX_JOYS]; | ||
146 | static char *joydevnames[MAX_JOYS]; | ||
147 | |||
148 | static int report_alloc(struct report *, struct report_desc *, int); | ||
149 | static void report_free(struct report *); | ||
150 | |||
151 | #if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) | ||
152 | #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) | ||
153 | #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) | ||
154 | #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) | ||
155 | #else | ||
156 | #define REP_BUF_DATA(rep) ((rep)->buf->data) | ||
157 | #endif | ||
158 | |||
159 | int | ||
160 | SDL_SYS_JoystickInit(void) | ||
161 | { | ||
162 | char s[16]; | ||
163 | int i, fd; | ||
164 | |||
165 | SDL_numjoysticks = 0; | ||
166 | |||
167 | SDL_memset(joynames, 0, sizeof(joynames)); | ||
168 | SDL_memset(joydevnames, 0, sizeof(joydevnames)); | ||
169 | |||
170 | for (i = 0; i < MAX_UHID_JOYS; i++) { | ||
171 | SDL_Joystick nj; | ||
172 | |||
173 | SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i); | ||
174 | |||
175 | nj.index = SDL_numjoysticks; | ||
176 | joynames[nj.index] = strdup(s); | ||
177 | |||
178 | if (SDL_SYS_JoystickOpen(&nj) == 0) { | ||
179 | SDL_SYS_JoystickClose(&nj); | ||
180 | SDL_numjoysticks++; | ||
181 | } else { | ||
182 | SDL_free(joynames[nj.index]); | ||
183 | joynames[nj.index] = NULL; | ||
184 | } | ||
185 | } | ||
186 | for (i = 0; i < MAX_JOY_JOYS; i++) { | ||
187 | SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i); | ||
188 | fd = open(s, O_RDONLY); | ||
189 | if (fd != -1) { | ||
190 | joynames[SDL_numjoysticks++] = strdup(s); | ||
191 | close(fd); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | /* Read the default USB HID usage table. */ | ||
196 | hid_init(NULL); | ||
197 | |||
198 | return (SDL_numjoysticks); | ||
199 | } | ||
200 | |||
201 | const char * | ||
202 | SDL_SYS_JoystickName(int index) | ||
203 | { | ||
204 | if (joydevnames[index] != NULL) { | ||
205 | return (joydevnames[index]); | ||
206 | } | ||
207 | return (joynames[index]); | ||
208 | } | ||
209 | |||
210 | static int | ||
211 | usage_to_joyaxe(unsigned usage) | ||
212 | { | ||
213 | int joyaxe; | ||
214 | switch (usage) { | ||
215 | case HUG_X: | ||
216 | joyaxe = JOYAXE_X; break; | ||
217 | case HUG_Y: | ||
218 | joyaxe = JOYAXE_Y; break; | ||
219 | case HUG_Z: | ||
220 | joyaxe = JOYAXE_Z; break; | ||
221 | case HUG_SLIDER: | ||
222 | joyaxe = JOYAXE_SLIDER; break; | ||
223 | case HUG_WHEEL: | ||
224 | joyaxe = JOYAXE_WHEEL; break; | ||
225 | case HUG_RX: | ||
226 | joyaxe = JOYAXE_RX; break; | ||
227 | case HUG_RY: | ||
228 | joyaxe = JOYAXE_RY; break; | ||
229 | case HUG_RZ: | ||
230 | joyaxe = JOYAXE_RZ; break; | ||
231 | default: | ||
232 | joyaxe = -1; | ||
233 | } | ||
234 | return joyaxe; | ||
235 | } | ||
236 | |||
237 | static unsigned | ||
238 | hatval_to_sdl(Sint32 hatval) | ||
239 | { | ||
240 | static const unsigned hat_dir_map[8] = { | ||
241 | SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN, | ||
242 | SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP | ||
243 | }; | ||
244 | unsigned result; | ||
245 | if ((hatval & 7) == hatval) | ||
246 | result = hat_dir_map[hatval]; | ||
247 | else | ||
248 | result = SDL_HAT_CENTERED; | ||
249 | return result; | ||
250 | } | ||
251 | |||
252 | |||
253 | int | ||
254 | SDL_SYS_JoystickOpen(SDL_Joystick *joy) | ||
255 | { | ||
256 | char *path = joynames[joy->index]; | ||
257 | struct joystick_hwdata *hw; | ||
258 | struct hid_item hitem; | ||
259 | struct hid_data *hdata; | ||
260 | struct report *rep; | ||
261 | int fd; | ||
262 | int i; | ||
263 | |||
264 | fd = open(path, O_RDONLY); | ||
265 | if (fd == -1) { | ||
266 | SDL_SetError("%s: %s", path, strerror(errno)); | ||
267 | return (-1); | ||
268 | } | ||
269 | |||
270 | hw = (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata)); | ||
271 | if (hw == NULL) { | ||
272 | SDL_OutOfMemory(); | ||
273 | close(fd); | ||
274 | return (-1); | ||
275 | } | ||
276 | joy->hwdata = hw; | ||
277 | hw->fd = fd; | ||
278 | hw->path = strdup(path); | ||
279 | hw->x = 0; | ||
280 | hw->y = 0; | ||
281 | hw->xmin = 0xffff; | ||
282 | hw->ymin = 0xffff; | ||
283 | hw->xmax = 0; | ||
284 | hw->ymax = 0; | ||
285 | if (! SDL_strncmp(path, "/dev/joy", 8)) { | ||
286 | hw->type = BSDJOY_JOY; | ||
287 | joy->naxes = 2; | ||
288 | joy->nbuttons = 2; | ||
289 | joy->nhats = 0; | ||
290 | joy->nballs = 0; | ||
291 | joydevnames[joy->index] = strdup("Gameport joystick"); | ||
292 | goto usbend; | ||
293 | } else { | ||
294 | hw->type = BSDJOY_UHID; | ||
295 | } | ||
296 | |||
297 | { | ||
298 | int ax; | ||
299 | for (ax = 0; ax < JOYAXE_count; ax++) | ||
300 | hw->axis_map[ax] = -1; | ||
301 | } | ||
302 | hw->repdesc = hid_get_report_desc(fd); | ||
303 | if (hw->repdesc == NULL) { | ||
304 | SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path, | ||
305 | strerror(errno)); | ||
306 | goto usberr; | ||
307 | } | ||
308 | rep = &hw->inreport; | ||
309 | #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) | ||
310 | rep->rid = hid_get_report_id(fd); | ||
311 | if (rep->rid < 0) { | ||
312 | #else | ||
313 | if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) { | ||
314 | #endif | ||
315 | rep->rid = -1; /* XXX */ | ||
316 | } | ||
317 | if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) { | ||
318 | goto usberr; | ||
319 | } | ||
320 | if (rep->size <= 0) { | ||
321 | SDL_SetError("%s: Input report descriptor has invalid length", | ||
322 | hw->path); | ||
323 | goto usberr; | ||
324 | } | ||
325 | |||
326 | #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) | ||
327 | hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid); | ||
328 | #else | ||
329 | hdata = hid_start_parse(hw->repdesc, 1 << hid_input); | ||
330 | #endif | ||
331 | if (hdata == NULL) { | ||
332 | SDL_SetError("%s: Cannot start HID parser", hw->path); | ||
333 | goto usberr; | ||
334 | } | ||
335 | joy->naxes = 0; | ||
336 | joy->nbuttons = 0; | ||
337 | joy->nhats = 0; | ||
338 | joy->nballs = 0; | ||
339 | for (i=0; i<JOYAXE_count; i++) | ||
340 | hw->axis_map[i] = -1; | ||
341 | |||
342 | while (hid_get_item(hdata, &hitem) > 0) { | ||
343 | char *sp; | ||
344 | const char *s; | ||
345 | |||
346 | switch (hitem.kind) { | ||
347 | case hid_collection: | ||
348 | switch (HID_PAGE(hitem.usage)) { | ||
349 | case HUP_GENERIC_DESKTOP: | ||
350 | switch (HID_USAGE(hitem.usage)) { | ||
351 | case HUG_JOYSTICK: | ||
352 | case HUG_GAME_PAD: | ||
353 | s = hid_usage_in_page(hitem.usage); | ||
354 | sp = SDL_malloc(SDL_strlen(s) + 5); | ||
355 | SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)", s, | ||
356 | joy->index); | ||
357 | joydevnames[joy->index] = sp; | ||
358 | } | ||
359 | } | ||
360 | break; | ||
361 | case hid_input: | ||
362 | switch (HID_PAGE(hitem.usage)) { | ||
363 | case HUP_GENERIC_DESKTOP: { | ||
364 | unsigned usage = HID_USAGE(hitem.usage); | ||
365 | int joyaxe = usage_to_joyaxe(usage); | ||
366 | if (joyaxe >= 0) { | ||
367 | hw->axis_map[joyaxe] = 1; | ||
368 | } else if (usage == HUG_HAT_SWITCH) { | ||
369 | joy->nhats++; | ||
370 | } | ||
371 | break; | ||
372 | } | ||
373 | case HUP_BUTTON: | ||
374 | joy->nbuttons++; | ||
375 | break; | ||
376 | default: | ||
377 | break; | ||
378 | } | ||
379 | break; | ||
380 | default: | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | hid_end_parse(hdata); | ||
385 | for (i=0; i<JOYAXE_count; i++) | ||
386 | if (hw->axis_map[i] > 0) | ||
387 | hw->axis_map[i] = joy->naxes++; | ||
388 | |||
389 | usbend: | ||
390 | /* The poll blocks the event thread. */ | ||
391 | fcntl(fd, F_SETFL, O_NONBLOCK); | ||
392 | |||
393 | return (0); | ||
394 | usberr: | ||
395 | close(hw->fd); | ||
396 | SDL_free(hw->path); | ||
397 | SDL_free(hw); | ||
398 | return (-1); | ||
399 | } | ||
400 | |||
401 | void | ||
402 | SDL_SYS_JoystickUpdate(SDL_Joystick *joy) | ||
403 | { | ||
404 | struct hid_item hitem; | ||
405 | struct hid_data *hdata; | ||
406 | struct report *rep; | ||
407 | int nbutton, naxe = -1; | ||
408 | Sint32 v; | ||
409 | |||
410 | #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) | ||
411 | struct joystick gameport; | ||
412 | |||
413 | if (joy->hwdata->type == BSDJOY_JOY) { | ||
414 | if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport) | ||
415 | return; | ||
416 | if (abs(joy->hwdata->x - gameport.x) > 8) { | ||
417 | joy->hwdata->x = gameport.x; | ||
418 | if (joy->hwdata->x < joy->hwdata->xmin) { | ||
419 | joy->hwdata->xmin = joy->hwdata->x; | ||
420 | } | ||
421 | if (joy->hwdata->x > joy->hwdata->xmax) { | ||
422 | joy->hwdata->xmax = joy->hwdata->x; | ||
423 | } | ||
424 | if (joy->hwdata->xmin == joy->hwdata->xmax) { | ||
425 | joy->hwdata->xmin--; | ||
426 | joy->hwdata->xmax++; | ||
427 | } | ||
428 | v = (Sint32)joy->hwdata->x; | ||
429 | v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2; | ||
430 | v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2); | ||
431 | SDL_PrivateJoystickAxis(joy, 0, v); | ||
432 | } | ||
433 | if (abs(joy->hwdata->y - gameport.y) > 8) { | ||
434 | joy->hwdata->y = gameport.y; | ||
435 | if (joy->hwdata->y < joy->hwdata->ymin) { | ||
436 | joy->hwdata->ymin = joy->hwdata->y; | ||
437 | } | ||
438 | if (joy->hwdata->y > joy->hwdata->ymax) { | ||
439 | joy->hwdata->ymax = joy->hwdata->y; | ||
440 | } | ||
441 | if (joy->hwdata->ymin == joy->hwdata->ymax) { | ||
442 | joy->hwdata->ymin--; | ||
443 | joy->hwdata->ymax++; | ||
444 | } | ||
445 | v = (Sint32)joy->hwdata->y; | ||
446 | v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2; | ||
447 | v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2); | ||
448 | SDL_PrivateJoystickAxis(joy, 1, v); | ||
449 | } | ||
450 | if (gameport.b1 != joy->buttons[0]) { | ||
451 | SDL_PrivateJoystickButton(joy, 0, gameport.b1); | ||
452 | } | ||
453 | if (gameport.b2 != joy->buttons[1]) { | ||
454 | SDL_PrivateJoystickButton(joy, 1, gameport.b2); | ||
455 | } | ||
456 | return; | ||
457 | } | ||
458 | #endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */ | ||
459 | |||
460 | rep = &joy->hwdata->inreport; | ||
461 | |||
462 | if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) { | ||
463 | return; | ||
464 | } | ||
465 | #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) | ||
466 | hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); | ||
467 | #else | ||
468 | hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); | ||
469 | #endif | ||
470 | if (hdata == NULL) { | ||
471 | fprintf(stderr, "%s: Cannot start HID parser\n", | ||
472 | joy->hwdata->path); | ||
473 | return; | ||
474 | } | ||
475 | |||
476 | for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { | ||
477 | switch (hitem.kind) { | ||
478 | case hid_input: | ||
479 | switch (HID_PAGE(hitem.usage)) { | ||
480 | case HUP_GENERIC_DESKTOP: { | ||
481 | unsigned usage = HID_USAGE(hitem.usage); | ||
482 | int joyaxe = usage_to_joyaxe(usage); | ||
483 | if (joyaxe >= 0) { | ||
484 | naxe = joy->hwdata->axis_map[joyaxe]; | ||
485 | /* scaleaxe */ | ||
486 | v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | ||
487 | &hitem); | ||
488 | v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; | ||
489 | v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); | ||
490 | if (v != joy->axes[naxe]) { | ||
491 | SDL_PrivateJoystickAxis(joy, naxe, v); | ||
492 | } | ||
493 | } else if (usage == HUG_HAT_SWITCH) { | ||
494 | v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | ||
495 | &hitem); | ||
496 | SDL_PrivateJoystickHat(joy, 0, | ||
497 | hatval_to_sdl(v)-hitem.logical_minimum); | ||
498 | } | ||
499 | break; | ||
500 | } | ||
501 | case HUP_BUTTON: | ||
502 | v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | ||
503 | &hitem); | ||
504 | if (joy->buttons[nbutton] != v) { | ||
505 | SDL_PrivateJoystickButton(joy, | ||
506 | nbutton, v); | ||
507 | } | ||
508 | nbutton++; | ||
509 | break; | ||
510 | default: | ||
511 | continue; | ||
512 | } | ||
513 | break; | ||
514 | default: | ||
515 | break; | ||
516 | } | ||
517 | } | ||
518 | hid_end_parse(hdata); | ||
519 | |||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* Function to close a joystick after use */ | ||
524 | void | ||
525 | SDL_SYS_JoystickClose(SDL_Joystick *joy) | ||
526 | { | ||
527 | if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) { | ||
528 | report_free(&joy->hwdata->inreport); | ||
529 | hid_dispose_report_desc(joy->hwdata->repdesc); | ||
530 | } | ||
531 | close(joy->hwdata->fd); | ||
532 | SDL_free(joy->hwdata->path); | ||
533 | SDL_free(joy->hwdata); | ||
534 | |||
535 | return; | ||
536 | } | ||
537 | |||
538 | void | ||
539 | SDL_SYS_JoystickQuit(void) | ||
540 | { | ||
541 | int i; | ||
542 | |||
543 | for (i = 0; i < MAX_JOYS; i++) { | ||
544 | if (joynames[i] != NULL) | ||
545 | SDL_free(joynames[i]); | ||
546 | if (joydevnames[i] != NULL) | ||
547 | SDL_free(joydevnames[i]); | ||
548 | } | ||
549 | |||
550 | return; | ||
551 | } | ||
552 | |||
553 | static int | ||
554 | report_alloc(struct report *r, struct report_desc *rd, int repind) | ||
555 | { | ||
556 | int len; | ||
557 | |||
558 | #ifdef __DragonFly__ | ||
559 | len = hid_report_size(rd, r->rid, repinfo[repind].kind); | ||
560 | #elif __FREEBSD__ | ||
561 | # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) | ||
562 | # if (__FreeBSD_kernel_version <= 500111) | ||
563 | len = hid_report_size(rd, r->rid, repinfo[repind].kind); | ||
564 | # else | ||
565 | len = hid_report_size(rd, repinfo[repind].kind, r->rid); | ||
566 | # endif | ||
567 | # else | ||
568 | len = hid_report_size(rd, repinfo[repind].kind, &r->rid); | ||
569 | # endif | ||
570 | #else | ||
571 | # ifdef USBHID_NEW | ||
572 | len = hid_report_size(rd, repinfo[repind].kind, r->rid); | ||
573 | # else | ||
574 | len = hid_report_size(rd, repinfo[repind].kind, &r->rid); | ||
575 | # endif | ||
576 | #endif | ||
577 | |||
578 | if (len < 0) { | ||
579 | SDL_SetError("Negative HID report size"); | ||
580 | return (-1); | ||
581 | } | ||
582 | r->size = len; | ||
583 | |||
584 | if (r->size > 0) { | ||
585 | r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + | ||
586 | r->size); | ||
587 | if (r->buf == NULL) { | ||
588 | SDL_OutOfMemory(); | ||
589 | return (-1); | ||
590 | } | ||
591 | } else { | ||
592 | r->buf = NULL; | ||
593 | } | ||
594 | |||
595 | r->status = SREPORT_CLEAN; | ||
596 | return (0); | ||
597 | } | ||
598 | |||
599 | static void | ||
600 | report_free(struct report *r) | ||
601 | { | ||
602 | if (r->buf != NULL) { | ||
603 | SDL_free(r->buf); | ||
604 | } | ||
605 | r->status = SREPORT_UNINIT; | ||
606 | } | ||
607 | |||
608 | #endif /* SDL_JOYSTICK_USBHID */ | ||
diff --git a/apps/plugins/sdl/src/joystick/darwin/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/darwin/SDL_sysjoystick.c new file mode 100644 index 0000000000..a9ccb35fad --- /dev/null +++ b/apps/plugins/sdl/src/joystick/darwin/SDL_sysjoystick.c | |||
@@ -0,0 +1,842 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #ifdef SDL_JOYSTICK_IOKIT | ||
25 | |||
26 | /* SDL joystick driver for Darwin / Mac OS X, based on the IOKit HID API */ | ||
27 | /* Written 2001 by Max Horn */ | ||
28 | |||
29 | #include <unistd.h> | ||
30 | #include <ctype.h> | ||
31 | #include <sysexits.h> | ||
32 | #include <mach/mach.h> | ||
33 | #include <mach/mach_error.h> | ||
34 | #include <IOKit/IOKitLib.h> | ||
35 | #include <IOKit/IOCFPlugIn.h> | ||
36 | #ifdef MACOS_10_0_4 | ||
37 | #include <IOKit/hidsystem/IOHIDUsageTables.h> | ||
38 | #else | ||
39 | /* The header was moved here in Mac OS X 10.1 */ | ||
40 | #include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> | ||
41 | #endif | ||
42 | #include <IOKit/hid/IOHIDLib.h> | ||
43 | #include <IOKit/hid/IOHIDKeys.h> | ||
44 | #include <CoreFoundation/CoreFoundation.h> | ||
45 | #include <Carbon/Carbon.h> /* for NewPtrClear, DisposePtr */ | ||
46 | |||
47 | #include "SDL_joystick.h" | ||
48 | #include "../SDL_sysjoystick.h" | ||
49 | #include "../SDL_joystick_c.h" | ||
50 | |||
51 | struct recElement | ||
52 | { | ||
53 | IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */ | ||
54 | long min; /* reported min value possible */ | ||
55 | long max; /* reported max value possible */ | ||
56 | #if 0 | ||
57 | /* TODO: maybe should handle the following stuff somehow? */ | ||
58 | |||
59 | long scaledMin; /* reported scaled min value possible */ | ||
60 | long scaledMax; /* reported scaled max value possible */ | ||
61 | long size; /* size in bits of data return from element */ | ||
62 | Boolean relative; /* are reports relative to last report (deltas) */ | ||
63 | Boolean wrapping; /* does element wrap around (one value higher than max is min) */ | ||
64 | Boolean nonLinear; /* are the values reported non-linear relative to element movement */ | ||
65 | Boolean preferredState; /* does element have a preferred state (such as a button) */ | ||
66 | Boolean nullState; /* does element have null state */ | ||
67 | #endif /* 0 */ | ||
68 | |||
69 | /* runtime variables used for auto-calibration */ | ||
70 | long minReport; /* min returned value */ | ||
71 | long maxReport; /* max returned value */ | ||
72 | |||
73 | struct recElement * pNext; /* next element in list */ | ||
74 | }; | ||
75 | typedef struct recElement recElement; | ||
76 | |||
77 | struct joystick_hwdata | ||
78 | { | ||
79 | IOHIDDeviceInterface ** interface; /* interface to device, NULL = no interface */ | ||
80 | |||
81 | char product[256]; /* name of product */ | ||
82 | long usage; /* usage page from IOUSBHID Parser.h which defines general usage */ | ||
83 | long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ | ||
84 | |||
85 | long axes; /* number of axis (calculated, not reported by device) */ | ||
86 | long buttons; /* number of buttons (calculated, not reported by device) */ | ||
87 | long hats; /* number of hat switches (calculated, not reported by device) */ | ||
88 | long elements; /* number of total elements (shouldbe total of above) (calculated, not reported by device) */ | ||
89 | |||
90 | recElement* firstAxis; | ||
91 | recElement* firstButton; | ||
92 | recElement* firstHat; | ||
93 | |||
94 | int removed; | ||
95 | int uncentered; | ||
96 | |||
97 | struct joystick_hwdata* pNext; /* next device */ | ||
98 | }; | ||
99 | typedef struct joystick_hwdata recDevice; | ||
100 | |||
101 | |||
102 | /* Linked list of all available devices */ | ||
103 | static recDevice *gpDeviceList = NULL; | ||
104 | |||
105 | |||
106 | static void HIDReportErrorNum (char * strError, long numError) | ||
107 | { | ||
108 | SDL_SetError(strError); | ||
109 | } | ||
110 | |||
111 | static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice); | ||
112 | |||
113 | /* returns current value for element, polling element | ||
114 | * will return 0 on error conditions which should be accounted for by application | ||
115 | */ | ||
116 | |||
117 | static SInt32 HIDGetElementValue (recDevice *pDevice, recElement *pElement) | ||
118 | { | ||
119 | IOReturn result = kIOReturnSuccess; | ||
120 | IOHIDEventStruct hidEvent; | ||
121 | hidEvent.value = 0; | ||
122 | |||
123 | if (NULL != pDevice && NULL != pElement && NULL != pDevice->interface) | ||
124 | { | ||
125 | result = (*(pDevice->interface))->getElementValue(pDevice->interface, pElement->cookie, &hidEvent); | ||
126 | if (kIOReturnSuccess == result) | ||
127 | { | ||
128 | /* record min and max for auto calibration */ | ||
129 | if (hidEvent.value < pElement->minReport) | ||
130 | pElement->minReport = hidEvent.value; | ||
131 | if (hidEvent.value > pElement->maxReport) | ||
132 | pElement->maxReport = hidEvent.value; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* auto user scale */ | ||
137 | return hidEvent.value; | ||
138 | } | ||
139 | |||
140 | static SInt32 HIDScaledCalibratedValue (recDevice *pDevice, recElement *pElement, long min, long max) | ||
141 | { | ||
142 | float deviceScale = max - min; | ||
143 | float readScale = pElement->maxReport - pElement->minReport; | ||
144 | SInt32 value = HIDGetElementValue(pDevice, pElement); | ||
145 | if (readScale == 0) | ||
146 | return value; /* no scaling at all */ | ||
147 | else | ||
148 | return ((value - pElement->minReport) * deviceScale / readScale) + min; | ||
149 | } | ||
150 | |||
151 | |||
152 | static void HIDRemovalCallback(void * target, | ||
153 | IOReturn result, | ||
154 | void * refcon, | ||
155 | void * sender) | ||
156 | { | ||
157 | recDevice *device = (recDevice *) refcon; | ||
158 | device->removed = 1; | ||
159 | device->uncentered = 1; | ||
160 | } | ||
161 | |||
162 | |||
163 | |||
164 | /* Create and open an interface to device, required prior to extracting values or building queues. | ||
165 | * Note: appliction now owns the device and must close and release it prior to exiting | ||
166 | */ | ||
167 | |||
168 | static IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, recDevice *pDevice) | ||
169 | { | ||
170 | IOReturn result = kIOReturnSuccess; | ||
171 | HRESULT plugInResult = S_OK; | ||
172 | SInt32 score = 0; | ||
173 | IOCFPlugInInterface ** ppPlugInInterface = NULL; | ||
174 | |||
175 | if (NULL == pDevice->interface) | ||
176 | { | ||
177 | result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, | ||
178 | kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); | ||
179 | if (kIOReturnSuccess == result) | ||
180 | { | ||
181 | /* Call a method of the intermediate plug-in to create the device interface */ | ||
182 | plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, | ||
183 | CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); | ||
184 | if (S_OK != plugInResult) | ||
185 | HIDReportErrorNum ("CouldnÕt query HID class device interface from plugInInterface", plugInResult); | ||
186 | (*ppPlugInInterface)->Release (ppPlugInInterface); | ||
187 | } | ||
188 | else | ||
189 | HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); | ||
190 | } | ||
191 | if (NULL != pDevice->interface) | ||
192 | { | ||
193 | result = (*(pDevice->interface))->open (pDevice->interface, 0); | ||
194 | if (kIOReturnSuccess != result) | ||
195 | HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); | ||
196 | else | ||
197 | (*(pDevice->interface))->setRemovalCallback (pDevice->interface, HIDRemovalCallback, pDevice, pDevice); | ||
198 | |||
199 | } | ||
200 | return result; | ||
201 | } | ||
202 | |||
203 | /* Closes and releases interface to device, should be done prior to exting application | ||
204 | * Note: will have no affect if device or interface do not exist | ||
205 | * application will "own" the device if interface is not closed | ||
206 | * (device may have to be plug and re-plugged in different location to get it working again without a restart) | ||
207 | */ | ||
208 | |||
209 | static IOReturn HIDCloseReleaseInterface (recDevice *pDevice) | ||
210 | { | ||
211 | IOReturn result = kIOReturnSuccess; | ||
212 | |||
213 | if ((NULL != pDevice) && (NULL != pDevice->interface)) | ||
214 | { | ||
215 | /* close the interface */ | ||
216 | result = (*(pDevice->interface))->close (pDevice->interface); | ||
217 | if (kIOReturnNotOpen == result) | ||
218 | { | ||
219 | /* do nothing as device was not opened, thus can't be closed */ | ||
220 | } | ||
221 | else if (kIOReturnSuccess != result) | ||
222 | HIDReportErrorNum ("Failed to close IOHIDDeviceInterface.", result); | ||
223 | /* release the interface */ | ||
224 | result = (*(pDevice->interface))->Release (pDevice->interface); | ||
225 | if (kIOReturnSuccess != result) | ||
226 | HIDReportErrorNum ("Failed to release IOHIDDeviceInterface.", result); | ||
227 | pDevice->interface = NULL; | ||
228 | } | ||
229 | return result; | ||
230 | } | ||
231 | |||
232 | /* extracts actual specific element information from each element CF dictionary entry */ | ||
233 | |||
234 | static void HIDGetElementInfo (CFTypeRef refElement, recElement *pElement) | ||
235 | { | ||
236 | long number; | ||
237 | CFTypeRef refType; | ||
238 | |||
239 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); | ||
240 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
241 | pElement->cookie = (IOHIDElementCookie) number; | ||
242 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); | ||
243 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
244 | pElement->minReport = pElement->min = number; | ||
245 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); | ||
246 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
247 | pElement->maxReport = pElement->max = number; | ||
248 | /* | ||
249 | TODO: maybe should handle the following stuff somehow? | ||
250 | |||
251 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); | ||
252 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
253 | pElement->scaledMin = number; | ||
254 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); | ||
255 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
256 | pElement->scaledMax = number; | ||
257 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); | ||
258 | if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) | ||
259 | pElement->size = number; | ||
260 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); | ||
261 | if (refType) | ||
262 | pElement->relative = CFBooleanGetValue (refType); | ||
263 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); | ||
264 | if (refType) | ||
265 | pElement->wrapping = CFBooleanGetValue (refType); | ||
266 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); | ||
267 | if (refType) | ||
268 | pElement->nonLinear = CFBooleanGetValue (refType); | ||
269 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); | ||
270 | if (refType) | ||
271 | pElement->preferredState = CFBooleanGetValue (refType); | ||
272 | refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); | ||
273 | if (refType) | ||
274 | pElement->nullState = CFBooleanGetValue (refType); | ||
275 | */ | ||
276 | } | ||
277 | |||
278 | /* examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements | ||
279 | * if element of interest allocate storage, add to list and retrieve element specific info | ||
280 | * if collection then pass on to deconstruction collection into additional individual elements | ||
281 | */ | ||
282 | |||
283 | static void HIDAddElement (CFTypeRef refElement, recDevice* pDevice) | ||
284 | { | ||
285 | recElement* element = NULL; | ||
286 | recElement** headElement = NULL; | ||
287 | long elementType, usagePage, usage; | ||
288 | CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); | ||
289 | CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); | ||
290 | CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); | ||
291 | |||
292 | |||
293 | if ((refElementType) && (CFNumberGetValue (refElementType, kCFNumberLongType, &elementType))) | ||
294 | { | ||
295 | /* look at types of interest */ | ||
296 | if ((elementType == kIOHIDElementTypeInput_Misc) || (elementType == kIOHIDElementTypeInput_Button) || | ||
297 | (elementType == kIOHIDElementTypeInput_Axis)) | ||
298 | { | ||
299 | if (refUsagePage && CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage) && | ||
300 | refUsage && CFNumberGetValue (refUsage, kCFNumberLongType, &usage)) | ||
301 | { | ||
302 | switch (usagePage) /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ | ||
303 | { | ||
304 | case kHIDPage_GenericDesktop: | ||
305 | { | ||
306 | switch (usage) /* look at usage to determine function */ | ||
307 | { | ||
308 | case kHIDUsage_GD_X: | ||
309 | case kHIDUsage_GD_Y: | ||
310 | case kHIDUsage_GD_Z: | ||
311 | case kHIDUsage_GD_Rx: | ||
312 | case kHIDUsage_GD_Ry: | ||
313 | case kHIDUsage_GD_Rz: | ||
314 | case kHIDUsage_GD_Slider: | ||
315 | case kHIDUsage_GD_Dial: | ||
316 | case kHIDUsage_GD_Wheel: | ||
317 | element = (recElement *) NewPtrClear (sizeof (recElement)); | ||
318 | if (element) | ||
319 | { | ||
320 | pDevice->axes++; | ||
321 | headElement = &(pDevice->firstAxis); | ||
322 | } | ||
323 | break; | ||
324 | case kHIDUsage_GD_Hatswitch: | ||
325 | element = (recElement *) NewPtrClear (sizeof (recElement)); | ||
326 | if (element) | ||
327 | { | ||
328 | pDevice->hats++; | ||
329 | headElement = &(pDevice->firstHat); | ||
330 | } | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | break; | ||
335 | case kHIDPage_Button: | ||
336 | element = (recElement *) NewPtrClear (sizeof (recElement)); | ||
337 | if (element) | ||
338 | { | ||
339 | pDevice->buttons++; | ||
340 | headElement = &(pDevice->firstButton); | ||
341 | } | ||
342 | break; | ||
343 | default: | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | else if (kIOHIDElementTypeCollection == elementType) | ||
349 | HIDGetCollectionElements ((CFMutableDictionaryRef) refElement, pDevice); | ||
350 | } | ||
351 | |||
352 | if (element && headElement) /* add to list */ | ||
353 | { | ||
354 | pDevice->elements++; | ||
355 | if (NULL == *headElement) | ||
356 | *headElement = element; | ||
357 | else | ||
358 | { | ||
359 | recElement *elementPrevious, *elementCurrent; | ||
360 | elementCurrent = *headElement; | ||
361 | while (elementCurrent) | ||
362 | { | ||
363 | elementPrevious = elementCurrent; | ||
364 | elementCurrent = elementPrevious->pNext; | ||
365 | } | ||
366 | elementPrevious->pNext = element; | ||
367 | } | ||
368 | element->pNext = NULL; | ||
369 | HIDGetElementInfo (refElement, element); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* collects information from each array member in device element list (each array memeber = element) */ | ||
374 | |||
375 | static void HIDGetElementsCFArrayHandler (const void * value, void * parameter) | ||
376 | { | ||
377 | if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) | ||
378 | HIDAddElement ((CFTypeRef) value, (recDevice *) parameter); | ||
379 | } | ||
380 | |||
381 | /* handles retrieval of element information from arrays of elements in device IO registry information */ | ||
382 | |||
383 | static void HIDGetElements (CFTypeRef refElementCurrent, recDevice *pDevice) | ||
384 | { | ||
385 | CFTypeID type = CFGetTypeID (refElementCurrent); | ||
386 | if (type == CFArrayGetTypeID()) /* if element is an array */ | ||
387 | { | ||
388 | CFRange range = {0, CFArrayGetCount (refElementCurrent)}; | ||
389 | /* CountElementsCFArrayHandler called for each array member */ | ||
390 | CFArrayApplyFunction (refElementCurrent, range, HIDGetElementsCFArrayHandler, pDevice); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /* handles extracting element information from element collection CF types | ||
395 | * used from top level element decoding and hierarchy deconstruction to flatten device element list | ||
396 | */ | ||
397 | |||
398 | static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice) | ||
399 | { | ||
400 | CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); | ||
401 | if (refElementTop) | ||
402 | HIDGetElements (refElementTop, pDevice); | ||
403 | } | ||
404 | |||
405 | /* use top level element usage page and usage to discern device usage page and usage setting appropriate vlaues in device record */ | ||
406 | |||
407 | static void HIDTopLevelElementHandler (const void * value, void * parameter) | ||
408 | { | ||
409 | CFTypeRef refCF = 0; | ||
410 | if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) | ||
411 | return; | ||
412 | refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); | ||
413 | if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usagePage)) | ||
414 | SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); | ||
415 | refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); | ||
416 | if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usage)) | ||
417 | SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); | ||
418 | } | ||
419 | |||
420 | /* extracts device info from CF dictionary records in IO registry */ | ||
421 | |||
422 | static void HIDGetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, recDevice *pDevice) | ||
423 | { | ||
424 | CFMutableDictionaryRef usbProperties = 0; | ||
425 | io_registry_entry_t parent1, parent2; | ||
426 | |||
427 | /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also | ||
428 | * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties | ||
429 | */ | ||
430 | if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && | ||
431 | (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && | ||
432 | (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) | ||
433 | { | ||
434 | if (usbProperties) | ||
435 | { | ||
436 | CFTypeRef refCF = 0; | ||
437 | /* get device info | ||
438 | * try hid dictionary first, if fail then go to usb dictionary | ||
439 | */ | ||
440 | |||
441 | |||
442 | /* get product name */ | ||
443 | refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); | ||
444 | if (!refCF) | ||
445 | refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); | ||
446 | if (refCF) | ||
447 | { | ||
448 | if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) | ||
449 | SDL_SetError ("CFStringGetCString error retrieving pDevice->product."); | ||
450 | } | ||
451 | |||
452 | /* get usage page and usage */ | ||
453 | refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); | ||
454 | if (refCF) | ||
455 | { | ||
456 | if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) | ||
457 | SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); | ||
458 | refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); | ||
459 | if (refCF) | ||
460 | if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) | ||
461 | SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); | ||
462 | } | ||
463 | |||
464 | if (NULL == refCF) /* get top level element HID usage page or usage */ | ||
465 | { | ||
466 | /* use top level element instead */ | ||
467 | CFTypeRef refCFTopElement = 0; | ||
468 | refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); | ||
469 | { | ||
470 | /* refCFTopElement points to an array of element dictionaries */ | ||
471 | CFRange range = {0, CFArrayGetCount (refCFTopElement)}; | ||
472 | CFArrayApplyFunction (refCFTopElement, range, HIDTopLevelElementHandler, pDevice); | ||
473 | } | ||
474 | } | ||
475 | |||
476 | CFRelease (usbProperties); | ||
477 | } | ||
478 | else | ||
479 | SDL_SetError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); | ||
480 | |||
481 | if (kIOReturnSuccess != IOObjectRelease (parent2)) | ||
482 | SDL_SetError ("IOObjectRelease error with parent2."); | ||
483 | if (kIOReturnSuccess != IOObjectRelease (parent1)) | ||
484 | SDL_SetError ("IOObjectRelease error with parent1."); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | |||
489 | static recDevice *HIDBuildDevice (io_object_t hidDevice) | ||
490 | { | ||
491 | recDevice *pDevice = (recDevice *) NewPtrClear (sizeof (recDevice)); | ||
492 | if (pDevice) | ||
493 | { | ||
494 | /* get dictionary for HID properties */ | ||
495 | CFMutableDictionaryRef hidProperties = 0; | ||
496 | kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); | ||
497 | if ((result == KERN_SUCCESS) && hidProperties) | ||
498 | { | ||
499 | /* create device interface */ | ||
500 | result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); | ||
501 | if (kIOReturnSuccess == result) | ||
502 | { | ||
503 | HIDGetDeviceInfo (hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */ | ||
504 | HIDGetCollectionElements (hidProperties, pDevice); | ||
505 | } | ||
506 | else | ||
507 | { | ||
508 | DisposePtr((Ptr)pDevice); | ||
509 | pDevice = NULL; | ||
510 | } | ||
511 | CFRelease (hidProperties); | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | DisposePtr((Ptr)pDevice); | ||
516 | pDevice = NULL; | ||
517 | } | ||
518 | } | ||
519 | return pDevice; | ||
520 | } | ||
521 | |||
522 | /* disposes of the element list associated with a device and the memory associated with the list | ||
523 | */ | ||
524 | |||
525 | static void HIDDisposeElementList (recElement **elementList) | ||
526 | { | ||
527 | recElement *pElement = *elementList; | ||
528 | while (pElement) | ||
529 | { | ||
530 | recElement *pElementNext = pElement->pNext; | ||
531 | DisposePtr ((Ptr) pElement); | ||
532 | pElement = pElementNext; | ||
533 | } | ||
534 | *elementList = NULL; | ||
535 | } | ||
536 | |||
537 | /* disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL | ||
538 | * all your device no longer belong to us... (i.e., you do not 'own' the device anymore) | ||
539 | */ | ||
540 | |||
541 | static recDevice *HIDDisposeDevice (recDevice **ppDevice) | ||
542 | { | ||
543 | kern_return_t result = KERN_SUCCESS; | ||
544 | recDevice *pDeviceNext = NULL; | ||
545 | if (*ppDevice) | ||
546 | { | ||
547 | /* save next device prior to disposing of this device */ | ||
548 | pDeviceNext = (*ppDevice)->pNext; | ||
549 | |||
550 | /* free element lists */ | ||
551 | HIDDisposeElementList (&(*ppDevice)->firstAxis); | ||
552 | HIDDisposeElementList (&(*ppDevice)->firstButton); | ||
553 | HIDDisposeElementList (&(*ppDevice)->firstHat); | ||
554 | |||
555 | result = HIDCloseReleaseInterface (*ppDevice); /* function sanity checks interface value (now application does not own device) */ | ||
556 | if (kIOReturnSuccess != result) | ||
557 | HIDReportErrorNum ("HIDCloseReleaseInterface failed when trying to dipose device.", result); | ||
558 | DisposePtr ((Ptr)*ppDevice); | ||
559 | *ppDevice = NULL; | ||
560 | } | ||
561 | return pDeviceNext; | ||
562 | } | ||
563 | |||
564 | |||
565 | /* Function to scan the system for joysticks. | ||
566 | * Joystick 0 should be the system default joystick. | ||
567 | * This function should return the number of available joysticks, or -1 | ||
568 | * on an unrecoverable fatal error. | ||
569 | */ | ||
570 | int SDL_SYS_JoystickInit(void) | ||
571 | { | ||
572 | IOReturn result = kIOReturnSuccess; | ||
573 | mach_port_t masterPort = 0; | ||
574 | io_iterator_t hidObjectIterator = 0; | ||
575 | CFMutableDictionaryRef hidMatchDictionary = NULL; | ||
576 | recDevice *device, *lastDevice; | ||
577 | io_object_t ioHIDDeviceObject = 0; | ||
578 | |||
579 | SDL_numjoysticks = 0; | ||
580 | |||
581 | if (gpDeviceList) | ||
582 | { | ||
583 | SDL_SetError("Joystick: Device list already inited."); | ||
584 | return -1; | ||
585 | } | ||
586 | |||
587 | result = IOMasterPort (bootstrap_port, &masterPort); | ||
588 | if (kIOReturnSuccess != result) | ||
589 | { | ||
590 | SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); | ||
591 | return -1; | ||
592 | } | ||
593 | |||
594 | /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ | ||
595 | hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); | ||
596 | if (hidMatchDictionary) | ||
597 | { | ||
598 | /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ | ||
599 | |||
600 | /* NOTE: we now perform this filtering later | ||
601 | UInt32 usagePage = kHIDPage_GenericDesktop; | ||
602 | UInt32 usage = kHIDUsage_GD_Joystick; | ||
603 | CFNumberRef refUsage = NULL, refUsagePage = NULL; | ||
604 | |||
605 | refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); | ||
606 | CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); | ||
607 | refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); | ||
608 | CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); | ||
609 | */ | ||
610 | } | ||
611 | else | ||
612 | { | ||
613 | SDL_SetError("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); | ||
614 | return -1; | ||
615 | } | ||
616 | |||
617 | /*/ Now search I/O Registry for matching devices. */ | ||
618 | result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); | ||
619 | /* Check for errors */ | ||
620 | if (kIOReturnSuccess != result) | ||
621 | { | ||
622 | SDL_SetError("Joystick: Couldn't create a HID object iterator."); | ||
623 | return -1; | ||
624 | } | ||
625 | if (!hidObjectIterator) /* there are no joysticks */ | ||
626 | { | ||
627 | gpDeviceList = NULL; | ||
628 | SDL_numjoysticks = 0; | ||
629 | return 0; | ||
630 | } | ||
631 | /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ | ||
632 | |||
633 | /* build flat linked list of devices from device iterator */ | ||
634 | |||
635 | gpDeviceList = lastDevice = NULL; | ||
636 | |||
637 | while ((ioHIDDeviceObject = IOIteratorNext (hidObjectIterator))) | ||
638 | { | ||
639 | /* build a device record */ | ||
640 | device = HIDBuildDevice (ioHIDDeviceObject); | ||
641 | if (!device) | ||
642 | continue; | ||
643 | |||
644 | /* dump device object, it is no longer needed */ | ||
645 | result = IOObjectRelease (ioHIDDeviceObject); | ||
646 | /* if (KERN_SUCCESS != result) | ||
647 | HIDReportErrorNum ("IOObjectRelease error with ioHIDDeviceObject.", result); | ||
648 | */ | ||
649 | |||
650 | /* Filter device list to non-keyboard/mouse stuff */ | ||
651 | if ( (device->usagePage != kHIDPage_GenericDesktop) || | ||
652 | ((device->usage != kHIDUsage_GD_Joystick && | ||
653 | device->usage != kHIDUsage_GD_GamePad && | ||
654 | device->usage != kHIDUsage_GD_MultiAxisController)) ) { | ||
655 | |||
656 | /* release memory for the device */ | ||
657 | HIDDisposeDevice (&device); | ||
658 | DisposePtr((Ptr)device); | ||
659 | continue; | ||
660 | } | ||
661 | |||
662 | /* Add device to the end of the list */ | ||
663 | if (lastDevice) | ||
664 | lastDevice->pNext = device; | ||
665 | else | ||
666 | gpDeviceList = device; | ||
667 | lastDevice = device; | ||
668 | } | ||
669 | result = IOObjectRelease (hidObjectIterator); /* release the iterator */ | ||
670 | |||
671 | /* Count the total number of devices we found */ | ||
672 | device = gpDeviceList; | ||
673 | while (device) | ||
674 | { | ||
675 | SDL_numjoysticks++; | ||
676 | device = device->pNext; | ||
677 | } | ||
678 | |||
679 | return SDL_numjoysticks; | ||
680 | } | ||
681 | |||
682 | /* Function to get the device-dependent name of a joystick */ | ||
683 | const char *SDL_SYS_JoystickName(int index) | ||
684 | { | ||
685 | recDevice *device = gpDeviceList; | ||
686 | |||
687 | for (; index > 0; index--) | ||
688 | device = device->pNext; | ||
689 | |||
690 | return device->product; | ||
691 | } | ||
692 | |||
693 | /* Function to open a joystick for use. | ||
694 | * The joystick to open is specified by the index field of the joystick. | ||
695 | * This should fill the nbuttons and naxes fields of the joystick structure. | ||
696 | * It returns 0, or -1 if there is an error. | ||
697 | */ | ||
698 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
699 | { | ||
700 | recDevice *device = gpDeviceList; | ||
701 | int index; | ||
702 | |||
703 | for (index = joystick->index; index > 0; index--) | ||
704 | device = device->pNext; | ||
705 | |||
706 | joystick->hwdata = device; | ||
707 | joystick->name = device->product; | ||
708 | |||
709 | joystick->naxes = device->axes; | ||
710 | joystick->nhats = device->hats; | ||
711 | joystick->nballs = 0; | ||
712 | joystick->nbuttons = device->buttons; | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /* Function to update the state of a joystick - called as a device poll. | ||
718 | * This function shouldn't update the joystick structure directly, | ||
719 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
720 | * and update joystick device state. | ||
721 | */ | ||
722 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
723 | { | ||
724 | recDevice *device = joystick->hwdata; | ||
725 | recElement *element; | ||
726 | SInt32 value, range; | ||
727 | int i; | ||
728 | |||
729 | if (device->removed) /* device was unplugged; ignore it. */ | ||
730 | { | ||
731 | if (device->uncentered) | ||
732 | { | ||
733 | device->uncentered = 0; | ||
734 | |||
735 | /* Tell the app that everything is centered/unpressed... */ | ||
736 | for (i = 0; i < device->axes; i++) | ||
737 | SDL_PrivateJoystickAxis(joystick, i, 0); | ||
738 | |||
739 | for (i = 0; i < device->buttons; i++) | ||
740 | SDL_PrivateJoystickButton(joystick, i, 0); | ||
741 | |||
742 | for (i = 0; i < device->hats; i++) | ||
743 | SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); | ||
744 | } | ||
745 | |||
746 | return; | ||
747 | } | ||
748 | |||
749 | element = device->firstAxis; | ||
750 | i = 0; | ||
751 | while (element) | ||
752 | { | ||
753 | value = HIDScaledCalibratedValue(device, element, -32768, 32767); | ||
754 | if ( value != joystick->axes[i] ) | ||
755 | SDL_PrivateJoystickAxis(joystick, i, value); | ||
756 | element = element->pNext; | ||
757 | ++i; | ||
758 | } | ||
759 | |||
760 | element = device->firstButton; | ||
761 | i = 0; | ||
762 | while (element) | ||
763 | { | ||
764 | value = HIDGetElementValue(device, element); | ||
765 | if (value > 1) /* handle pressure-sensitive buttons */ | ||
766 | value = 1; | ||
767 | if ( value != joystick->buttons[i] ) | ||
768 | SDL_PrivateJoystickButton(joystick, i, value); | ||
769 | element = element->pNext; | ||
770 | ++i; | ||
771 | } | ||
772 | |||
773 | element = device->firstHat; | ||
774 | i = 0; | ||
775 | while (element) | ||
776 | { | ||
777 | Uint8 pos = 0; | ||
778 | |||
779 | range = (element->max - element->min + 1); | ||
780 | value = HIDGetElementValue(device, element) - element->min; | ||
781 | if (range == 4) /* 4 position hatswitch - scale up value */ | ||
782 | value *= 2; | ||
783 | else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ | ||
784 | value = -1; | ||
785 | switch(value) | ||
786 | { | ||
787 | case 0: | ||
788 | pos = SDL_HAT_UP; | ||
789 | break; | ||
790 | case 1: | ||
791 | pos = SDL_HAT_RIGHTUP; | ||
792 | break; | ||
793 | case 2: | ||
794 | pos = SDL_HAT_RIGHT; | ||
795 | break; | ||
796 | case 3: | ||
797 | pos = SDL_HAT_RIGHTDOWN; | ||
798 | break; | ||
799 | case 4: | ||
800 | pos = SDL_HAT_DOWN; | ||
801 | break; | ||
802 | case 5: | ||
803 | pos = SDL_HAT_LEFTDOWN; | ||
804 | break; | ||
805 | case 6: | ||
806 | pos = SDL_HAT_LEFT; | ||
807 | break; | ||
808 | case 7: | ||
809 | pos = SDL_HAT_LEFTUP; | ||
810 | break; | ||
811 | default: | ||
812 | /* Every other value is mapped to center. We do that because some | ||
813 | * joysticks use 8 and some 15 for this value, and apparently | ||
814 | * there are even more variants out there - so we try to be generous. | ||
815 | */ | ||
816 | pos = SDL_HAT_CENTERED; | ||
817 | break; | ||
818 | } | ||
819 | if ( pos != joystick->hats[i] ) | ||
820 | SDL_PrivateJoystickHat(joystick, i, pos); | ||
821 | element = element->pNext; | ||
822 | ++i; | ||
823 | } | ||
824 | |||
825 | return; | ||
826 | } | ||
827 | |||
828 | /* Function to close a joystick after use */ | ||
829 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
830 | { | ||
831 | /* Should we do anything here? */ | ||
832 | return; | ||
833 | } | ||
834 | |||
835 | /* Function to perform any system-specific joystick related cleanup */ | ||
836 | void SDL_SYS_JoystickQuit(void) | ||
837 | { | ||
838 | while (NULL != gpDeviceList) | ||
839 | gpDeviceList = HIDDisposeDevice (&gpDeviceList); | ||
840 | } | ||
841 | |||
842 | #endif /* SDL_JOYSTICK_IOKIT */ | ||
diff --git a/apps/plugins/sdl/src/joystick/dc/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/dc/SDL_sysjoystick.c new file mode 100644 index 0000000000..dc089e7bf0 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/dc/SDL_sysjoystick.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_DC | ||
25 | |||
26 | #include "SDL_events.h" | ||
27 | #include "SDL_joystick.h" | ||
28 | #include "../SDL_sysjoystick.h" | ||
29 | #include "../SDL_joystick_c.h" | ||
30 | |||
31 | #include <dc/maple.h> | ||
32 | #include <dc/maple/controller.h> | ||
33 | |||
34 | #define MAX_JOYSTICKS 8 /* only 2 are supported in the multimedia API */ | ||
35 | #define MAX_AXES 6 /* each joystick can have up to 6 axes */ | ||
36 | #define MAX_BUTTONS 8 /* and 8 buttons */ | ||
37 | #define MAX_HATS 2 | ||
38 | |||
39 | #define JOYNAMELEN 8 | ||
40 | |||
41 | /* array to hold joystick ID values */ | ||
42 | static uint8 SYS_Joystick_addr[MAX_JOYSTICKS]; | ||
43 | |||
44 | /* The private structure used to keep track of a joystick */ | ||
45 | struct joystick_hwdata | ||
46 | { | ||
47 | cont_cond_t prev_cond; | ||
48 | int prev_buttons; | ||
49 | }; | ||
50 | |||
51 | /* Function to scan the system for joysticks. | ||
52 | * This function should set SDL_numjoysticks to the number of available | ||
53 | * joysticks. Joystick 0 should be the system default joystick. | ||
54 | * It should return 0, or -1 on an unrecoverable fatal error. | ||
55 | */ | ||
56 | int SDL_SYS_JoystickInit(void) | ||
57 | { | ||
58 | int numdevs; | ||
59 | |||
60 | int p,u; | ||
61 | |||
62 | numdevs = 0; | ||
63 | for(p=0;p<MAPLE_PORT_COUNT;p++) { | ||
64 | for(u=0;u<MAPLE_UNIT_COUNT;u++) { | ||
65 | if (maple_device_func(p,u)&MAPLE_FUNC_CONTROLLER) { | ||
66 | SYS_Joystick_addr[numdevs] = maple_addr(p,u); | ||
67 | numdevs++; | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | return(numdevs); | ||
73 | } | ||
74 | |||
75 | /* Function to get the device-dependent name of a joystick */ | ||
76 | const char *SDL_SYS_JoystickName(int index) | ||
77 | { | ||
78 | maple_device_t *dev; | ||
79 | if (maple_compat_resolve(SYS_Joystick_addr[index],&dev,MAPLE_FUNC_CONTROLLER)!=0) return NULL; | ||
80 | return dev->info.product_name; | ||
81 | } | ||
82 | |||
83 | /* Function to open a joystick for use. | ||
84 | The joystick to open is specified by the index field of the joystick. | ||
85 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
86 | It returns 0, or -1 if there is an error. | ||
87 | */ | ||
88 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
89 | { | ||
90 | /* allocate memory for system specific hardware data */ | ||
91 | joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); | ||
92 | if (joystick->hwdata == NULL) | ||
93 | { | ||
94 | SDL_OutOfMemory(); | ||
95 | return(-1); | ||
96 | } | ||
97 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | ||
98 | |||
99 | /* fill nbuttons, naxes, and nhats fields */ | ||
100 | joystick->nbuttons = MAX_BUTTONS; | ||
101 | joystick->naxes = MAX_AXES; | ||
102 | joystick->nhats = MAX_HATS; | ||
103 | return(0); | ||
104 | } | ||
105 | |||
106 | |||
107 | /* Function to update the state of a joystick - called as a device poll. | ||
108 | * This function shouldn't update the joystick structure directly, | ||
109 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
110 | * and update joystick device state. | ||
111 | */ | ||
112 | |||
113 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
114 | { | ||
115 | const int sdl_buttons[] = { | ||
116 | CONT_C, | ||
117 | CONT_B, | ||
118 | CONT_A, | ||
119 | CONT_START, | ||
120 | CONT_Z, | ||
121 | CONT_Y, | ||
122 | CONT_X, | ||
123 | CONT_D | ||
124 | }; | ||
125 | |||
126 | uint8 addr; | ||
127 | cont_cond_t cond,*prev_cond; | ||
128 | int buttons,prev_buttons,i,changed; | ||
129 | |||
130 | addr = SYS_Joystick_addr[joystick->index]; | ||
131 | if (cont_get_cond(addr,&cond)<0) return; | ||
132 | |||
133 | buttons = cond.buttons; | ||
134 | prev_buttons = joystick->hwdata->prev_buttons; | ||
135 | changed = buttons^prev_buttons; | ||
136 | |||
137 | if ((changed)&(CONT_DPAD_UP|CONT_DPAD_DOWN|CONT_DPAD_LEFT|CONT_DPAD_RIGHT)) { | ||
138 | int hat = SDL_HAT_CENTERED; | ||
139 | if (buttons&CONT_DPAD_UP) hat|=SDL_HAT_UP; | ||
140 | if (buttons&CONT_DPAD_DOWN) hat|=SDL_HAT_DOWN; | ||
141 | if (buttons&CONT_DPAD_LEFT) hat|=SDL_HAT_LEFT; | ||
142 | if (buttons&CONT_DPAD_RIGHT) hat|=SDL_HAT_RIGHT; | ||
143 | SDL_PrivateJoystickHat(joystick, 0, hat); | ||
144 | } | ||
145 | if ((changed)&(CONT_DPAD2_UP|CONT_DPAD2_DOWN|CONT_DPAD2_LEFT|CONT_DPAD2_RIGHT)) { | ||
146 | int hat = SDL_HAT_CENTERED; | ||
147 | if (buttons&CONT_DPAD2_UP) hat|=SDL_HAT_UP; | ||
148 | if (buttons&CONT_DPAD2_DOWN) hat|=SDL_HAT_DOWN; | ||
149 | if (buttons&CONT_DPAD2_LEFT) hat|=SDL_HAT_LEFT; | ||
150 | if (buttons&CONT_DPAD2_RIGHT) hat|=SDL_HAT_RIGHT; | ||
151 | SDL_PrivateJoystickHat(joystick, 1, hat); | ||
152 | } | ||
153 | |||
154 | for(i=0;i<sizeof(sdl_buttons)/sizeof(sdl_buttons[0]);i++) { | ||
155 | if (changed & sdl_buttons[i]) { | ||
156 | SDL_PrivateJoystickButton(joystick, i, (buttons & sdl_buttons[i])?SDL_PRESSED:SDL_RELEASED); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | prev_cond = &joystick->hwdata->prev_cond; | ||
161 | if (cond.joyx!=prev_cond->joyx) | ||
162 | SDL_PrivateJoystickAxis(joystick, 0, cond.joyx-128); | ||
163 | if (cond.joyy!=prev_cond->joyy) | ||
164 | SDL_PrivateJoystickAxis(joystick, 1, cond.joyy-128); | ||
165 | if (cond.rtrig!=prev_cond->rtrig) | ||
166 | SDL_PrivateJoystickAxis(joystick, 2, cond.rtrig); | ||
167 | if (cond.ltrig!=prev_cond->ltrig) | ||
168 | SDL_PrivateJoystickAxis(joystick, 3, cond.ltrig); | ||
169 | if (cond.joy2x!=prev_cond->joy2x) | ||
170 | SDL_PrivateJoystickAxis(joystick, 4, cond.joy2x-128); | ||
171 | if (cond.joy2y!=prev_cond->joy2y) | ||
172 | SDL_PrivateJoystickAxis(joystick, 5, cond.joy2y-128); | ||
173 | |||
174 | joystick->hwdata->prev_buttons = buttons; | ||
175 | joystick->hwdata->prev_cond = cond; | ||
176 | } | ||
177 | |||
178 | /* Function to close a joystick after use */ | ||
179 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
180 | { | ||
181 | if (joystick->hwdata != NULL) { | ||
182 | /* free system specific hardware data */ | ||
183 | SDL_free(joystick->hwdata); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* Function to perform any system-specific joystick related cleanup */ | ||
188 | void SDL_SYS_JoystickQuit(void) | ||
189 | { | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | #endif /* SDL_JOYSTICK_DC */ | ||
diff --git a/apps/plugins/sdl/src/joystick/dummy/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/dummy/SDL_sysjoystick.c new file mode 100644 index 0000000000..3a1aae7c46 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/dummy/SDL_sysjoystick.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED) | ||
25 | |||
26 | /* This is the system specific header for the SDL joystick API */ | ||
27 | |||
28 | #include "SDL_joystick.h" | ||
29 | #include "../SDL_sysjoystick.h" | ||
30 | #include "../SDL_joystick_c.h" | ||
31 | |||
32 | /* Function to scan the system for joysticks. | ||
33 | * This function should set SDL_numjoysticks to the number of available | ||
34 | * joysticks. Joystick 0 should be the system default joystick. | ||
35 | * It should return 0, or -1 on an unrecoverable fatal error. | ||
36 | */ | ||
37 | int SDL_SYS_JoystickInit(void) | ||
38 | { | ||
39 | SDL_numjoysticks = 0; | ||
40 | return(0); | ||
41 | } | ||
42 | |||
43 | /* Function to get the device-dependent name of a joystick */ | ||
44 | const char *SDL_SYS_JoystickName(int index) | ||
45 | { | ||
46 | SDL_SetError("Logic error: No joysticks available"); | ||
47 | return(NULL); | ||
48 | } | ||
49 | |||
50 | /* Function to open a joystick for use. | ||
51 | The joystick to open is specified by the index field of the joystick. | ||
52 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
53 | It returns 0, or -1 if there is an error. | ||
54 | */ | ||
55 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
56 | { | ||
57 | SDL_SetError("Logic error: No joysticks available"); | ||
58 | return(-1); | ||
59 | } | ||
60 | |||
61 | /* Function to update the state of a joystick - called as a device poll. | ||
62 | * This function shouldn't update the joystick structure directly, | ||
63 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
64 | * and update joystick device state. | ||
65 | */ | ||
66 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
67 | { | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | /* Function to close a joystick after use */ | ||
72 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
73 | { | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | /* Function to perform any system-specific joystick related cleanup */ | ||
78 | void SDL_SYS_JoystickQuit(void) | ||
79 | { | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | #endif /* SDL_JOYSTICK_DUMMY || SDL_JOYSTICK_DISABLED */ | ||
diff --git a/apps/plugins/sdl/src/joystick/linux/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/linux/SDL_sysjoystick.c new file mode 100644 index 0000000000..ee43974789 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/linux/SDL_sysjoystick.c | |||
@@ -0,0 +1,1218 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_LINUX | ||
25 | |||
26 | /* This is the system specific header for the SDL joystick API */ | ||
27 | |||
28 | #include <sys/stat.h> | ||
29 | #include <unistd.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <sys/ioctl.h> | ||
32 | #include <limits.h> /* For the definition of PATH_MAX */ | ||
33 | #include <linux/joystick.h> | ||
34 | #if SDL_INPUT_LINUXEV | ||
35 | #include <linux/input.h> | ||
36 | #endif | ||
37 | |||
38 | #include "SDL_joystick.h" | ||
39 | #include "../SDL_sysjoystick.h" | ||
40 | #include "../SDL_joystick_c.h" | ||
41 | |||
42 | /* Special joystick configurations */ | ||
43 | static struct { | ||
44 | const char *name; | ||
45 | int naxes; | ||
46 | int nhats; | ||
47 | int nballs; | ||
48 | } special_joysticks[] = { | ||
49 | { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */ | ||
50 | { "SideWinder Precision Pro", 4, 1, 0 }, | ||
51 | { "SideWinder 3D Pro", 4, 1, 0 }, | ||
52 | { "Microsoft SideWinder 3D Pro", 4, 1, 0 }, | ||
53 | { "Microsoft SideWinder Precision Pro", 4, 1, 0 }, | ||
54 | { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 }, | ||
55 | { "WingMan Interceptor", 3, 3, 0 }, | ||
56 | { "WingMan Extreme Digital 3D", 4, 1, 0 }, | ||
57 | { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 }, | ||
58 | { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 }, | ||
59 | { "Saitek Saitek X45", 6, 1, 0 } | ||
60 | }; | ||
61 | |||
62 | /* It looks like newer kernels have the logical mapping at the driver level */ | ||
63 | #define NO_LOGICAL_JOYSTICKS | ||
64 | |||
65 | #ifndef NO_LOGICAL_JOYSTICKS | ||
66 | |||
67 | /* | ||
68 | Some USB HIDs show up as a single joystick even though they actually | ||
69 | control 2 or more joysticks. | ||
70 | */ | ||
71 | /* | ||
72 | This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can | ||
73 | be identified by their transparent blue design. It's quite trivial | ||
74 | to add other joysticks with similar quirky behavior. | ||
75 | -id | ||
76 | */ | ||
77 | |||
78 | struct joystick_logical_mapping { | ||
79 | int njoy; | ||
80 | int nthing; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | {logical joy, logical axis}, | ||
85 | {logical joy, logical hat}, | ||
86 | {logical joy, logical ball}, | ||
87 | {logical joy, logical button} | ||
88 | */ | ||
89 | |||
90 | static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = { | ||
91 | {0,0},{0,1},{0,2},{0,3},{0,4},{0,5} | ||
92 | }; | ||
93 | static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = { | ||
94 | {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11} | ||
95 | }; | ||
96 | |||
97 | static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = { | ||
98 | {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | ||
99 | {1,2},{1,3},{0,4},{0,5},{1,4},{1,5} | ||
100 | }; | ||
101 | static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = { | ||
102 | {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | ||
103 | {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11} | ||
104 | }; | ||
105 | |||
106 | static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = { | ||
107 | {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | ||
108 | {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, | ||
109 | {0,4},{0,5},{1,4},{1,5},{2,4},{2,5} | ||
110 | }; | ||
111 | static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = { | ||
112 | {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | ||
113 | {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, | ||
114 | {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11} | ||
115 | }; | ||
116 | |||
117 | static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = { | ||
118 | {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | ||
119 | {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, | ||
120 | {3,0},{3,1},{3,2},{3,3},{0,4},{0,5}, | ||
121 | {1,4},{1,5},{2,4},{2,5},{3,4},{3,5} | ||
122 | }; | ||
123 | static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = { | ||
124 | {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | ||
125 | {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, | ||
126 | {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, | ||
127 | {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11} | ||
128 | }; | ||
129 | |||
130 | struct joystick_logical_layout { | ||
131 | int naxes; | ||
132 | int nhats; | ||
133 | int nballs; | ||
134 | int nbuttons; | ||
135 | }; | ||
136 | |||
137 | static struct joystick_logical_layout mp88xx_1_logical_layout[] = { | ||
138 | {6, 0, 0, 12} | ||
139 | }; | ||
140 | static struct joystick_logical_layout mp88xx_2_logical_layout[] = { | ||
141 | {6, 0, 0, 12}, | ||
142 | {6, 0, 0, 12} | ||
143 | }; | ||
144 | static struct joystick_logical_layout mp88xx_3_logical_layout[] = { | ||
145 | {6, 0, 0, 12}, | ||
146 | {6, 0, 0, 12}, | ||
147 | {6, 0, 0, 12} | ||
148 | }; | ||
149 | static struct joystick_logical_layout mp88xx_4_logical_layout[] = { | ||
150 | {6, 0, 0, 12}, | ||
151 | {6, 0, 0, 12}, | ||
152 | {6, 0, 0, 12}, | ||
153 | {6, 0, 0, 12} | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | This array sets up a means of mapping a single physical joystick to | ||
158 | multiple logical joysticks. (djm) | ||
159 | |||
160 | njoys | ||
161 | the number of logical joysticks | ||
162 | |||
163 | layouts | ||
164 | an array of layout structures, one to describe each logical joystick | ||
165 | |||
166 | axes, hats, balls, buttons | ||
167 | arrays that map a physical thingy to a logical thingy | ||
168 | */ | ||
169 | struct joystick_logicalmap { | ||
170 | const char *name; | ||
171 | int nbuttons; | ||
172 | int njoys; | ||
173 | struct joystick_logical_layout *layout; | ||
174 | struct joystick_logical_mapping *axismap; | ||
175 | struct joystick_logical_mapping *hatmap; | ||
176 | struct joystick_logical_mapping *ballmap; | ||
177 | struct joystick_logical_mapping *buttonmap; | ||
178 | }; | ||
179 | |||
180 | static struct joystick_logicalmap joystick_logicalmap[] = { | ||
181 | { | ||
182 | "WiseGroup.,Ltd MP-8866 Dual USB Joypad", | ||
183 | 12, | ||
184 | 1, | ||
185 | mp88xx_1_logical_layout, | ||
186 | mp88xx_1_logical_axismap, | ||
187 | NULL, | ||
188 | NULL, | ||
189 | mp88xx_1_logical_buttonmap | ||
190 | }, | ||
191 | { | ||
192 | "WiseGroup.,Ltd MP-8866 Dual USB Joypad", | ||
193 | 24, | ||
194 | 2, | ||
195 | mp88xx_2_logical_layout, | ||
196 | mp88xx_2_logical_axismap, | ||
197 | NULL, | ||
198 | NULL, | ||
199 | mp88xx_2_logical_buttonmap | ||
200 | }, | ||
201 | { | ||
202 | "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | ||
203 | 12, | ||
204 | 1, | ||
205 | mp88xx_1_logical_layout, | ||
206 | mp88xx_1_logical_axismap, | ||
207 | NULL, | ||
208 | NULL, | ||
209 | mp88xx_1_logical_buttonmap | ||
210 | }, | ||
211 | { | ||
212 | "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | ||
213 | 24, | ||
214 | 2, | ||
215 | mp88xx_2_logical_layout, | ||
216 | mp88xx_2_logical_axismap, | ||
217 | NULL, | ||
218 | NULL, | ||
219 | mp88xx_2_logical_buttonmap | ||
220 | }, | ||
221 | { | ||
222 | "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | ||
223 | 36, | ||
224 | 3, | ||
225 | mp88xx_3_logical_layout, | ||
226 | mp88xx_3_logical_axismap, | ||
227 | NULL, | ||
228 | NULL, | ||
229 | mp88xx_3_logical_buttonmap | ||
230 | }, | ||
231 | { | ||
232 | "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | ||
233 | 48, | ||
234 | 4, | ||
235 | mp88xx_4_logical_layout, | ||
236 | mp88xx_4_logical_axismap, | ||
237 | NULL, | ||
238 | NULL, | ||
239 | mp88xx_4_logical_buttonmap | ||
240 | } | ||
241 | }; | ||
242 | |||
243 | /* find the head of a linked list, given a point in it | ||
244 | */ | ||
245 | #define SDL_joylist_head(i, start)\ | ||
246 | for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev; | ||
247 | |||
248 | #define SDL_logical_joydecl(d) d | ||
249 | |||
250 | |||
251 | #else | ||
252 | |||
253 | #define SDL_logical_joydecl(d) | ||
254 | |||
255 | #endif /* USE_LOGICAL_JOYSTICKS */ | ||
256 | |||
257 | /* The maximum number of joysticks we'll detect */ | ||
258 | #define MAX_JOYSTICKS 32 | ||
259 | |||
260 | /* A list of available joysticks */ | ||
261 | static struct | ||
262 | { | ||
263 | char* fname; | ||
264 | #ifndef NO_LOGICAL_JOYSTICKS | ||
265 | SDL_Joystick* joy; | ||
266 | struct joystick_logicalmap* map; | ||
267 | int prev; | ||
268 | int next; | ||
269 | int logicalno; | ||
270 | #endif /* USE_LOGICAL_JOYSTICKS */ | ||
271 | } SDL_joylist[MAX_JOYSTICKS]; | ||
272 | |||
273 | |||
274 | /* The private structure used to keep track of a joystick */ | ||
275 | struct joystick_hwdata { | ||
276 | int fd; | ||
277 | /* The current linux joystick driver maps hats to two axes */ | ||
278 | struct hwdata_hat { | ||
279 | int axis[2]; | ||
280 | } *hats; | ||
281 | /* The current linux joystick driver maps balls to two axes */ | ||
282 | struct hwdata_ball { | ||
283 | int axis[2]; | ||
284 | } *balls; | ||
285 | |||
286 | /* Support for the Linux 2.4 unified input interface */ | ||
287 | #if SDL_INPUT_LINUXEV | ||
288 | SDL_bool is_hid; | ||
289 | Uint8 key_map[KEY_MAX-BTN_MISC]; | ||
290 | Uint8 abs_map[ABS_MAX]; | ||
291 | struct axis_correct { | ||
292 | int used; | ||
293 | int coef[3]; | ||
294 | } abs_correct[ABS_MAX]; | ||
295 | #endif | ||
296 | }; | ||
297 | |||
298 | |||
299 | #ifndef NO_LOGICAL_JOYSTICKS | ||
300 | |||
301 | static int CountLogicalJoysticks(int max) | ||
302 | { | ||
303 | register int i, j, k, ret, prev; | ||
304 | const char* name; | ||
305 | int nbuttons, fd; | ||
306 | unsigned char n; | ||
307 | |||
308 | ret = 0; | ||
309 | |||
310 | for(i = 0; i < max; i++) { | ||
311 | name = SDL_SYS_JoystickName(i); | ||
312 | |||
313 | fd = open(SDL_joylist[i].fname, O_RDONLY, 0); | ||
314 | if ( fd >= 0 ) { | ||
315 | if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { | ||
316 | nbuttons = -1; | ||
317 | } else { | ||
318 | nbuttons = n; | ||
319 | } | ||
320 | close(fd); | ||
321 | } | ||
322 | else { | ||
323 | nbuttons=-1; | ||
324 | } | ||
325 | |||
326 | if (name) { | ||
327 | for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) { | ||
328 | if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) { | ||
329 | prev = i; | ||
330 | SDL_joylist[prev].map = &(joystick_logicalmap[j]); | ||
331 | |||
332 | for(k = 1; k < joystick_logicalmap[j].njoys; k++) { | ||
333 | SDL_joylist[prev].next = max + ret; | ||
334 | SDL_joylist[max+ret].prev = prev; | ||
335 | |||
336 | prev = max + ret; | ||
337 | SDL_joylist[prev].logicalno = k; | ||
338 | SDL_joylist[prev].map = &(joystick_logicalmap[j]); | ||
339 | ret++; | ||
340 | } | ||
341 | |||
342 | break; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static void LogicalSuffix(int logicalno, char* namebuf, int len) | ||
352 | { | ||
353 | register int slen; | ||
354 | const static char suffixs[] = | ||
355 | "01020304050607080910111213141516171819" | ||
356 | "20212223242526272829303132"; | ||
357 | const char* suffix; | ||
358 | slen = SDL_strlen(namebuf); | ||
359 | suffix = NULL; | ||
360 | |||
361 | if (logicalno*2<sizeof(suffixs)) | ||
362 | suffix = suffixs + (logicalno*2); | ||
363 | |||
364 | if (slen + 4 < len && suffix) { | ||
365 | namebuf[slen++] = ' '; | ||
366 | namebuf[slen++] = '#'; | ||
367 | namebuf[slen++] = suffix[0]; | ||
368 | namebuf[slen++] = suffix[1]; | ||
369 | namebuf[slen++] = 0; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | #endif /* USE_LOGICAL_JOYSTICKS */ | ||
374 | |||
375 | #if SDL_INPUT_LINUXEV | ||
376 | #define test_bit(nr, addr) \ | ||
377 | (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0) | ||
378 | #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1) | ||
379 | |||
380 | static int EV_IsJoystick(int fd) | ||
381 | { | ||
382 | unsigned long evbit[NBITS(EV_MAX)] = { 0 }; | ||
383 | unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; | ||
384 | unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; | ||
385 | |||
386 | if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) || | ||
387 | (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || | ||
388 | (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) { | ||
389 | return(0); | ||
390 | } | ||
391 | if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) && | ||
392 | test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && | ||
393 | (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0; | ||
394 | return(1); | ||
395 | } | ||
396 | |||
397 | #endif /* SDL_INPUT_LINUXEV */ | ||
398 | |||
399 | /* Function to scan the system for joysticks */ | ||
400 | int SDL_SYS_JoystickInit(void) | ||
401 | { | ||
402 | /* The base path of the joystick devices */ | ||
403 | const char *joydev_pattern[] = { | ||
404 | #if SDL_INPUT_LINUXEV | ||
405 | "/dev/input/event%d", | ||
406 | #endif | ||
407 | "/dev/input/js%d", | ||
408 | "/dev/js%d" | ||
409 | }; | ||
410 | int numjoysticks; | ||
411 | int i, j; | ||
412 | int fd; | ||
413 | char path[PATH_MAX]; | ||
414 | dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ | ||
415 | struct stat sb; | ||
416 | int n, duplicate; | ||
417 | |||
418 | numjoysticks = 0; | ||
419 | |||
420 | /* First see if the user specified one or more joysticks to use */ | ||
421 | if ( SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL ) { | ||
422 | char *envcopy, *envpath, *delim; | ||
423 | envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE")); | ||
424 | envpath = envcopy; | ||
425 | while ( envpath != NULL ) { | ||
426 | delim = SDL_strchr(envpath, ':'); | ||
427 | if ( delim != NULL ) { | ||
428 | *delim++ = '\0'; | ||
429 | } | ||
430 | if ( stat(envpath, &sb) == 0 ) { | ||
431 | fd = open(envpath, O_RDONLY, 0); | ||
432 | if ( fd >= 0 ) { | ||
433 | /* Assume the user knows what they're doing. */ | ||
434 | SDL_joylist[numjoysticks].fname = SDL_strdup(envpath); | ||
435 | if ( SDL_joylist[numjoysticks].fname ) { | ||
436 | dev_nums[numjoysticks] = sb.st_rdev; | ||
437 | ++numjoysticks; | ||
438 | } | ||
439 | close(fd); | ||
440 | } | ||
441 | } | ||
442 | envpath = delim; | ||
443 | } | ||
444 | SDL_free(envcopy); | ||
445 | } | ||
446 | |||
447 | for ( i=0; i<SDL_arraysize(joydev_pattern); ++i ) { | ||
448 | for ( j=0; j < MAX_JOYSTICKS; ++j ) { | ||
449 | SDL_snprintf(path, SDL_arraysize(path), joydev_pattern[i], j); | ||
450 | |||
451 | /* rcg06302000 replaced access(F_OK) call with stat(). | ||
452 | * stat() will fail if the file doesn't exist, so it's | ||
453 | * equivalent behaviour. | ||
454 | */ | ||
455 | if ( stat(path, &sb) == 0 ) { | ||
456 | /* Check to make sure it's not already in list. | ||
457 | * This happens when we see a stick via symlink. | ||
458 | */ | ||
459 | duplicate = 0; | ||
460 | for (n=0; (n<numjoysticks) && !duplicate; ++n) { | ||
461 | if ( sb.st_rdev == dev_nums[n] ) { | ||
462 | duplicate = 1; | ||
463 | } | ||
464 | } | ||
465 | if (duplicate) { | ||
466 | continue; | ||
467 | } | ||
468 | |||
469 | fd = open(path, O_RDONLY, 0); | ||
470 | if ( fd < 0 ) { | ||
471 | continue; | ||
472 | } | ||
473 | #if SDL_INPUT_LINUXEV | ||
474 | #ifdef DEBUG_INPUT_EVENTS | ||
475 | printf("Checking %s\n", path); | ||
476 | #endif | ||
477 | if ( (i == 0) && ! EV_IsJoystick(fd) ) { | ||
478 | close(fd); | ||
479 | continue; | ||
480 | } | ||
481 | #endif | ||
482 | close(fd); | ||
483 | |||
484 | /* We're fine, add this joystick */ | ||
485 | SDL_joylist[numjoysticks].fname = SDL_strdup(path); | ||
486 | if ( SDL_joylist[numjoysticks].fname ) { | ||
487 | dev_nums[numjoysticks] = sb.st_rdev; | ||
488 | ++numjoysticks; | ||
489 | } | ||
490 | } | ||
491 | } | ||
492 | |||
493 | #if SDL_INPUT_LINUXEV | ||
494 | /* This is a special case... | ||
495 | If the event devices are valid then the joystick devices | ||
496 | will be duplicates but without extra information about their | ||
497 | hats or balls. Unfortunately, the event devices can't | ||
498 | currently be calibrated, so it's a win-lose situation. | ||
499 | So : /dev/input/eventX = /dev/input/jsY = /dev/jsY | ||
500 | */ | ||
501 | if ( (i == 0) && (numjoysticks > 0) ) | ||
502 | break; | ||
503 | #endif | ||
504 | } | ||
505 | #ifndef NO_LOGICAL_JOYSTICKS | ||
506 | numjoysticks += CountLogicalJoysticks(numjoysticks); | ||
507 | #endif | ||
508 | |||
509 | return(numjoysticks); | ||
510 | } | ||
511 | |||
512 | /* Function to get the device-dependent name of a joystick */ | ||
513 | const char *SDL_SYS_JoystickName(int index) | ||
514 | { | ||
515 | int fd; | ||
516 | static char namebuf[128]; | ||
517 | char *name; | ||
518 | SDL_logical_joydecl(int oindex = index); | ||
519 | |||
520 | #ifndef NO_LOGICAL_JOYSTICKS | ||
521 | SDL_joylist_head(index, index); | ||
522 | #endif | ||
523 | name = NULL; | ||
524 | fd = open(SDL_joylist[index].fname, O_RDONLY, 0); | ||
525 | if ( fd >= 0 ) { | ||
526 | if ( | ||
527 | #if SDL_INPUT_LINUXEV | ||
528 | (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) && | ||
529 | #endif | ||
530 | (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) { | ||
531 | name = SDL_joylist[index].fname; | ||
532 | } else { | ||
533 | name = namebuf; | ||
534 | } | ||
535 | close(fd); | ||
536 | |||
537 | |||
538 | #ifndef NO_LOGICAL_JOYSTICKS | ||
539 | if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex) | ||
540 | { | ||
541 | LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128); | ||
542 | } | ||
543 | #endif | ||
544 | } | ||
545 | return name; | ||
546 | } | ||
547 | |||
548 | static int allocate_hatdata(SDL_Joystick *joystick) | ||
549 | { | ||
550 | int i; | ||
551 | |||
552 | joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc( | ||
553 | joystick->nhats * sizeof(struct hwdata_hat)); | ||
554 | if ( joystick->hwdata->hats == NULL ) { | ||
555 | return(-1); | ||
556 | } | ||
557 | for ( i=0; i<joystick->nhats; ++i ) { | ||
558 | joystick->hwdata->hats[i].axis[0] = 1; | ||
559 | joystick->hwdata->hats[i].axis[1] = 1; | ||
560 | } | ||
561 | return(0); | ||
562 | } | ||
563 | |||
564 | static int allocate_balldata(SDL_Joystick *joystick) | ||
565 | { | ||
566 | int i; | ||
567 | |||
568 | joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc( | ||
569 | joystick->nballs * sizeof(struct hwdata_ball)); | ||
570 | if ( joystick->hwdata->balls == NULL ) { | ||
571 | return(-1); | ||
572 | } | ||
573 | for ( i=0; i<joystick->nballs; ++i ) { | ||
574 | joystick->hwdata->balls[i].axis[0] = 0; | ||
575 | joystick->hwdata->balls[i].axis[1] = 0; | ||
576 | } | ||
577 | return(0); | ||
578 | } | ||
579 | |||
580 | static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd) | ||
581 | { | ||
582 | SDL_bool handled; | ||
583 | unsigned char n; | ||
584 | int tmp_naxes, tmp_nhats, tmp_nballs; | ||
585 | const char *name; | ||
586 | char *env, env_name[128]; | ||
587 | int i; | ||
588 | |||
589 | handled = SDL_FALSE; | ||
590 | |||
591 | /* Default joystick device settings */ | ||
592 | if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) { | ||
593 | joystick->naxes = 2; | ||
594 | } else { | ||
595 | joystick->naxes = n; | ||
596 | } | ||
597 | if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { | ||
598 | joystick->nbuttons = 2; | ||
599 | } else { | ||
600 | joystick->nbuttons = n; | ||
601 | } | ||
602 | |||
603 | name = SDL_SYS_JoystickName(joystick->index); | ||
604 | |||
605 | /* Generic analog joystick support */ | ||
606 | if ( SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat") ) { | ||
607 | if ( SDL_sscanf(name,"Analog %d-axis %*d-button %d-hat", | ||
608 | &tmp_naxes, &tmp_nhats) == 2 ) { | ||
609 | |||
610 | joystick->naxes = tmp_naxes; | ||
611 | joystick->nhats = tmp_nhats; | ||
612 | |||
613 | handled = SDL_TRUE; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | /* Special joystick support */ | ||
618 | for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) { | ||
619 | if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) { | ||
620 | |||
621 | joystick->naxes = special_joysticks[i].naxes; | ||
622 | joystick->nhats = special_joysticks[i].nhats; | ||
623 | joystick->nballs = special_joysticks[i].nballs; | ||
624 | |||
625 | handled = SDL_TRUE; | ||
626 | break; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /* User environment joystick support */ | ||
631 | if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) { | ||
632 | *env_name = '\0'; | ||
633 | if ( *env == '\'' && SDL_sscanf(env, "'%[^']s'", env_name) == 1 ) | ||
634 | env += SDL_strlen(env_name)+2; | ||
635 | else if ( SDL_sscanf(env, "%s", env_name) == 1 ) | ||
636 | env += SDL_strlen(env_name); | ||
637 | |||
638 | if ( SDL_strcmp(name, env_name) == 0 ) { | ||
639 | |||
640 | if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats, | ||
641 | &tmp_nballs) == 3 ) { | ||
642 | |||
643 | joystick->naxes = tmp_naxes; | ||
644 | joystick->nhats = tmp_nhats; | ||
645 | joystick->nballs = tmp_nballs; | ||
646 | |||
647 | handled = SDL_TRUE; | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /* Remap hats and balls */ | ||
653 | if (handled) { | ||
654 | if ( joystick->nhats > 0 ) { | ||
655 | if ( allocate_hatdata(joystick) < 0 ) { | ||
656 | joystick->nhats = 0; | ||
657 | } | ||
658 | } | ||
659 | if ( joystick->nballs > 0 ) { | ||
660 | if ( allocate_balldata(joystick) < 0 ) { | ||
661 | joystick->nballs = 0; | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | |||
666 | return(handled); | ||
667 | } | ||
668 | |||
669 | #if SDL_INPUT_LINUXEV | ||
670 | |||
671 | static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd) | ||
672 | { | ||
673 | int i, t; | ||
674 | unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; | ||
675 | unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; | ||
676 | unsigned long relbit[NBITS(REL_MAX)] = { 0 }; | ||
677 | |||
678 | /* See if this device uses the new unified event API */ | ||
679 | if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && | ||
680 | (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && | ||
681 | (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) { | ||
682 | joystick->hwdata->is_hid = SDL_TRUE; | ||
683 | |||
684 | /* Get the number of buttons, axes, and other thingamajigs */ | ||
685 | for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) { | ||
686 | if ( test_bit(i, keybit) ) { | ||
687 | #ifdef DEBUG_INPUT_EVENTS | ||
688 | printf("Joystick has button: 0x%x\n", i); | ||
689 | #endif | ||
690 | joystick->hwdata->key_map[i-BTN_MISC] = | ||
691 | joystick->nbuttons; | ||
692 | ++joystick->nbuttons; | ||
693 | } | ||
694 | } | ||
695 | for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) { | ||
696 | if ( test_bit(i, keybit) ) { | ||
697 | #ifdef DEBUG_INPUT_EVENTS | ||
698 | printf("Joystick has button: 0x%x\n", i); | ||
699 | #endif | ||
700 | joystick->hwdata->key_map[i-BTN_MISC] = | ||
701 | joystick->nbuttons; | ||
702 | ++joystick->nbuttons; | ||
703 | } | ||
704 | } | ||
705 | for ( i=0; i<ABS_MISC; ++i ) { | ||
706 | /* Skip hats */ | ||
707 | if ( i == ABS_HAT0X ) { | ||
708 | i = ABS_HAT3Y; | ||
709 | continue; | ||
710 | } | ||
711 | if ( test_bit(i, absbit) ) { | ||
712 | struct input_absinfo absinfo; | ||
713 | |||
714 | if ( ioctl(fd, EVIOCGABS(i), &absinfo) < 0 ) | ||
715 | continue; | ||
716 | #ifdef DEBUG_INPUT_EVENTS | ||
717 | printf("Joystick has absolute axis: %x\n", i); | ||
718 | printf("Values = { %d, %d, %d, %d, %d }\n", | ||
719 | absinfo.value, absinfo.minimum, | ||
720 | absinfo.maximum, absinfo.fuzz, absinfo.flat); | ||
721 | #endif /* DEBUG_INPUT_EVENTS */ | ||
722 | joystick->hwdata->abs_map[i] = joystick->naxes; | ||
723 | if ( absinfo.minimum == absinfo.maximum ) { | ||
724 | joystick->hwdata->abs_correct[i].used = 0; | ||
725 | } else { | ||
726 | joystick->hwdata->abs_correct[i].used = 1; | ||
727 | joystick->hwdata->abs_correct[i].coef[0] = | ||
728 | (absinfo.maximum + absinfo.minimum) / 2 - absinfo.flat; | ||
729 | joystick->hwdata->abs_correct[i].coef[1] = | ||
730 | (absinfo.maximum + absinfo.minimum) / 2 + absinfo.flat; | ||
731 | t = ((absinfo.maximum - absinfo.minimum) / 2 - 2 * absinfo.flat); | ||
732 | if ( t != 0 ) { | ||
733 | joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t; | ||
734 | } else { | ||
735 | joystick->hwdata->abs_correct[i].coef[2] = 0; | ||
736 | } | ||
737 | } | ||
738 | ++joystick->naxes; | ||
739 | } | ||
740 | } | ||
741 | for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) { | ||
742 | if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) { | ||
743 | #ifdef DEBUG_INPUT_EVENTS | ||
744 | printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2); | ||
745 | #endif | ||
746 | ++joystick->nhats; | ||
747 | } | ||
748 | } | ||
749 | if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) { | ||
750 | ++joystick->nballs; | ||
751 | } | ||
752 | |||
753 | /* Allocate data to keep track of these thingamajigs */ | ||
754 | if ( joystick->nhats > 0 ) { | ||
755 | if ( allocate_hatdata(joystick) < 0 ) { | ||
756 | joystick->nhats = 0; | ||
757 | } | ||
758 | } | ||
759 | if ( joystick->nballs > 0 ) { | ||
760 | if ( allocate_balldata(joystick) < 0 ) { | ||
761 | joystick->nballs = 0; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | return(joystick->hwdata->is_hid); | ||
766 | } | ||
767 | |||
768 | #endif /* SDL_INPUT_LINUXEV */ | ||
769 | |||
770 | #ifndef NO_LOGICAL_JOYSTICKS | ||
771 | static void ConfigLogicalJoystick(SDL_Joystick *joystick) | ||
772 | { | ||
773 | struct joystick_logical_layout* layout; | ||
774 | |||
775 | layout = SDL_joylist[joystick->index].map->layout + | ||
776 | SDL_joylist[joystick->index].logicalno; | ||
777 | |||
778 | joystick->nbuttons = layout->nbuttons; | ||
779 | joystick->nhats = layout->nhats; | ||
780 | joystick->naxes = layout->naxes; | ||
781 | joystick->nballs = layout->nballs; | ||
782 | } | ||
783 | #endif | ||
784 | |||
785 | |||
786 | /* Function to open a joystick for use. | ||
787 | The joystick to open is specified by the index field of the joystick. | ||
788 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
789 | It returns 0, or -1 if there is an error. | ||
790 | */ | ||
791 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
792 | { | ||
793 | int fd; | ||
794 | SDL_logical_joydecl(int realindex); | ||
795 | SDL_logical_joydecl(SDL_Joystick *realjoy = NULL); | ||
796 | |||
797 | /* Open the joystick and set the joystick file descriptor */ | ||
798 | #ifndef NO_LOGICAL_JOYSTICKS | ||
799 | if (SDL_joylist[joystick->index].fname == NULL) { | ||
800 | SDL_joylist_head(realindex, joystick->index); | ||
801 | realjoy = SDL_JoystickOpen(realindex); | ||
802 | |||
803 | if (realjoy == NULL) | ||
804 | return(-1); | ||
805 | |||
806 | fd = realjoy->hwdata->fd; | ||
807 | |||
808 | } else { | ||
809 | fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0); | ||
810 | } | ||
811 | SDL_joylist[joystick->index].joy = joystick; | ||
812 | #else | ||
813 | fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0); | ||
814 | #endif | ||
815 | |||
816 | if ( fd < 0 ) { | ||
817 | SDL_SetError("Unable to open %s\n", | ||
818 | SDL_joylist[joystick->index]); | ||
819 | return(-1); | ||
820 | } | ||
821 | joystick->hwdata = (struct joystick_hwdata *) | ||
822 | SDL_malloc(sizeof(*joystick->hwdata)); | ||
823 | if ( joystick->hwdata == NULL ) { | ||
824 | SDL_OutOfMemory(); | ||
825 | close(fd); | ||
826 | return(-1); | ||
827 | } | ||
828 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | ||
829 | joystick->hwdata->fd = fd; | ||
830 | |||
831 | /* Set the joystick to non-blocking read mode */ | ||
832 | fcntl(fd, F_SETFL, O_NONBLOCK); | ||
833 | |||
834 | /* Get the number of buttons and axes on the joystick */ | ||
835 | #ifndef NO_LOGICAL_JOYSTICKS | ||
836 | if (realjoy) | ||
837 | ConfigLogicalJoystick(joystick); | ||
838 | else | ||
839 | #endif | ||
840 | #if SDL_INPUT_LINUXEV | ||
841 | if ( ! EV_ConfigJoystick(joystick, fd) ) | ||
842 | #endif | ||
843 | JS_ConfigJoystick(joystick, fd); | ||
844 | |||
845 | return(0); | ||
846 | } | ||
847 | |||
848 | #ifndef NO_LOGICAL_JOYSTICKS | ||
849 | |||
850 | static SDL_Joystick* FindLogicalJoystick( | ||
851 | SDL_Joystick *joystick, struct joystick_logical_mapping* v) | ||
852 | { | ||
853 | SDL_Joystick *logicaljoy; | ||
854 | register int i; | ||
855 | |||
856 | i = joystick->index; | ||
857 | logicaljoy = NULL; | ||
858 | |||
859 | /* get the fake joystick that will receive the event | ||
860 | */ | ||
861 | for(;;) { | ||
862 | |||
863 | if (SDL_joylist[i].logicalno == v->njoy) { | ||
864 | logicaljoy = SDL_joylist[i].joy; | ||
865 | break; | ||
866 | } | ||
867 | |||
868 | if (SDL_joylist[i].next == 0) | ||
869 | break; | ||
870 | |||
871 | i = SDL_joylist[i].next; | ||
872 | |||
873 | } | ||
874 | |||
875 | return logicaljoy; | ||
876 | } | ||
877 | |||
878 | static int LogicalJoystickButton( | ||
879 | SDL_Joystick *joystick, Uint8 button, Uint8 state){ | ||
880 | struct joystick_logical_mapping* buttons; | ||
881 | SDL_Joystick *logicaljoy = NULL; | ||
882 | |||
883 | /* if there's no map then this is just a regular joystick | ||
884 | */ | ||
885 | if (SDL_joylist[joystick->index].map == NULL) | ||
886 | return 0; | ||
887 | |||
888 | /* get the logical joystick that will receive the event | ||
889 | */ | ||
890 | buttons = SDL_joylist[joystick->index].map->buttonmap+button; | ||
891 | logicaljoy = FindLogicalJoystick(joystick, buttons); | ||
892 | |||
893 | if (logicaljoy == NULL) | ||
894 | return 1; | ||
895 | |||
896 | SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state); | ||
897 | |||
898 | return 1; | ||
899 | } | ||
900 | |||
901 | static int LogicalJoystickAxis( | ||
902 | SDL_Joystick *joystick, Uint8 axis, Sint16 value) | ||
903 | { | ||
904 | struct joystick_logical_mapping* axes; | ||
905 | SDL_Joystick *logicaljoy = NULL; | ||
906 | |||
907 | /* if there's no map then this is just a regular joystick | ||
908 | */ | ||
909 | if (SDL_joylist[joystick->index].map == NULL) | ||
910 | return 0; | ||
911 | |||
912 | /* get the logical joystick that will receive the event | ||
913 | */ | ||
914 | axes = SDL_joylist[joystick->index].map->axismap+axis; | ||
915 | logicaljoy = FindLogicalJoystick(joystick, axes); | ||
916 | |||
917 | if (logicaljoy == NULL) | ||
918 | return 1; | ||
919 | |||
920 | SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value); | ||
921 | |||
922 | return 1; | ||
923 | } | ||
924 | #endif /* USE_LOGICAL_JOYSTICKS */ | ||
925 | |||
926 | static __inline__ | ||
927 | void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) | ||
928 | { | ||
929 | struct hwdata_hat *the_hat; | ||
930 | const Uint8 position_map[3][3] = { | ||
931 | { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, | ||
932 | { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, | ||
933 | { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } | ||
934 | }; | ||
935 | SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL); | ||
936 | SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL); | ||
937 | |||
938 | if (stick->nhats <= hat) { | ||
939 | return; /* whoops, that shouldn't happen! */ | ||
940 | } | ||
941 | |||
942 | the_hat = &stick->hwdata->hats[hat]; | ||
943 | if ( value < 0 ) { | ||
944 | value = 0; | ||
945 | } else | ||
946 | if ( value == 0 ) { | ||
947 | value = 1; | ||
948 | } else | ||
949 | if ( value > 0 ) { | ||
950 | value = 2; | ||
951 | } | ||
952 | if ( value != the_hat->axis[axis] ) { | ||
953 | the_hat->axis[axis] = value; | ||
954 | |||
955 | #ifndef NO_LOGICAL_JOYSTICKS | ||
956 | /* if there's no map then this is just a regular joystick | ||
957 | */ | ||
958 | if (SDL_joylist[stick->index].map != NULL) { | ||
959 | |||
960 | /* get the fake joystick that will receive the event | ||
961 | */ | ||
962 | hats = SDL_joylist[stick->index].map->hatmap+hat; | ||
963 | logicaljoy = FindLogicalJoystick(stick, hats); | ||
964 | } | ||
965 | |||
966 | if (logicaljoy) { | ||
967 | stick = logicaljoy; | ||
968 | hat = hats->nthing; | ||
969 | } | ||
970 | #endif /* USE_LOGICAL_JOYSTICKS */ | ||
971 | |||
972 | SDL_PrivateJoystickHat(stick, hat, | ||
973 | position_map[the_hat->axis[1]][the_hat->axis[0]]); | ||
974 | } | ||
975 | } | ||
976 | |||
977 | static __inline__ | ||
978 | void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) | ||
979 | { | ||
980 | if ((stick->nballs <= ball) || (axis >= 2)) { | ||
981 | return; /* whoops, that shouldn't happen! */ | ||
982 | } | ||
983 | stick->hwdata->balls[ball].axis[axis] += value; | ||
984 | } | ||
985 | |||
986 | /* Function to update the state of a joystick - called as a device poll. | ||
987 | * This function shouldn't update the joystick structure directly, | ||
988 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
989 | * and update joystick device state. | ||
990 | */ | ||
991 | static __inline__ void JS_HandleEvents(SDL_Joystick *joystick) | ||
992 | { | ||
993 | struct js_event events[32]; | ||
994 | int i, len; | ||
995 | Uint8 other_axis; | ||
996 | |||
997 | #ifndef NO_LOGICAL_JOYSTICKS | ||
998 | if (SDL_joylist[joystick->index].fname == NULL) { | ||
999 | SDL_joylist_head(i, joystick->index); | ||
1000 | JS_HandleEvents(SDL_joylist[i].joy); | ||
1001 | return; | ||
1002 | } | ||
1003 | #endif | ||
1004 | |||
1005 | while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) { | ||
1006 | len /= sizeof(events[0]); | ||
1007 | for ( i=0; i<len; ++i ) { | ||
1008 | switch (events[i].type & ~JS_EVENT_INIT) { | ||
1009 | case JS_EVENT_AXIS: | ||
1010 | if ( events[i].number < joystick->naxes ) { | ||
1011 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1012 | if (!LogicalJoystickAxis(joystick, | ||
1013 | events[i].number, events[i].value)) | ||
1014 | #endif | ||
1015 | SDL_PrivateJoystickAxis(joystick, | ||
1016 | events[i].number, events[i].value); | ||
1017 | break; | ||
1018 | } | ||
1019 | events[i].number -= joystick->naxes; | ||
1020 | other_axis = (events[i].number / 2); | ||
1021 | if ( other_axis < joystick->nhats ) { | ||
1022 | HandleHat(joystick, other_axis, | ||
1023 | events[i].number%2, | ||
1024 | events[i].value); | ||
1025 | break; | ||
1026 | } | ||
1027 | events[i].number -= joystick->nhats*2; | ||
1028 | other_axis = (events[i].number / 2); | ||
1029 | if ( other_axis < joystick->nballs ) { | ||
1030 | HandleBall(joystick, other_axis, | ||
1031 | events[i].number%2, | ||
1032 | events[i].value); | ||
1033 | break; | ||
1034 | } | ||
1035 | break; | ||
1036 | case JS_EVENT_BUTTON: | ||
1037 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1038 | if (!LogicalJoystickButton(joystick, | ||
1039 | events[i].number, events[i].value)) | ||
1040 | #endif | ||
1041 | SDL_PrivateJoystickButton(joystick, | ||
1042 | events[i].number, events[i].value); | ||
1043 | break; | ||
1044 | default: | ||
1045 | /* ?? */ | ||
1046 | break; | ||
1047 | } | ||
1048 | } | ||
1049 | } | ||
1050 | } | ||
1051 | #if SDL_INPUT_LINUXEV | ||
1052 | static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value) | ||
1053 | { | ||
1054 | struct axis_correct *correct; | ||
1055 | |||
1056 | correct = &joystick->hwdata->abs_correct[which]; | ||
1057 | if ( correct->used ) { | ||
1058 | if ( value > correct->coef[0] ) { | ||
1059 | if ( value < correct->coef[1] ) { | ||
1060 | return 0; | ||
1061 | } | ||
1062 | value -= correct->coef[1]; | ||
1063 | } else { | ||
1064 | value -= correct->coef[0]; | ||
1065 | } | ||
1066 | value *= correct->coef[2]; | ||
1067 | value >>= 14; | ||
1068 | } | ||
1069 | |||
1070 | /* Clamp and return */ | ||
1071 | if ( value < -32768 ) return -32768; | ||
1072 | if ( value > 32767 ) return 32767; | ||
1073 | |||
1074 | return value; | ||
1075 | } | ||
1076 | |||
1077 | static __inline__ void EV_HandleEvents(SDL_Joystick *joystick) | ||
1078 | { | ||
1079 | struct input_event events[32]; | ||
1080 | int i, len; | ||
1081 | int code; | ||
1082 | |||
1083 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1084 | if (SDL_joylist[joystick->index].fname == NULL) { | ||
1085 | SDL_joylist_head(i, joystick->index); | ||
1086 | return EV_HandleEvents(SDL_joylist[i].joy); | ||
1087 | } | ||
1088 | #endif | ||
1089 | |||
1090 | while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) { | ||
1091 | len /= sizeof(events[0]); | ||
1092 | for ( i=0; i<len; ++i ) { | ||
1093 | code = events[i].code; | ||
1094 | switch (events[i].type) { | ||
1095 | case EV_KEY: | ||
1096 | if ( code >= BTN_MISC ) { | ||
1097 | code -= BTN_MISC; | ||
1098 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1099 | if (!LogicalJoystickButton(joystick, | ||
1100 | joystick->hwdata->key_map[code], | ||
1101 | events[i].value)) | ||
1102 | #endif | ||
1103 | SDL_PrivateJoystickButton(joystick, | ||
1104 | joystick->hwdata->key_map[code], | ||
1105 | events[i].value); | ||
1106 | } | ||
1107 | break; | ||
1108 | case EV_ABS: | ||
1109 | switch (code) { | ||
1110 | case ABS_HAT0X: | ||
1111 | case ABS_HAT0Y: | ||
1112 | case ABS_HAT1X: | ||
1113 | case ABS_HAT1Y: | ||
1114 | case ABS_HAT2X: | ||
1115 | case ABS_HAT2Y: | ||
1116 | case ABS_HAT3X: | ||
1117 | case ABS_HAT3Y: | ||
1118 | code -= ABS_HAT0X; | ||
1119 | HandleHat(joystick, code/2, code%2, | ||
1120 | events[i].value); | ||
1121 | break; | ||
1122 | default: | ||
1123 | events[i].value = EV_AxisCorrect(joystick, code, events[i].value); | ||
1124 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1125 | if (!LogicalJoystickAxis(joystick, | ||
1126 | joystick->hwdata->abs_map[code], | ||
1127 | events[i].value)) | ||
1128 | #endif | ||
1129 | SDL_PrivateJoystickAxis(joystick, | ||
1130 | joystick->hwdata->abs_map[code], | ||
1131 | events[i].value); | ||
1132 | break; | ||
1133 | } | ||
1134 | break; | ||
1135 | case EV_REL: | ||
1136 | switch (code) { | ||
1137 | case REL_X: | ||
1138 | case REL_Y: | ||
1139 | code -= REL_X; | ||
1140 | HandleBall(joystick, code/2, code%2, | ||
1141 | events[i].value); | ||
1142 | break; | ||
1143 | default: | ||
1144 | break; | ||
1145 | } | ||
1146 | break; | ||
1147 | default: | ||
1148 | break; | ||
1149 | } | ||
1150 | } | ||
1151 | } | ||
1152 | } | ||
1153 | #endif /* SDL_INPUT_LINUXEV */ | ||
1154 | |||
1155 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
1156 | { | ||
1157 | int i; | ||
1158 | |||
1159 | #if SDL_INPUT_LINUXEV | ||
1160 | if ( joystick->hwdata->is_hid ) | ||
1161 | EV_HandleEvents(joystick); | ||
1162 | else | ||
1163 | #endif | ||
1164 | JS_HandleEvents(joystick); | ||
1165 | |||
1166 | /* Deliver ball motion updates */ | ||
1167 | for ( i=0; i<joystick->nballs; ++i ) { | ||
1168 | int xrel, yrel; | ||
1169 | |||
1170 | xrel = joystick->hwdata->balls[i].axis[0]; | ||
1171 | yrel = joystick->hwdata->balls[i].axis[1]; | ||
1172 | if ( xrel || yrel ) { | ||
1173 | joystick->hwdata->balls[i].axis[0] = 0; | ||
1174 | joystick->hwdata->balls[i].axis[1] = 0; | ||
1175 | SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel); | ||
1176 | } | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | /* Function to close a joystick after use */ | ||
1181 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
1182 | { | ||
1183 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1184 | register int i; | ||
1185 | if (SDL_joylist[joystick->index].fname == NULL) { | ||
1186 | SDL_joylist_head(i, joystick->index); | ||
1187 | SDL_JoystickClose(SDL_joylist[i].joy); | ||
1188 | } | ||
1189 | #endif | ||
1190 | |||
1191 | if ( joystick->hwdata ) { | ||
1192 | #ifndef NO_LOGICAL_JOYSTICKS | ||
1193 | if (SDL_joylist[joystick->index].fname != NULL) | ||
1194 | #endif | ||
1195 | close(joystick->hwdata->fd); | ||
1196 | if ( joystick->hwdata->hats ) { | ||
1197 | SDL_free(joystick->hwdata->hats); | ||
1198 | } | ||
1199 | if ( joystick->hwdata->balls ) { | ||
1200 | SDL_free(joystick->hwdata->balls); | ||
1201 | } | ||
1202 | SDL_free(joystick->hwdata); | ||
1203 | joystick->hwdata = NULL; | ||
1204 | } | ||
1205 | } | ||
1206 | |||
1207 | /* Function to perform any system-specific joystick related cleanup */ | ||
1208 | void SDL_SYS_JoystickQuit(void) | ||
1209 | { | ||
1210 | int i; | ||
1211 | |||
1212 | for ( i=0; SDL_joylist[i].fname; ++i ) { | ||
1213 | SDL_free(SDL_joylist[i].fname); | ||
1214 | SDL_joylist[i].fname = NULL; | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | #endif /* SDL_JOYSTICK_LINUX */ | ||
diff --git a/apps/plugins/sdl/src/joystick/macos/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/macos/SDL_sysjoystick.c new file mode 100644 index 0000000000..3645dbd014 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/macos/SDL_sysjoystick.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_MACOS | ||
25 | |||
26 | /* SDL stuff -- "SDL_sysjoystick.c" | ||
27 | MacOS joystick functions by Frederick Reitberger | ||
28 | |||
29 | The code that follows is meant for SDL. Use at your own risk. | ||
30 | */ | ||
31 | |||
32 | #include <InputSprocket.h> | ||
33 | |||
34 | #include "SDL_joystick.h" | ||
35 | #include "../SDL_sysjoystick.h" | ||
36 | #include "../SDL_joystick_c.h" | ||
37 | |||
38 | |||
39 | /* The max number of joysticks we will detect */ | ||
40 | #define MAX_JOYSTICKS 16 | ||
41 | /* Limit ourselves to 32 elements per device */ | ||
42 | #define kMaxReferences 32 | ||
43 | |||
44 | #define ISpSymmetricAxisToFloat(axis) ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle)) | ||
45 | #define ISpAsymmetricAxisToFloat(axis) (((float) axis) / (kISpAxisMaximum)) | ||
46 | |||
47 | |||
48 | static ISpDeviceReference SYS_Joysticks[MAX_JOYSTICKS]; | ||
49 | static ISpElementListReference SYS_Elements[MAX_JOYSTICKS]; | ||
50 | static ISpDeviceDefinition SYS_DevDef[MAX_JOYSTICKS]; | ||
51 | |||
52 | struct joystick_hwdata | ||
53 | { | ||
54 | char name[64]; | ||
55 | /* Uint8 id;*/ | ||
56 | ISpElementReference refs[kMaxReferences]; | ||
57 | /* gonna need some sort of mapping info */ | ||
58 | }; | ||
59 | |||
60 | |||
61 | /* Function to scan the system for joysticks. | ||
62 | * Joystick 0 should be the system default joystick. | ||
63 | * This function should return the number of available joysticks, or -1 | ||
64 | * on an unrecoverable fatal error. | ||
65 | */ | ||
66 | int SDL_SYS_JoystickInit(void) | ||
67 | { | ||
68 | static ISpDeviceClass classes[4] = { | ||
69 | kISpDeviceClass_Joystick, | ||
70 | #if kISpDeviceClass_Gamepad | ||
71 | kISpDeviceClass_Gamepad, | ||
72 | #endif | ||
73 | kISpDeviceClass_Wheel, | ||
74 | 0 | ||
75 | }; | ||
76 | OSErr err; | ||
77 | int i; | ||
78 | UInt32 count, numJoysticks; | ||
79 | |||
80 | if ( (Ptr)0 == (Ptr)ISpStartup ) { | ||
81 | SDL_SetError("InputSprocket not installed"); | ||
82 | return -1; // InputSprocket not installed | ||
83 | } | ||
84 | |||
85 | if( (Ptr)0 == (Ptr)ISpGetVersion ) { | ||
86 | SDL_SetError("InputSprocket not version 1.1 or newer"); | ||
87 | return -1; // old version of ISp (not at least 1.1) | ||
88 | } | ||
89 | |||
90 | ISpStartup(); | ||
91 | |||
92 | /* Get all the joysticks */ | ||
93 | numJoysticks = 0; | ||
94 | for ( i=0; classes[i]; ++i ) { | ||
95 | count = 0; | ||
96 | err = ISpDevices_ExtractByClass( | ||
97 | classes[i], | ||
98 | MAX_JOYSTICKS-numJoysticks, | ||
99 | &count, | ||
100 | &SYS_Joysticks[numJoysticks]); | ||
101 | numJoysticks += count; | ||
102 | } | ||
103 | |||
104 | for(i = 0; i < numJoysticks; i++) | ||
105 | { | ||
106 | ISpDevice_GetDefinition( | ||
107 | SYS_Joysticks[i], sizeof(ISpDeviceDefinition), | ||
108 | &SYS_DevDef[i]); | ||
109 | |||
110 | err = ISpElementList_New( | ||
111 | 0, NULL, | ||
112 | &SYS_Elements[i], 0); | ||
113 | |||
114 | if (err) { | ||
115 | SDL_OutOfMemory(); | ||
116 | return -1; | ||
117 | } | ||
118 | |||
119 | ISpDevice_GetElementList( | ||
120 | SYS_Joysticks[i], | ||
121 | &SYS_Elements[i]); | ||
122 | } | ||
123 | |||
124 | ISpDevices_Deactivate(numJoysticks, SYS_Joysticks); | ||
125 | |||
126 | return numJoysticks; | ||
127 | } | ||
128 | |||
129 | /* Function to get the device-dependent name of a joystick */ | ||
130 | const char *SDL_SYS_JoystickName(int index) | ||
131 | { | ||
132 | static char name[64]; | ||
133 | int len; | ||
134 | |||
135 | /* convert pascal string to c-string */ | ||
136 | len = SYS_DevDef[index].deviceName[0]; | ||
137 | if ( len >= sizeof(name) ) { | ||
138 | len = (sizeof(name) - 1); | ||
139 | } | ||
140 | SDL_memcpy(name, &SYS_DevDef[index].deviceName[1], len); | ||
141 | name[len] = '\0'; | ||
142 | |||
143 | return name; | ||
144 | } | ||
145 | |||
146 | /* Function to open a joystick for use. | ||
147 | The joystick to open is specified by the index field of the joystick. | ||
148 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
149 | It returns 0, or -1 if there is an error. | ||
150 | */ | ||
151 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
152 | { | ||
153 | int index; | ||
154 | UInt32 count, gotCount, count2; | ||
155 | long numAxis, numButtons, numHats, numBalls; | ||
156 | |||
157 | count = kMaxReferences; | ||
158 | count2 = 0; | ||
159 | numAxis = numButtons = numHats = numBalls = 0; | ||
160 | |||
161 | index = joystick->index; | ||
162 | |||
163 | /* allocate memory for system specific hardware data */ | ||
164 | joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); | ||
165 | if (joystick->hwdata == NULL) | ||
166 | { | ||
167 | SDL_OutOfMemory(); | ||
168 | return(-1); | ||
169 | } | ||
170 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | ||
171 | SDL_strlcpy(joystick->hwdata->name, SDL_SYS_JoystickName(index), SDL_arraysize(joystick->hwdata->name)); | ||
172 | joystick->name = joystick->hwdata->name; | ||
173 | |||
174 | ISpElementList_ExtractByKind( | ||
175 | SYS_Elements[index], | ||
176 | kISpElementKind_Axis, | ||
177 | count, | ||
178 | &gotCount, | ||
179 | joystick->hwdata->refs); | ||
180 | |||
181 | numAxis = gotCount; | ||
182 | count -= gotCount; | ||
183 | count2 += gotCount; | ||
184 | |||
185 | ISpElementList_ExtractByKind( | ||
186 | SYS_Elements[index], | ||
187 | kISpElementKind_DPad, | ||
188 | count, | ||
189 | &gotCount, | ||
190 | &(joystick->hwdata->refs[count2])); | ||
191 | |||
192 | numHats = gotCount; | ||
193 | count -= gotCount; | ||
194 | count2 += gotCount; | ||
195 | |||
196 | ISpElementList_ExtractByKind( | ||
197 | SYS_Elements[index], | ||
198 | kISpElementKind_Button, | ||
199 | count, | ||
200 | &gotCount, | ||
201 | &(joystick->hwdata->refs[count2])); | ||
202 | |||
203 | numButtons = gotCount; | ||
204 | count -= gotCount; | ||
205 | count2 += gotCount; | ||
206 | |||
207 | joystick->naxes = numAxis; | ||
208 | joystick->nhats = numHats; | ||
209 | joystick->nballs = numBalls; | ||
210 | joystick->nbuttons = numButtons; | ||
211 | |||
212 | ISpDevices_Activate( | ||
213 | 1, | ||
214 | &SYS_Joysticks[index]); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* Function to update the state of a joystick - called as a device poll. | ||
220 | * This function shouldn't update the joystick structure directly, | ||
221 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
222 | * and update joystick device state. | ||
223 | */ | ||
224 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
225 | { | ||
226 | int i, j; | ||
227 | ISpAxisData a; | ||
228 | ISpDPadData b; | ||
229 | //ISpDeltaData c; | ||
230 | ISpButtonData d; | ||
231 | |||
232 | for(i = 0, j = 0; i < joystick->naxes; i++, j++) | ||
233 | { | ||
234 | Sint16 value; | ||
235 | |||
236 | ISpElement_GetSimpleState( | ||
237 | joystick->hwdata->refs[j], | ||
238 | &a); | ||
239 | value = (ISpSymmetricAxisToFloat(a)* 32767.0); | ||
240 | if ( value != joystick->axes[i] ) { | ||
241 | SDL_PrivateJoystickAxis(joystick, i, value); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | for(i = 0; i < joystick->nhats; i++, j++) | ||
246 | { | ||
247 | Uint8 pos; | ||
248 | |||
249 | ISpElement_GetSimpleState( | ||
250 | joystick->hwdata->refs[j], | ||
251 | &b); | ||
252 | switch(b) { | ||
253 | case kISpPadIdle: | ||
254 | pos = SDL_HAT_CENTERED; | ||
255 | break; | ||
256 | case kISpPadLeft: | ||
257 | pos = SDL_HAT_LEFT; | ||
258 | break; | ||
259 | case kISpPadUpLeft: | ||
260 | pos = SDL_HAT_LEFTUP; | ||
261 | break; | ||
262 | case kISpPadUp: | ||
263 | pos = SDL_HAT_UP; | ||
264 | break; | ||
265 | case kISpPadUpRight: | ||
266 | pos = SDL_HAT_RIGHTUP; | ||
267 | break; | ||
268 | case kISpPadRight: | ||
269 | pos = SDL_HAT_RIGHT; | ||
270 | break; | ||
271 | case kISpPadDownRight: | ||
272 | pos = SDL_HAT_RIGHTDOWN; | ||
273 | break; | ||
274 | case kISpPadDown: | ||
275 | pos = SDL_HAT_DOWN; | ||
276 | break; | ||
277 | case kISpPadDownLeft: | ||
278 | pos = SDL_HAT_LEFTDOWN; | ||
279 | break; | ||
280 | } | ||
281 | if ( pos != joystick->hats[i] ) { | ||
282 | SDL_PrivateJoystickHat(joystick, i, pos); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | for(i = 0; i < joystick->nballs; i++, j++) | ||
287 | { | ||
288 | /* ignore balls right now */ | ||
289 | } | ||
290 | |||
291 | for(i = 0; i < joystick->nbuttons; i++, j++) | ||
292 | { | ||
293 | ISpElement_GetSimpleState( | ||
294 | joystick->hwdata->refs[j], | ||
295 | &d); | ||
296 | if ( d != joystick->buttons[i] ) { | ||
297 | SDL_PrivateJoystickButton(joystick, i, d); | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | /* Function to close a joystick after use */ | ||
303 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
304 | { | ||
305 | int index; | ||
306 | |||
307 | index = joystick->index; | ||
308 | |||
309 | ISpDevices_Deactivate( | ||
310 | 1, | ||
311 | &SYS_Joysticks[index]); | ||
312 | } | ||
313 | |||
314 | /* Function to perform any system-specific joystick related cleanup */ | ||
315 | void SDL_SYS_JoystickQuit(void) | ||
316 | { | ||
317 | ISpShutdown(); | ||
318 | } | ||
319 | |||
320 | #endif /* SDL_JOYSTICK_MACOS */ | ||
diff --git a/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c new file mode 100644 index 0000000000..9a36152927 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c | |||
@@ -0,0 +1,826 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_MINT | ||
25 | |||
26 | /* | ||
27 | * Atari Joystick/Joypad drivers | ||
28 | * | ||
29 | * Patrice Mandin | ||
30 | */ | ||
31 | |||
32 | #include <mint/cookie.h> | ||
33 | #include <mint/osbind.h> | ||
34 | |||
35 | #include "SDL_events.h" | ||
36 | #include "../SDL_sysjoystick.h" | ||
37 | #include "../SDL_joystick_c.h" | ||
38 | |||
39 | #include "../../video/ataricommon/SDL_ikbdinterrupt_s.h" | ||
40 | #include "../../video/ataricommon/SDL_xbiosevents_c.h" | ||
41 | #include "../../video/ataricommon/SDL_xbiosinterrupt_s.h" | ||
42 | |||
43 | /*--- Const ---*/ | ||
44 | |||
45 | /* We can have: | ||
46 | 1 joystick on IKBD port 1, read via hardware I/O | ||
47 | or same joystick on IKBD port 1, read via xbios | ||
48 | 1 joypad on port A (up to 4 with teamtap) | ||
49 | or 2 joysticks on joypad port A | ||
50 | or 1 analog paddle on joypad port A | ||
51 | or 1 lightpen on joypad port A | ||
52 | 1 joypad on port B (up to 4 with teamtap) | ||
53 | or 2 joysticks on joypad port B | ||
54 | or 1 analog paddle on joypad port B | ||
55 | 2 joysticks on parallel port | ||
56 | */ | ||
57 | |||
58 | enum { | ||
59 | IKBD_JOY1=0, | ||
60 | XBIOS_JOY1, | ||
61 | PORTA_PAD0, | ||
62 | PORTA_PAD1, | ||
63 | PORTA_PAD2, | ||
64 | PORTA_PAD3, | ||
65 | PORTB_PAD0, | ||
66 | PORTB_PAD1, | ||
67 | PORTB_PAD2, | ||
68 | PORTB_PAD3, | ||
69 | PORTA_JOY0, | ||
70 | PORTA_JOY1, | ||
71 | PORTB_JOY0, | ||
72 | PORTB_JOY1, | ||
73 | PORTA_LP, | ||
74 | PORTA_ANPAD, | ||
75 | PORTB_ANPAD, | ||
76 | #if 0 | ||
77 | PARA_JOY0, | ||
78 | PARA_JOY1, | ||
79 | #endif | ||
80 | MAX_JOYSTICKS | ||
81 | }; | ||
82 | |||
83 | enum { | ||
84 | MCH_ST=0, | ||
85 | MCH_STE, | ||
86 | MCH_TT, | ||
87 | MCH_F30, | ||
88 | MCH_CLONE, | ||
89 | MCH_ARANYM | ||
90 | }; | ||
91 | |||
92 | /* Joypad buttons | ||
93 | * Procontroller note: | ||
94 | * L,R are connected to 4,6 | ||
95 | * X,Y,Z are connected to 7,8,9 | ||
96 | */ | ||
97 | |||
98 | enum { | ||
99 | JP_UP=0, JP_DOWN, JP_LEFT, JP_RIGHT, | ||
100 | JP_KPMULT, JP_KP7, JP_KP4, JP_KP1, | ||
101 | JP_KP0, JP_KP8, JP_KP5, JP_KP2, | ||
102 | JP_KPNUM, JP_KP9, JP_KP6, JP_KP3, | ||
103 | JP_PAUSE, JP_FIRE0, JP_UNDEF0, JP_FIRE1, | ||
104 | JP_UNDEF1, JP_FIRE2, JP_UNDEF2, JP_OPTION | ||
105 | }; | ||
106 | |||
107 | #define JP_NUM_BUTTONS 17 | ||
108 | |||
109 | #define PORT_JS_RIGHT (1<<0) | ||
110 | #define PORT_JS_LEFT (1<<1) | ||
111 | #define PORT_JS_DOWN (1<<2) | ||
112 | #define PORT_JS_UP (1<<3) | ||
113 | #define PORT_JS_FIRE (1<<4) | ||
114 | |||
115 | enum { | ||
116 | TEAMTAP_MAYBE=0, | ||
117 | TEAMTAP_YES, | ||
118 | TEAMTAP_NO | ||
119 | }; | ||
120 | |||
121 | /* Teamtap detection values */ | ||
122 | static const Uint32 teamtap_ghosts[20][4]={ | ||
123 | {1<<JP_UP, /* for this event on joypad 0, port X */ | ||
124 | (1<<JP_UP)|(1<<JP_KP0), /* we get this on joypad 1 */ | ||
125 | (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KP0), /* this on joypad 2 */ | ||
126 | (1<<JP_KPMULT)|(1<<JP_KP0)}, /* this on joypad 3 */ | ||
127 | {1<<JP_DOWN, | ||
128 | (1<<JP_DOWN)|(1<<JP_KP8), | ||
129 | (1<<JP_DOWN)|(1<<JP_KP9)|(1<<JP_KP8), | ||
130 | (1<<JP_KP7)|(1<<JP_KP8)}, | ||
131 | {1<<JP_LEFT, | ||
132 | (1<<JP_LEFT)|(1<<JP_KP5), | ||
133 | (1<<JP_LEFT)|(1<<JP_KP6)|(1<<JP_KP5), | ||
134 | (1<<JP_KP4)|(1<<JP_KP5)}, | ||
135 | {1<<JP_RIGHT, | ||
136 | (1<<JP_RIGHT)|(1<<JP_KP2), | ||
137 | (1<<JP_RIGHT)|(1<<JP_KP3)|(1<<JP_KP2), | ||
138 | (1<<JP_KP1)|(1<<JP_KP2)}, | ||
139 | {1<<JP_OPTION, | ||
140 | (1<<JP_OPTION)|(1<<JP_FIRE1)|(1<<JP_FIRE2), | ||
141 | (1<<JP_FIRE0)|(1<<JP_FIRE1)|(1<<JP_FIRE2), | ||
142 | 0}, | ||
143 | {1<<JP_FIRE0, | ||
144 | (1<<JP_FIRE2)|(1<<JP_FIRE0), | ||
145 | (1<<JP_FIRE0)|(1<<JP_OPTION)|(1<<JP_FIRE2), | ||
146 | (1<<JP_FIRE1)|(1<<JP_FIRE2)}, | ||
147 | {1<<JP_FIRE1, | ||
148 | (1<<JP_FIRE0), | ||
149 | (1<<JP_OPTION)|(1<<JP_FIRE0)|(1<<JP_FIRE1), | ||
150 | (1<<JP_FIRE0)|(1<<JP_FIRE2)}, | ||
151 | {1<<JP_FIRE2, | ||
152 | (1<<JP_OPTION)|(1<<JP_FIRE0)|(1<<JP_FIRE1)|(1<<JP_FIRE2), | ||
153 | (1<<JP_OPTION), | ||
154 | (1<<JP_FIRE0)|(1<<JP_FIRE1)}, | ||
155 | {1<<JP_KP1, | ||
156 | (1<<JP_RIGHT)|(1<<JP_KP1), | ||
157 | (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP3), | ||
158 | (1<<JP_RIGHT)|(1<<JP_KP2)}, | ||
159 | {1<<JP_KP2, | ||
160 | (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2)|(1<<JP_KP3), | ||
161 | (1<<JP_KP3), | ||
162 | (1<<JP_RIGHT)|(1<<JP_KP1)}, | ||
163 | {1<<JP_KP3, | ||
164 | (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2)|(1<<JP_KP3), | ||
165 | (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2), | ||
166 | 0}, | ||
167 | {1<<JP_KP4, | ||
168 | (1<<JP_LEFT)|(1<<JP_KP4), | ||
169 | (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP6), | ||
170 | (1<<JP_LEFT)|(1<<JP_KP5)}, | ||
171 | {1<<JP_KP5, | ||
172 | (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5)|(1<<JP_KP6), | ||
173 | (1<<JP_KP6), | ||
174 | (1<<JP_LEFT)|(1<<JP_KP4)}, | ||
175 | {1<<JP_KP6, | ||
176 | (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5)|(1<<JP_KP6), | ||
177 | (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5), | ||
178 | 0}, | ||
179 | {1<<JP_KP7, | ||
180 | (1<<JP_DOWN)|(1<<JP_KP7), | ||
181 | (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP9), | ||
182 | (1<<JP_DOWN)|(1<<JP_KP8)}, | ||
183 | {1<<JP_KP8, | ||
184 | (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8)|(1<<JP_KP9), | ||
185 | (1<<JP_KP9), | ||
186 | (1<<JP_DOWN)|(1<<JP_KP7)}, | ||
187 | {1<<JP_KP9, | ||
188 | (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8)|(1<<JP_KP9), | ||
189 | (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8), | ||
190 | 0}, | ||
191 | {1<<JP_KPMULT, | ||
192 | (1<<JP_UP)|(1<<JP_KPMULT), | ||
193 | (1<<JP_UP)|(1<<JP_KPNUM), | ||
194 | (1<<JP_UP)|(1<<JP_KP0)}, | ||
195 | {1<<JP_KP0, | ||
196 | (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KPMULT)|(1<<JP_KP0), | ||
197 | 1<<JP_KPNUM, | ||
198 | (1<<JP_UP)|(1<<JP_KPMULT)}, | ||
199 | {1<<JP_KPNUM, | ||
200 | (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KPMULT)|(1<<JP_KP0), | ||
201 | (1<<JP_UP)|(1<<JP_KPMULT)|(1<<JP_KP0), | ||
202 | 0}, | ||
203 | }; | ||
204 | |||
205 | /*--- Types ---*/ | ||
206 | |||
207 | typedef struct { | ||
208 | SDL_bool enabled; | ||
209 | char *name; | ||
210 | Uint32 prevstate; | ||
211 | } atarijoy_t; | ||
212 | |||
213 | /*--- Variables ---*/ | ||
214 | |||
215 | static atarijoy_t atarijoysticks[MAX_JOYSTICKS]={ | ||
216 | {SDL_FALSE,"IKBD joystick port 1",0}, | ||
217 | {SDL_FALSE,"Xbios joystick port 1",0}, | ||
218 | {SDL_FALSE,"Joypad 0 port A",0}, | ||
219 | {SDL_FALSE,"Joypad 1 port A",0}, | ||
220 | {SDL_FALSE,"Joypad 2 port A",0}, | ||
221 | {SDL_FALSE,"Joypad 3 port A",0}, | ||
222 | {SDL_FALSE,"Joypad 0 port B",0}, | ||
223 | {SDL_FALSE,"Joypad 1 port B",0}, | ||
224 | {SDL_FALSE,"Joypad 2 port B",0}, | ||
225 | {SDL_FALSE,"Joypad 3 port B",0}, | ||
226 | {SDL_FALSE,"Joystick 0 port A",0}, | ||
227 | {SDL_FALSE,"Joystick 1 port A",0}, | ||
228 | {SDL_FALSE,"Joystick 0 port B",0}, | ||
229 | {SDL_FALSE,"Joystick 1 port B",0}, | ||
230 | {SDL_FALSE,"Lightpen port A",0}, | ||
231 | {SDL_FALSE,"Analog paddle port A",0}, | ||
232 | {SDL_FALSE,"Analog paddle port B",0} | ||
233 | #if 0 | ||
234 | ,{SDL_FALSE,"Joystick 0 parallel port",0}, | ||
235 | {SDL_FALSE,"Joystick 1 parallel port",0} | ||
236 | #endif | ||
237 | }; | ||
238 | |||
239 | static const int jp_buttons[JP_NUM_BUTTONS]={ | ||
240 | JP_FIRE0, JP_FIRE1, JP_FIRE2, JP_PAUSE, | ||
241 | JP_OPTION, JP_KPMULT, JP_KPNUM, JP_KP0, | ||
242 | JP_KP1, JP_KP2, JP_KP3, JP_KP4, | ||
243 | JP_KP5, JP_KP6, JP_KP7, JP_KP8, | ||
244 | JP_KP9 | ||
245 | }; | ||
246 | |||
247 | static SDL_bool joypad_ports_enabled=SDL_FALSE; | ||
248 | static int has_teamtap[2]={TEAMTAP_MAYBE,TEAMTAP_MAYBE}; | ||
249 | |||
250 | /* Updated joypad ports */ | ||
251 | static Uint16 jp_paddles[4]; | ||
252 | static Uint16 jp_lightpens[2]; | ||
253 | static Uint16 jp_directions; | ||
254 | static Uint16 jp_fires; | ||
255 | static Uint32 jp_joypads[8]; | ||
256 | |||
257 | /*--- Functions prototypes ---*/ | ||
258 | |||
259 | static int GetEnabledAtariJoystick(int index); | ||
260 | static void UpdateJoypads(void); | ||
261 | |||
262 | /*--- Functions ---*/ | ||
263 | |||
264 | int SDL_SYS_JoystickInit(void) | ||
265 | { | ||
266 | int i; | ||
267 | long cookie_mch; | ||
268 | const char *envr=SDL_getenv("SDL_JOYSTICK_ATARI"); | ||
269 | |||
270 | #define TEST_JOY_ENABLED(env,idstring,num) \ | ||
271 | if (SDL_strstr(env,idstring"-off")) { \ | ||
272 | atarijoysticks[num].enabled=SDL_FALSE; \ | ||
273 | } \ | ||
274 | if (SDL_strstr(env,idstring"-on")) { \ | ||
275 | atarijoysticks[num].enabled=SDL_TRUE; \ | ||
276 | } | ||
277 | |||
278 | /* Cookie _MCH present ? if not, assume ST machine */ | ||
279 | if (Getcookie(C__MCH, &cookie_mch) != C_FOUND) { | ||
280 | cookie_mch = MCH_ST << 16; | ||
281 | } | ||
282 | |||
283 | /* Enable some default joysticks */ | ||
284 | if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || | ||
285 | (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16) || | ||
286 | (cookie_mch == MCH_ARANYM<<16)) | ||
287 | { | ||
288 | atarijoysticks[IKBD_JOY1].enabled=(SDL_AtariIkbd_enabled!=0); | ||
289 | } | ||
290 | if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16) || | ||
291 | (cookie_mch == MCH_ARANYM<<16)) | ||
292 | { | ||
293 | atarijoysticks[PORTA_PAD0].enabled = | ||
294 | atarijoysticks[PORTA_PAD1].enabled = | ||
295 | atarijoysticks[PORTA_PAD2].enabled = | ||
296 | atarijoysticks[PORTA_PAD3].enabled = | ||
297 | atarijoysticks[PORTB_PAD0].enabled = | ||
298 | atarijoysticks[PORTB_PAD1].enabled = | ||
299 | atarijoysticks[PORTB_PAD2].enabled = | ||
300 | atarijoysticks[PORTB_PAD3].enabled = SDL_TRUE; | ||
301 | } | ||
302 | if (!atarijoysticks[IKBD_JOY1].enabled) { | ||
303 | atarijoysticks[XBIOS_JOY1].enabled=(SDL_AtariXbios_enabled!=0); | ||
304 | } | ||
305 | |||
306 | /* Read environment for joysticks to enable */ | ||
307 | if (envr) { | ||
308 | /* IKBD on any Atari, maybe clones */ | ||
309 | if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || | ||
310 | (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16) || | ||
311 | (cookie_mch == MCH_ARANYM<<16)) { | ||
312 | if (SDL_AtariIkbd_enabled!=0) { | ||
313 | TEST_JOY_ENABLED(envr, "ikbd-joy1", IKBD_JOY1); | ||
314 | } | ||
315 | } | ||
316 | /* Joypads ports on STE, Falcon and maybe others */ | ||
317 | if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16) || | ||
318 | (cookie_mch == MCH_ARANYM<<16)) { | ||
319 | TEST_JOY_ENABLED(envr, "porta-pad", PORTA_PAD0); | ||
320 | if (!atarijoysticks[PORTA_PAD0].enabled) { | ||
321 | TEST_JOY_ENABLED(envr, "porta-joy0", PORTA_JOY0); | ||
322 | TEST_JOY_ENABLED(envr, "porta-joy1", PORTA_JOY1); | ||
323 | if (!(atarijoysticks[PORTA_JOY0].enabled) && !(atarijoysticks[PORTA_JOY1].enabled)) { | ||
324 | TEST_JOY_ENABLED(envr, "porta-lp", PORTA_LP); | ||
325 | if (!atarijoysticks[PORTA_LP].enabled) { | ||
326 | TEST_JOY_ENABLED(envr, "porta-anpad", PORTA_ANPAD); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | TEST_JOY_ENABLED(envr, "portb-pad", PORTB_PAD0); | ||
332 | if (!atarijoysticks[PORTB_PAD0].enabled) { | ||
333 | TEST_JOY_ENABLED(envr, "portb-joy0", PORTB_JOY0); | ||
334 | TEST_JOY_ENABLED(envr, "portb-joy1", PORTB_JOY1); | ||
335 | if (!(atarijoysticks[PORTB_JOY0].enabled) && !(atarijoysticks[PORTB_JOY1].enabled)) { | ||
336 | TEST_JOY_ENABLED(envr, "portb-anpad", PORTB_ANPAD); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | if (!atarijoysticks[IKBD_JOY1].enabled) { | ||
342 | if (SDL_AtariXbios_enabled!=0) { | ||
343 | TEST_JOY_ENABLED(envr, "xbios-joy1", XBIOS_JOY1); | ||
344 | } | ||
345 | } | ||
346 | #if 0 | ||
347 | /* Parallel port on any Atari, maybe clones */ | ||
348 | if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || | ||
349 | (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) { | ||
350 | TEST_JOY_ENABLED(envr, "para-joy0", PARA_JOY0); | ||
351 | TEST_JOY_ENABLED(envr, "para-joy1", PARA_JOY1); | ||
352 | } | ||
353 | #endif | ||
354 | } | ||
355 | |||
356 | /* Need to update joypad ports ? */ | ||
357 | joypad_ports_enabled=SDL_FALSE; | ||
358 | for (i=PORTA_PAD0;i<=PORTB_ANPAD;i++) { | ||
359 | if (atarijoysticks[i].enabled) { | ||
360 | joypad_ports_enabled=SDL_TRUE; | ||
361 | break; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | SDL_numjoysticks = 0; | ||
366 | for (i=0;i<MAX_JOYSTICKS;i++) { | ||
367 | if (atarijoysticks[i].enabled) { | ||
368 | ++SDL_numjoysticks; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | return(SDL_numjoysticks); | ||
373 | } | ||
374 | |||
375 | static int GetEnabledAtariJoystick(int index) | ||
376 | { | ||
377 | int i,j; | ||
378 | |||
379 | /* Return the nth'index' enabled atari joystick */ | ||
380 | j=0; | ||
381 | for (i=0;i<MAX_JOYSTICKS;i++) { | ||
382 | if (!atarijoysticks[i].enabled) { | ||
383 | continue; | ||
384 | } | ||
385 | |||
386 | if (j==index) { | ||
387 | break; | ||
388 | } | ||
389 | |||
390 | ++j; | ||
391 | } | ||
392 | if (i==MAX_JOYSTICKS) | ||
393 | return -1; | ||
394 | |||
395 | return i; | ||
396 | } | ||
397 | |||
398 | const char *SDL_SYS_JoystickName(int index) | ||
399 | { | ||
400 | int numjoystick; | ||
401 | |||
402 | numjoystick=GetEnabledAtariJoystick(index); | ||
403 | if (numjoystick==-1) | ||
404 | return NULL; | ||
405 | |||
406 | return(atarijoysticks[numjoystick].name); | ||
407 | } | ||
408 | |||
409 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
410 | { | ||
411 | int numjoystick; | ||
412 | |||
413 | numjoystick=GetEnabledAtariJoystick(joystick->index); | ||
414 | if (numjoystick==-1) | ||
415 | return -1; | ||
416 | |||
417 | joystick->naxes=0; | ||
418 | joystick->nhats=0; | ||
419 | joystick->nballs=0; | ||
420 | |||
421 | switch(numjoystick) { | ||
422 | case PORTA_PAD0: | ||
423 | case PORTA_PAD1: | ||
424 | case PORTA_PAD2: | ||
425 | case PORTA_PAD3: | ||
426 | case PORTB_PAD0: | ||
427 | case PORTB_PAD1: | ||
428 | case PORTB_PAD2: | ||
429 | case PORTB_PAD3: | ||
430 | joystick->nhats=1; | ||
431 | joystick->nbuttons=JP_NUM_BUTTONS; | ||
432 | break; | ||
433 | case PORTA_LP: | ||
434 | case PORTA_ANPAD: | ||
435 | case PORTB_ANPAD: | ||
436 | joystick->naxes=2; | ||
437 | joystick->nbuttons=2; | ||
438 | break; | ||
439 | default: | ||
440 | joystick->nhats=1; | ||
441 | joystick->nbuttons=1; | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | return(0); | ||
446 | } | ||
447 | |||
448 | /* Detect Teamtap using ghost events */ | ||
449 | static void detect_teamtap(int num_port) | ||
450 | { | ||
451 | int i,j; | ||
452 | |||
453 | /* Check if joypad 1,2,3 triggered but not 0 */ | ||
454 | for (i=1; i<4; i++) { | ||
455 | if (jp_joypads[num_port*4+i] && (jp_joypads[num_port*4]==0)) { | ||
456 | has_teamtap[num_port] = TEAMTAP_YES; | ||
457 | return; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | /* Check if joypad 0 on a given port triggered ghost events for | ||
462 | * other joypads | ||
463 | */ | ||
464 | for (i=0; i<20; i++) { | ||
465 | int with_teamtap=1; | ||
466 | |||
467 | if (jp_joypads[num_port*4]!=teamtap_ghosts[i][0]) | ||
468 | continue; | ||
469 | |||
470 | /* If any button on first joypad pressed, check other pads */ | ||
471 | for (j=1; j<4; j++) { | ||
472 | if ((jp_joypads[num_port*4+j] & teamtap_ghosts[i][j]) | ||
473 | ==teamtap_ghosts[i][j]) | ||
474 | { | ||
475 | with_teamtap = 0; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | has_teamtap[num_port] = (with_teamtap ? TEAMTAP_YES : TEAMTAP_NO); | ||
480 | break; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
485 | { | ||
486 | int numjoystick; | ||
487 | Uint8 hatstate; | ||
488 | Uint32 curstate,prevstate; | ||
489 | |||
490 | numjoystick=GetEnabledAtariJoystick(joystick->index); | ||
491 | if (numjoystick==-1) | ||
492 | return; | ||
493 | |||
494 | prevstate = atarijoysticks[numjoystick].prevstate; | ||
495 | |||
496 | if (joypad_ports_enabled) { | ||
497 | Supexec(UpdateJoypads); | ||
498 | } | ||
499 | |||
500 | switch (numjoystick) { | ||
501 | case IKBD_JOY1: | ||
502 | case XBIOS_JOY1: | ||
503 | { | ||
504 | curstate = 0; | ||
505 | |||
506 | if (numjoystick==IKBD_JOY1) { | ||
507 | curstate = SDL_AtariIkbd_joystick & 0xff; | ||
508 | } | ||
509 | if (numjoystick==XBIOS_JOY1) { | ||
510 | curstate = SDL_AtariXbios_joystick & 0xff; | ||
511 | } | ||
512 | |||
513 | if (curstate != prevstate) { | ||
514 | hatstate = SDL_HAT_CENTERED; | ||
515 | if (curstate & IKBD_JOY_LEFT) { | ||
516 | hatstate |= SDL_HAT_LEFT; | ||
517 | } | ||
518 | if (curstate & IKBD_JOY_RIGHT) { | ||
519 | hatstate |= SDL_HAT_RIGHT; | ||
520 | } | ||
521 | if (curstate & IKBD_JOY_UP) { | ||
522 | hatstate |= SDL_HAT_UP; | ||
523 | } | ||
524 | if (curstate & IKBD_JOY_DOWN) { | ||
525 | hatstate |= SDL_HAT_DOWN; | ||
526 | } | ||
527 | SDL_PrivateJoystickHat(joystick, 0, hatstate); | ||
528 | |||
529 | /* Button */ | ||
530 | if ((curstate & IKBD_JOY_FIRE) && !(prevstate & IKBD_JOY_FIRE)) { | ||
531 | SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); | ||
532 | } | ||
533 | if (!(curstate & IKBD_JOY_FIRE) && (prevstate & IKBD_JOY_FIRE)) { | ||
534 | SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); | ||
535 | } | ||
536 | } | ||
537 | atarijoysticks[numjoystick].prevstate = curstate; | ||
538 | } | ||
539 | break; | ||
540 | case PORTA_PAD0: | ||
541 | case PORTA_PAD1: | ||
542 | case PORTA_PAD2: | ||
543 | case PORTA_PAD3: | ||
544 | case PORTB_PAD0: | ||
545 | case PORTB_PAD1: | ||
546 | case PORTB_PAD2: | ||
547 | case PORTB_PAD3: | ||
548 | { | ||
549 | int numjoypad,i,numport; | ||
550 | |||
551 | numjoypad = numport = 0; | ||
552 | switch(numjoystick) { | ||
553 | case PORTA_PAD0: | ||
554 | numjoypad = 0; break; | ||
555 | case PORTA_PAD1: | ||
556 | numjoypad = 1; break; | ||
557 | case PORTA_PAD2: | ||
558 | numjoypad = 2; break; | ||
559 | case PORTA_PAD3: | ||
560 | numjoypad = 3; break; | ||
561 | case PORTB_PAD0: | ||
562 | numjoypad = 4; numport = 1; break; | ||
563 | case PORTB_PAD1: | ||
564 | numjoypad = 5; numport = 1; break; | ||
565 | case PORTB_PAD2: | ||
566 | numjoypad = 6; numport = 1; break; | ||
567 | case PORTB_PAD3: | ||
568 | numjoypad = 7; numport = 1; break; | ||
569 | } | ||
570 | |||
571 | jp_joypads[numjoypad] &= 0xabffff; | ||
572 | |||
573 | if (has_teamtap[numport]==TEAMTAP_MAYBE) { | ||
574 | detect_teamtap(numport); | ||
575 | } | ||
576 | /* No events for PORTX_PAD[1,2,3] if no teamtap detected */ | ||
577 | if (has_teamtap[numport] == TEAMTAP_NO) { | ||
578 | if ((numjoypad & 3)!=0) { | ||
579 | return; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | curstate=jp_joypads[numjoypad]; | ||
584 | if (curstate!=prevstate) { | ||
585 | hatstate = SDL_HAT_CENTERED; | ||
586 | if (curstate & (1<<JP_LEFT)) { | ||
587 | hatstate |= SDL_HAT_LEFT; | ||
588 | } | ||
589 | if (curstate & (1<<JP_RIGHT)) { | ||
590 | hatstate |= SDL_HAT_RIGHT; | ||
591 | } | ||
592 | if (curstate & (1<<JP_UP)) { | ||
593 | hatstate |= SDL_HAT_UP; | ||
594 | } | ||
595 | if (curstate & (1<<JP_DOWN)) { | ||
596 | hatstate |= SDL_HAT_DOWN; | ||
597 | } | ||
598 | SDL_PrivateJoystickHat(joystick, 0, hatstate); | ||
599 | |||
600 | /* Buttons */ | ||
601 | for (i=0;i<JP_NUM_BUTTONS;i++) { | ||
602 | int button; | ||
603 | |||
604 | button=1<<jp_buttons[i]; | ||
605 | |||
606 | if ((curstate & button) && !(prevstate & button)) { | ||
607 | SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); | ||
608 | } | ||
609 | if (!(curstate & button) && (prevstate & button)) { | ||
610 | SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | atarijoysticks[numjoystick].prevstate = curstate; | ||
615 | } | ||
616 | break; | ||
617 | case PORTA_JOY0: | ||
618 | case PORTA_JOY1: | ||
619 | case PORTB_JOY0: | ||
620 | case PORTB_JOY1: | ||
621 | { | ||
622 | int fire_shift=0,dir_shift=0; | ||
623 | |||
624 | if (numjoystick==PORTA_JOY0) { fire_shift=0; dir_shift=0; } | ||
625 | if (numjoystick==PORTA_JOY1) { fire_shift=1; dir_shift=4; } | ||
626 | if (numjoystick==PORTB_JOY0) { fire_shift=2; dir_shift=8; } | ||
627 | if (numjoystick==PORTB_JOY1) { fire_shift=3; dir_shift=12; } | ||
628 | |||
629 | curstate = (jp_directions>>dir_shift) & 15; | ||
630 | curstate |= ((jp_fires>>fire_shift) & 1)<<4; | ||
631 | |||
632 | if (curstate != prevstate) { | ||
633 | hatstate = SDL_HAT_CENTERED; | ||
634 | if (curstate & PORT_JS_LEFT) { | ||
635 | hatstate |= SDL_HAT_LEFT; | ||
636 | } | ||
637 | if (curstate & PORT_JS_RIGHT) { | ||
638 | hatstate |= SDL_HAT_RIGHT; | ||
639 | } | ||
640 | if (curstate & PORT_JS_UP) { | ||
641 | hatstate |= SDL_HAT_UP; | ||
642 | } | ||
643 | if (curstate & PORT_JS_DOWN) { | ||
644 | hatstate |= SDL_HAT_DOWN; | ||
645 | } | ||
646 | SDL_PrivateJoystickHat(joystick, 0, hatstate); | ||
647 | |||
648 | /* Button */ | ||
649 | if ((curstate & PORT_JS_FIRE) && !(prevstate & PORT_JS_FIRE)) { | ||
650 | SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); | ||
651 | } | ||
652 | if (!(curstate & PORT_JS_FIRE) && (prevstate & PORT_JS_FIRE)) { | ||
653 | SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); | ||
654 | } | ||
655 | } | ||
656 | atarijoysticks[numjoystick].prevstate = curstate; | ||
657 | } | ||
658 | break; | ||
659 | case PORTA_LP: | ||
660 | { | ||
661 | int i; | ||
662 | |||
663 | curstate = jp_lightpens[0]>>1; | ||
664 | curstate |= (jp_lightpens[1]>>1)<<15; | ||
665 | curstate |= (jp_fires & 3)<<30; | ||
666 | |||
667 | if (curstate != prevstate) { | ||
668 | /* X axis */ | ||
669 | SDL_PrivateJoystickAxis(joystick,0,jp_lightpens[0] ^ 0x8000); | ||
670 | /* Y axis */ | ||
671 | SDL_PrivateJoystickAxis(joystick,1,jp_lightpens[1] ^ 0x8000); | ||
672 | /* Buttons */ | ||
673 | for (i=0;i<2;i++) { | ||
674 | int button; | ||
675 | |||
676 | button=1<<(30+i); | ||
677 | |||
678 | if ((curstate & button) && !(prevstate & button)) { | ||
679 | SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); | ||
680 | } | ||
681 | if (!(curstate & button) && (prevstate & button)) { | ||
682 | SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); | ||
683 | } | ||
684 | } | ||
685 | } | ||
686 | atarijoysticks[numjoystick].prevstate = curstate; | ||
687 | } | ||
688 | break; | ||
689 | case PORTA_ANPAD: | ||
690 | case PORTB_ANPAD: | ||
691 | { | ||
692 | int numpaddle, i; | ||
693 | |||
694 | numpaddle=0<<1; | ||
695 | if (numjoystick==PORTB_ANPAD) numpaddle=1<<1; | ||
696 | |||
697 | curstate = jp_paddles[numpaddle]>>1; | ||
698 | curstate |= (jp_paddles[numpaddle+1]>>1)<<15; | ||
699 | curstate |= ((jp_fires>>numpaddle) & 3)<<30; | ||
700 | |||
701 | if (curstate != prevstate) { | ||
702 | /* X axis */ | ||
703 | SDL_PrivateJoystickAxis(joystick,0,jp_paddles[numpaddle] ^ 0x8000); | ||
704 | /* Y axis */ | ||
705 | SDL_PrivateJoystickAxis(joystick,1,jp_paddles[numpaddle+1] ^ 0x8000); | ||
706 | /* Buttons */ | ||
707 | for (i=0;i<2;i++) { | ||
708 | int button; | ||
709 | |||
710 | button=1<<(30+i); | ||
711 | |||
712 | if ((curstate & button) && !(prevstate & button)) { | ||
713 | SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); | ||
714 | } | ||
715 | if (!(curstate & button) && (prevstate & button)) { | ||
716 | SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | atarijoysticks[numjoystick].prevstate = curstate; | ||
721 | } | ||
722 | break; | ||
723 | #if 0 | ||
724 | case PARA_JOY0: | ||
725 | case PARA_JOY1: | ||
726 | break; | ||
727 | #endif | ||
728 | }; | ||
729 | |||
730 | return; | ||
731 | } | ||
732 | |||
733 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
734 | { | ||
735 | return; | ||
736 | } | ||
737 | |||
738 | void SDL_SYS_JoystickQuit(void) | ||
739 | { | ||
740 | SDL_numjoysticks=0; | ||
741 | return; | ||
742 | } | ||
743 | |||
744 | /*--- Joypad I/O read/write interface ---*/ | ||
745 | |||
746 | #define JOYPAD_IO_BASE (0xffff9200) | ||
747 | struct JOYPAD_IO_S { | ||
748 | Uint16 fires; | ||
749 | Uint16 directions; | ||
750 | Uint16 dummy1[6]; | ||
751 | Uint16 paddles[4]; | ||
752 | Uint16 dummy2[4]; | ||
753 | Uint16 lightpens[2]; | ||
754 | }; | ||
755 | #define JOYPAD_IO ((*(volatile struct JOYPAD_IO_S *)JOYPAD_IO_BASE)) | ||
756 | |||
757 | static const Uint16 joypad_masks[8*4]={ | ||
758 | 0xfffe, 0xfffd, 0xfffb, 0xfff7, | ||
759 | 0xfff0, 0xfff1, 0xfff2, 0xfff3, | ||
760 | 0xfff4, 0xfff5, 0xfff6, 0xfff8, | ||
761 | 0xfff9, 0xfffa, 0xfffc, 0xffff, | ||
762 | 0xffef, 0xffdf, 0xffbf, 0xff7f, | ||
763 | 0xff0f, 0xff1f, 0xff2f, 0xff3f, | ||
764 | 0xff4f, 0xff5f, 0xff6f, 0xff8f, | ||
765 | 0xff9f, 0xffaf, 0xffcf, 0xffff | ||
766 | }; | ||
767 | |||
768 | static void UpdateJoypads(void) | ||
769 | { | ||
770 | Uint16 tmp, i, j; | ||
771 | Uint32 cur_fire, cur_dir; | ||
772 | |||
773 | /*--- This function is called in supervisor mode ---*/ | ||
774 | |||
775 | /* Update joysticks */ | ||
776 | jp_fires = (~(JOYPAD_IO.fires)) & 15; | ||
777 | jp_directions = (~(JOYPAD_IO.directions)); | ||
778 | |||
779 | /* Update lightpen */ | ||
780 | tmp = JOYPAD_IO.lightpens[0] & 1023; | ||
781 | jp_lightpens[0] = (tmp<<6) | (tmp>>4); | ||
782 | tmp = JOYPAD_IO.lightpens[1] & 1023; | ||
783 | jp_lightpens[1] = (tmp<<6) | (tmp>>4); | ||
784 | |||
785 | /* Update paddles */ | ||
786 | tmp = (JOYPAD_IO.paddles[0] & 255); | ||
787 | jp_paddles[0] = (tmp<<8) | tmp; | ||
788 | tmp = (JOYPAD_IO.paddles[1] & 255); | ||
789 | jp_paddles[1] = (tmp<<8) | tmp; | ||
790 | tmp = (JOYPAD_IO.paddles[2] & 255); | ||
791 | jp_paddles[2] = (tmp<<8) | tmp; | ||
792 | tmp = (JOYPAD_IO.paddles[3] & 255); | ||
793 | jp_paddles[3] = (tmp<<8) | tmp; | ||
794 | |||
795 | /* Update joypads on teamtap port A */ | ||
796 | for (i=0; i<4; i++) { | ||
797 | jp_joypads[i] = 0; | ||
798 | for (j=0; j<4; j++) { | ||
799 | JOYPAD_IO.directions = joypad_masks[(i*4)+j]; | ||
800 | |||
801 | cur_fire = (~(JOYPAD_IO.fires) & 3)<<16; | ||
802 | cur_dir = (~(JOYPAD_IO.directions)>>8) & 15; | ||
803 | |||
804 | jp_joypads[i] |= cur_fire<<(j*2); | ||
805 | jp_joypads[i] |= cur_dir<<(j*4); | ||
806 | } | ||
807 | } | ||
808 | |||
809 | /* Update joypads on teamtap port B */ | ||
810 | for (i=4; i<8; i++) { | ||
811 | jp_joypads[i] = 0; | ||
812 | for (j=0; j<4; j++) { | ||
813 | JOYPAD_IO.directions = joypad_masks[(i*4)+j]; | ||
814 | |||
815 | cur_fire = (~(JOYPAD_IO.fires) & 0xc)<<14; | ||
816 | cur_dir = (~(JOYPAD_IO.directions)>>12) & 15; | ||
817 | |||
818 | jp_joypads[i] |= cur_fire<<(j*2); | ||
819 | jp_joypads[i] |= cur_dir<<(j*4); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | JOYPAD_IO.directions=0xffff; | ||
824 | } | ||
825 | |||
826 | #endif /* SDL_JOYSTICK_MINT */ | ||
diff --git a/apps/plugins/sdl/src/joystick/nds/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/nds/SDL_sysjoystick.c new file mode 100644 index 0000000000..122f48d863 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/nds/SDL_sysjoystick.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 system specific header for the SDL joystick API */ | ||
25 | #include <nds.h> | ||
26 | //#include <nds/registers_alt.h> | ||
27 | |||
28 | #include "SDL_error.h" | ||
29 | #include "SDL_events.h" | ||
30 | #include "SDL_joystick.h" | ||
31 | #include "../SDL_sysjoystick.h" | ||
32 | #include "../SDL_joystick_c.h" | ||
33 | |||
34 | #include "../../video/nds/SDL_ndsevents_c.h" | ||
35 | |||
36 | /* Function to scan the system for joysticks. | ||
37 | * This function should set SDL_numjoysticks to the number of available | ||
38 | * joysticks. Joystick 0 should be the system default joystick. | ||
39 | * It should return 0, or -1 on an unrecoverable fatal error. | ||
40 | */ | ||
41 | int SDL_SYS_JoystickInit(void) | ||
42 | { | ||
43 | SDL_numjoysticks = 1; | ||
44 | //keysInit(); | ||
45 | |||
46 | return(1); | ||
47 | } | ||
48 | |||
49 | /* Function to get the device-dependent name of a joystick */ | ||
50 | const char *SDL_SYS_JoystickName(int index) | ||
51 | { | ||
52 | if(!index) | ||
53 | return "NDS builtin joypad"; | ||
54 | SDL_SetError("No joystick available with that index"); | ||
55 | return (NULL); | ||
56 | } | ||
57 | |||
58 | /* Function to open a joystick for use. | ||
59 | The joystick to open is specified by the index field of the joystick. | ||
60 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
61 | It returns 0, or -1 if there is an error. | ||
62 | */ | ||
63 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
64 | { | ||
65 | joystick->nbuttons=8; | ||
66 | joystick->nhats=0; | ||
67 | joystick->nballs=0; | ||
68 | joystick->naxes=2; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | |||
73 | /* Function to update the state of a joystick - called as a device poll. | ||
74 | * This function shouldn't update the joystick structure directly, | ||
75 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
76 | * and update joystick device state. | ||
77 | */ | ||
78 | |||
79 | int prevbutton=0; | ||
80 | int prevkey=0; | ||
81 | |||
82 | int dc=0;int ldc=0; | ||
83 | u32 keysd,keysu=0; | ||
84 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
85 | { | ||
86 | //dc=keysd; | ||
87 | //if (dc) | ||
88 | //{ | ||
89 | //fprintf(stderr,"heartbeat= %d\n",REG_VCOUNT); | ||
90 | //swiWaitForVBlank(); | ||
91 | //scanKeys(); | ||
92 | //keysd = keysDown(); | ||
93 | //keysu = keysUp(); | ||
94 | //ldc=keysd; | ||
95 | |||
96 | //} | ||
97 | /*if (prevkey && prevbutton) | ||
98 | { | ||
99 | scanKeys(); | ||
100 | } | ||
101 | */ | ||
102 | |||
103 | //scanKeys(); | ||
104 | keysd = keysDown(); | ||
105 | keysu = keysUp(); | ||
106 | |||
107 | |||
108 | short ax=0,v=0,h=0; | ||
109 | if((keysd&KEY_UP)) {ax=1;v=-10;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=KEY_UP;}//fprintf(stderr,"KEY_UP\n");} | ||
110 | if((keysd&KEY_DOWN)) {ax=1;v=10;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=KEY_DOWN;}//fprintf(stderr,"KEY_DOWN\n");} | ||
111 | if((keysd&KEY_LEFT)) {ax=0;h=-10;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=KEY_LEFT;}//fprintf(stderr,"KEY_LEFT\n");} | ||
112 | if((keysd&KEY_RIGHT)) {ax=0;h=10;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=KEY_RIGHT;}//fprintf(stderr,"KEY_RIGHT\n");} | ||
113 | |||
114 | if((keysu&KEY_UP)) {ax=1;v=0;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=0;}//fprintf(stderr,"KEY_UP\n");} | ||
115 | if((keysu&KEY_DOWN)) {ax=1;v=0;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=0;}//fprintf(stderr,"KEY_DOWN\n");} | ||
116 | if((keysu&KEY_LEFT)) {ax=0;h=0;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=0;}//fprintf(stderr,"KEY_LEFT\n");} | ||
117 | if((keysu&KEY_RIGHT)) {ax=0;h=0;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=0;}//fprintf(stderr,"KEY_RIGHT\n");} | ||
118 | |||
119 | if((keysd&KEY_A)) {SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED);prevbutton=KEY_A;} | ||
120 | if((keysd&KEY_B)) {SDL_PrivateJoystickButton(joystick,1,SDL_PRESSED);prevbutton=KEY_B;} | ||
121 | if((keysd&KEY_X)) {SDL_PrivateJoystickButton(joystick,2,SDL_PRESSED);prevbutton=KEY_X;} | ||
122 | if((keysd&KEY_Y)) {SDL_PrivateJoystickButton(joystick,3,SDL_PRESSED);prevbutton=KEY_Y;} | ||
123 | if((keysd&KEY_SELECT)) {SDL_PrivateJoystickButton(joystick,6,SDL_PRESSED);prevbutton=KEY_SELECT;} | ||
124 | if((keysd&KEY_START)) {SDL_PrivateJoystickButton(joystick,7,SDL_PRESSED);prevbutton=KEY_START;} | ||
125 | if((keysd&KEY_L)) {SDL_PrivateJoystickButton(joystick,4,SDL_PRESSED);prevbutton=KEY_L;} | ||
126 | if((keysd&KEY_R)) {SDL_PrivateJoystickButton(joystick,5,SDL_PRESSED);prevbutton=KEY_R;} | ||
127 | |||
128 | if((keysu&KEY_A)) {SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED);prevbutton=0;} | ||
129 | if((keysu&KEY_B)) {SDL_PrivateJoystickButton(joystick,1,SDL_RELEASED);prevbutton=0;} | ||
130 | if((keysu&KEY_X)) {SDL_PrivateJoystickButton(joystick,2,SDL_RELEASED);prevbutton=0;} | ||
131 | if((keysu&KEY_Y)) {SDL_PrivateJoystickButton(joystick,3,SDL_RELEASED);prevbutton=0;} | ||
132 | if((keysu&KEY_SELECT)) {SDL_PrivateJoystickButton(joystick,6,SDL_RELEASED);prevbutton=0;} | ||
133 | if((keysu&KEY_START)) {SDL_PrivateJoystickButton(joystick,7,SDL_RELEASED);prevbutton=0;} | ||
134 | if((keysu&KEY_L)) {SDL_PrivateJoystickButton(joystick,4,SDL_RELEASED);prevbutton=0;} | ||
135 | if((keysu&KEY_R)) {SDL_PrivateJoystickButton(joystick,5,SDL_RELEASED);prevbutton=0;} | ||
136 | |||
137 | |||
138 | |||
139 | } | ||
140 | |||
141 | /* Function to close a joystick after use */ | ||
142 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
143 | { | ||
144 | } | ||
145 | |||
146 | /* Function to perform any system-specific joystick related cleanup */ | ||
147 | void SDL_SYS_JoystickQuit(void) | ||
148 | { | ||
149 | } | ||
150 | |||
diff --git a/apps/plugins/sdl/src/joystick/riscos/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/riscos/SDL_sysjoystick.c new file mode 100644 index 0000000000..214d4c7474 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/riscos/SDL_sysjoystick.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_RISCOS | ||
25 | |||
26 | /* | ||
27 | RISC OS - Joystick support by Alan Buckley (alan_baa@hotmail.com) - 10 April 2003 | ||
28 | |||
29 | Note: Currently assumes joystick is present if joystick module is loaded | ||
30 | and that there is one joystick with four buttons. | ||
31 | */ | ||
32 | |||
33 | /* This is the system specific header for the SDL joystick API */ | ||
34 | |||
35 | #include "SDL_events.h" | ||
36 | #include "SDL_joystick.h" | ||
37 | #include "../SDL_sysjoystick.h" | ||
38 | #include "../SDL_joystick_c.h" | ||
39 | |||
40 | #include "kernel.h" | ||
41 | |||
42 | #define JOYSTICK_READ 0x43F40 | ||
43 | |||
44 | struct joystick_hwdata | ||
45 | { | ||
46 | int joystate; | ||
47 | }; | ||
48 | |||
49 | |||
50 | /* Function to scan the system for joysticks. | ||
51 | * This function should set SDL_numjoysticks to the number of available | ||
52 | * joysticks. Joystick 0 should be the system default joystick. | ||
53 | * It should return number of joysticks, or -1 on an unrecoverable fatal error. | ||
54 | */ | ||
55 | int SDL_SYS_JoystickInit(void) | ||
56 | { | ||
57 | _kernel_swi_regs regs; | ||
58 | |||
59 | /* Try to read joystick 0 */ | ||
60 | regs.r[0] = 0; | ||
61 | if (_kernel_swi(JOYSTICK_READ, ®s, ®s) == NULL) | ||
62 | { | ||
63 | /* Switch works so assume we've got a joystick */ | ||
64 | return 1; | ||
65 | } | ||
66 | /* Switch fails so it looks like there's no joystick here */ | ||
67 | |||
68 | return(0); | ||
69 | } | ||
70 | |||
71 | /* Function to get the device-dependent name of a joystick */ | ||
72 | const char *SDL_SYS_JoystickName(int index) | ||
73 | { | ||
74 | if (index == 0) | ||
75 | { | ||
76 | return "RISC OS Joystick 0"; | ||
77 | } | ||
78 | |||
79 | SDL_SetError("No joystick available with that index"); | ||
80 | return(NULL); | ||
81 | } | ||
82 | |||
83 | /* Function to open a joystick for use. | ||
84 | The joystick to open is specified by the index field of the joystick. | ||
85 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
86 | It returns 0, or -1 if there is an error. | ||
87 | */ | ||
88 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
89 | { | ||
90 | _kernel_swi_regs regs; | ||
91 | |||
92 | if(!(joystick->hwdata=SDL_malloc(sizeof(struct joystick_hwdata)))) | ||
93 | return -1; | ||
94 | |||
95 | regs.r[0] = joystick->index; | ||
96 | |||
97 | /* Don't know how to get exact count of buttons so assume max of 4 for now */ | ||
98 | joystick->nbuttons=4; | ||
99 | |||
100 | joystick->nhats=0; | ||
101 | joystick->nballs=0; | ||
102 | joystick->naxes=2; | ||
103 | joystick->hwdata->joystate=0; | ||
104 | |||
105 | return 0; | ||
106 | |||
107 | } | ||
108 | |||
109 | /* Function to update the state of a joystick - called as a device poll. | ||
110 | * This function shouldn't update the joystick structure directly, | ||
111 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
112 | * and update joystick device state. | ||
113 | */ | ||
114 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
115 | { | ||
116 | _kernel_swi_regs regs; | ||
117 | regs.r[0] = joystick->index; | ||
118 | |||
119 | if (_kernel_swi(JOYSTICK_READ, ®s, ®s) == NULL) | ||
120 | { | ||
121 | int newstate = regs.r[0]; | ||
122 | int oldstate = joystick->hwdata->joystate; | ||
123 | if (newstate != oldstate) | ||
124 | { | ||
125 | if ((newstate & 0xFF) != (oldstate & 0xFF)) | ||
126 | { | ||
127 | int y = regs.r[0] & 0xFF; | ||
128 | /* Convert to signed values */ | ||
129 | if (y >= 128) y -= 256; | ||
130 | SDL_PrivateJoystickAxis(joystick,1,-y * 256); /* Up and down opposite to result in SDL */ | ||
131 | } | ||
132 | if ((newstate & 0xFF00) != (oldstate & 0xFF00)) | ||
133 | { | ||
134 | int x = (regs.r[0] & 0xFF00) >> 8; | ||
135 | if (x >= 128) x -= 256; | ||
136 | SDL_PrivateJoystickAxis(joystick,0,x * 256); | ||
137 | } | ||
138 | |||
139 | if ((newstate & 0xFF0000) != (oldstate & 0xFF0000)) | ||
140 | { | ||
141 | int buttons = (regs.r[0] & 0xFF0000) >> 16; | ||
142 | int oldbuttons = (oldstate & 0xFF0000) >> 16; | ||
143 | int i; | ||
144 | for (i = 0; i < joystick->nbuttons; i++) | ||
145 | { | ||
146 | if ((buttons & (1<<i)) != (oldbuttons & (1<<i))) | ||
147 | { | ||
148 | if (buttons & (1<<i)) SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); | ||
149 | else SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | joystick->hwdata->joystate = newstate; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | return; | ||
158 | } | ||
159 | |||
160 | /* Function to close a joystick after use */ | ||
161 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
162 | { | ||
163 | if(joystick->hwdata) | ||
164 | SDL_free(joystick->hwdata); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | /* Function to perform any system-specific joystick related cleanup */ | ||
169 | void SDL_SYS_JoystickQuit(void) | ||
170 | { | ||
171 | SDL_numjoysticks=0; | ||
172 | |||
173 | return; | ||
174 | } | ||
175 | |||
176 | #endif /* SDL_JOYSTICK_RISCOS */ | ||
diff --git a/apps/plugins/sdl/src/joystick/win32/SDL_mmjoystick.c b/apps/plugins/sdl/src/joystick/win32/SDL_mmjoystick.c new file mode 100644 index 0000000000..8c53f9e3dd --- /dev/null +++ b/apps/plugins/sdl/src/joystick/win32/SDL_mmjoystick.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | #ifdef SDL_JOYSTICK_WINMM | ||
25 | |||
26 | /* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */ | ||
27 | |||
28 | #define WIN32_LEAN_AND_MEAN | ||
29 | #include <windows.h> | ||
30 | #include <mmsystem.h> | ||
31 | #include <regstr.h> | ||
32 | |||
33 | #include "SDL_events.h" | ||
34 | #include "SDL_joystick.h" | ||
35 | #include "../SDL_sysjoystick.h" | ||
36 | #include "../SDL_joystick_c.h" | ||
37 | |||
38 | #define MAX_JOYSTICKS 16 | ||
39 | #define MAX_AXES 6 /* each joystick can have up to 6 axes */ | ||
40 | #define MAX_BUTTONS 32 /* and 32 buttons */ | ||
41 | #define AXIS_MIN -32768 /* minimum value for axis coordinate */ | ||
42 | #define AXIS_MAX 32767 /* maximum value for axis coordinate */ | ||
43 | /* limit axis to 256 possible positions to filter out noise */ | ||
44 | #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256) | ||
45 | #define JOY_BUTTON_FLAG(n) (1<<n) | ||
46 | |||
47 | |||
48 | /* array to hold joystick ID values */ | ||
49 | static UINT SYS_JoystickID[MAX_JOYSTICKS]; | ||
50 | static JOYCAPS SYS_Joystick[MAX_JOYSTICKS]; | ||
51 | static char *SYS_JoystickName[MAX_JOYSTICKS]; | ||
52 | |||
53 | /* The private structure used to keep track of a joystick */ | ||
54 | struct joystick_hwdata | ||
55 | { | ||
56 | /* joystick ID */ | ||
57 | UINT id; | ||
58 | |||
59 | /* values used to translate device-specific coordinates into | ||
60 | SDL-standard ranges */ | ||
61 | struct _transaxis { | ||
62 | int offset; | ||
63 | float scale; | ||
64 | } transaxis[6]; | ||
65 | }; | ||
66 | |||
67 | /* Convert a win32 Multimedia API return code to a text message */ | ||
68 | static void SetMMerror(char *function, int code); | ||
69 | |||
70 | |||
71 | static char *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, REGSTR_VAL_JOYOEMNAME); | ||
102 | regresult = RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE)regname, ®size); | ||
103 | RegCloseKey(hKey); | ||
104 | |||
105 | if (regresult != ERROR_SUCCESS) { | ||
106 | return NULL; | ||
107 | } | ||
108 | |||
109 | /* open that registry key */ | ||
110 | SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM, regname); | ||
111 | regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); | ||
112 | if (regresult != ERROR_SUCCESS) { | ||
113 | return NULL; | ||
114 | } | ||
115 | |||
116 | /* find the size for the OEM name text */ | ||
117 | regsize = sizeof(regvalue); | ||
118 | regresult = RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, ®size); | ||
119 | if (regresult == ERROR_SUCCESS) { | ||
120 | /* allocate enough memory for the OEM name text ... */ | ||
121 | name = (char *) SDL_malloc(regsize); | ||
122 | if ( name ) { | ||
123 | /* ... and read it from the registry */ | ||
124 | regresult = RegQueryValueExA(hKey, | ||
125 | REGSTR_VAL_JOYOEMNAME, 0, 0, | ||
126 | (LPBYTE) name, ®size); | ||
127 | } | ||
128 | } | ||
129 | RegCloseKey(hKey); | ||
130 | |||
131 | return(name); | ||
132 | } | ||
133 | |||
134 | /* Function to scan the system for joysticks. | ||
135 | * This function should set SDL_numjoysticks to the number of available | ||
136 | * joysticks. Joystick 0 should be the system default joystick. | ||
137 | * It should return 0, or -1 on an unrecoverable fatal error. | ||
138 | */ | ||
139 | int SDL_SYS_JoystickInit(void) | ||
140 | { | ||
141 | int i; | ||
142 | int maxdevs; | ||
143 | int numdevs; | ||
144 | JOYINFOEX joyinfo; | ||
145 | JOYCAPS joycaps; | ||
146 | MMRESULT result; | ||
147 | |||
148 | /* Reset the joystick ID & name mapping tables */ | ||
149 | for ( i = 0; i < MAX_JOYSTICKS; ++i ) { | ||
150 | SYS_JoystickID[i] = 0; | ||
151 | SYS_JoystickName[i] = NULL; | ||
152 | } | ||
153 | |||
154 | /* Loop over all potential joystick devices */ | ||
155 | numdevs = 0; | ||
156 | maxdevs = joyGetNumDevs(); | ||
157 | for ( i = JOYSTICKID1; i < maxdevs && numdevs < MAX_JOYSTICKS; ++i ) { | ||
158 | |||
159 | joyinfo.dwSize = sizeof(joyinfo); | ||
160 | joyinfo.dwFlags = JOY_RETURNALL; | ||
161 | result = joyGetPosEx(i, &joyinfo); | ||
162 | if ( result == JOYERR_NOERROR ) { | ||
163 | result = joyGetDevCaps(i, &joycaps, sizeof(joycaps)); | ||
164 | if ( result == JOYERR_NOERROR ) { | ||
165 | SYS_JoystickID[numdevs] = i; | ||
166 | SYS_Joystick[numdevs] = joycaps; | ||
167 | SYS_JoystickName[numdevs] = GetJoystickName(i, joycaps.szRegKey); | ||
168 | numdevs++; | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | return(numdevs); | ||
173 | } | ||
174 | |||
175 | /* Function to get the device-dependent name of a joystick */ | ||
176 | const char *SDL_SYS_JoystickName(int index) | ||
177 | { | ||
178 | if ( SYS_JoystickName[index] != NULL ) { | ||
179 | return(SYS_JoystickName[index]); | ||
180 | } else { | ||
181 | return(SYS_Joystick[index].szPname); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* Function to open a joystick for use. | ||
186 | The joystick to open is specified by the index field of the joystick. | ||
187 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
188 | It returns 0, or -1 if there is an error. | ||
189 | */ | ||
190 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | ||
191 | { | ||
192 | int index, i; | ||
193 | int caps_flags[MAX_AXES-2] = | ||
194 | { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; | ||
195 | int axis_min[MAX_AXES], axis_max[MAX_AXES]; | ||
196 | |||
197 | |||
198 | /* shortcut */ | ||
199 | index = joystick->index; | ||
200 | axis_min[0] = SYS_Joystick[index].wXmin; | ||
201 | axis_max[0] = SYS_Joystick[index].wXmax; | ||
202 | axis_min[1] = SYS_Joystick[index].wYmin; | ||
203 | axis_max[1] = SYS_Joystick[index].wYmax; | ||
204 | axis_min[2] = SYS_Joystick[index].wZmin; | ||
205 | axis_max[2] = SYS_Joystick[index].wZmax; | ||
206 | axis_min[3] = SYS_Joystick[index].wRmin; | ||
207 | axis_max[3] = SYS_Joystick[index].wRmax; | ||
208 | axis_min[4] = SYS_Joystick[index].wUmin; | ||
209 | axis_max[4] = SYS_Joystick[index].wUmax; | ||
210 | axis_min[5] = SYS_Joystick[index].wVmin; | ||
211 | axis_max[5] = SYS_Joystick[index].wVmax; | ||
212 | |||
213 | /* allocate memory for system specific hardware data */ | ||
214 | joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); | ||
215 | if (joystick->hwdata == NULL) | ||
216 | { | ||
217 | SDL_OutOfMemory(); | ||
218 | return(-1); | ||
219 | } | ||
220 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | ||
221 | |||
222 | /* set hardware data */ | ||
223 | joystick->hwdata->id = SYS_JoystickID[index]; | ||
224 | for ( i = 0; i < MAX_AXES; ++i ) { | ||
225 | if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { | ||
226 | joystick->hwdata->transaxis[i].offset = | ||
227 | AXIS_MIN - axis_min[i]; | ||
228 | joystick->hwdata->transaxis[i].scale = | ||
229 | (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); | ||
230 | } else { | ||
231 | joystick->hwdata->transaxis[i].offset = 0; | ||
232 | joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /* fill nbuttons, naxes, and nhats fields */ | ||
237 | joystick->nbuttons = SYS_Joystick[index].wNumButtons; | ||
238 | joystick->naxes = SYS_Joystick[index].wNumAxes; | ||
239 | if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { | ||
240 | joystick->nhats = 1; | ||
241 | } else { | ||
242 | joystick->nhats = 0; | ||
243 | } | ||
244 | return(0); | ||
245 | } | ||
246 | |||
247 | static Uint8 TranslatePOV(DWORD value) | ||
248 | { | ||
249 | Uint8 pos; | ||
250 | |||
251 | pos = SDL_HAT_CENTERED; | ||
252 | if ( value != JOY_POVCENTERED ) { | ||
253 | if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { | ||
254 | pos |= SDL_HAT_UP; | ||
255 | } | ||
256 | if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { | ||
257 | pos |= SDL_HAT_RIGHT; | ||
258 | } | ||
259 | if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { | ||
260 | pos |= SDL_HAT_DOWN; | ||
261 | } | ||
262 | if ( value > JOY_POVBACKWARD ) { | ||
263 | pos |= SDL_HAT_LEFT; | ||
264 | } | ||
265 | } | ||
266 | return(pos); | ||
267 | } | ||
268 | |||
269 | /* Function to update the state of a joystick - called as a device poll. | ||
270 | * This function shouldn't update the joystick structure directly, | ||
271 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
272 | * and update joystick device state. | ||
273 | */ | ||
274 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | ||
275 | { | ||
276 | MMRESULT result; | ||
277 | int i; | ||
278 | DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, | ||
279 | JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; | ||
280 | DWORD pos[MAX_AXES]; | ||
281 | struct _transaxis *transaxis; | ||
282 | int value, change; | ||
283 | JOYINFOEX joyinfo; | ||
284 | |||
285 | joyinfo.dwSize = sizeof(joyinfo); | ||
286 | joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; | ||
287 | if ( ! joystick->hats ) { | ||
288 | joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); | ||
289 | } | ||
290 | result = joyGetPosEx(joystick->hwdata->id, &joyinfo); | ||
291 | if ( result != JOYERR_NOERROR ) { | ||
292 | SetMMerror("joyGetPosEx", result); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | /* joystick motion events */ | ||
297 | pos[0] = joyinfo.dwXpos; | ||
298 | pos[1] = joyinfo.dwYpos; | ||
299 | pos[2] = joyinfo.dwZpos; | ||
300 | pos[3] = joyinfo.dwRpos; | ||
301 | pos[4] = joyinfo.dwUpos; | ||
302 | pos[5] = joyinfo.dwVpos; | ||
303 | |||
304 | transaxis = joystick->hwdata->transaxis; | ||
305 | for (i = 0; i < joystick->naxes; i++) { | ||
306 | if (joyinfo.dwFlags & flags[i]) { | ||
307 | value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); | ||
308 | change = (value - joystick->axes[i]); | ||
309 | if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { | ||
310 | SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* joystick button events */ | ||
316 | if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { | ||
317 | for ( i = 0; i < joystick->nbuttons; ++i ) { | ||
318 | if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { | ||
319 | if ( ! joystick->buttons[i] ) { | ||
320 | SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); | ||
321 | } | ||
322 | } else { | ||
323 | if ( joystick->buttons[i] ) { | ||
324 | SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | |||
330 | /* joystick hat events */ | ||
331 | if ( joyinfo.dwFlags & JOY_RETURNPOV ) { | ||
332 | Uint8 pos; | ||
333 | |||
334 | pos = TranslatePOV(joyinfo.dwPOV); | ||
335 | if ( pos != joystick->hats[0] ) { | ||
336 | SDL_PrivateJoystickHat(joystick, 0, pos); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* Function to close a joystick after use */ | ||
342 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | ||
343 | { | ||
344 | if (joystick->hwdata != NULL) { | ||
345 | /* free system specific hardware data */ | ||
346 | SDL_free(joystick->hwdata); | ||
347 | joystick->hwdata = NULL; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /* Function to perform any system-specific joystick related cleanup */ | ||
352 | void SDL_SYS_JoystickQuit(void) | ||
353 | { | ||
354 | int i; | ||
355 | for (i = 0; i < MAX_JOYSTICKS; i++) { | ||
356 | if ( SYS_JoystickName[i] != NULL ) { | ||
357 | SDL_free(SYS_JoystickName[i]); | ||
358 | SYS_JoystickName[i] = NULL; | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
363 | |||
364 | /* implementation functions */ | ||
365 | void SetMMerror(char *function, int code) | ||
366 | { | ||
367 | static char *error; | ||
368 | static char errbuf[1024]; | ||
369 | |||
370 | errbuf[0] = 0; | ||
371 | switch (code) | ||
372 | { | ||
373 | case MMSYSERR_NODRIVER: | ||
374 | error = "Joystick driver not present"; | ||
375 | break; | ||
376 | |||
377 | case MMSYSERR_INVALPARAM: | ||
378 | case JOYERR_PARMS: | ||
379 | error = "Invalid parameter(s)"; | ||
380 | break; | ||
381 | |||
382 | case MMSYSERR_BADDEVICEID: | ||
383 | error = "Bad device ID"; | ||
384 | break; | ||
385 | |||
386 | case JOYERR_UNPLUGGED: | ||
387 | error = "Joystick not attached"; | ||
388 | break; | ||
389 | |||
390 | case JOYERR_NOCANDO: | ||
391 | error = "Can't capture joystick input"; | ||
392 | break; | ||
393 | |||
394 | default: | ||
395 | SDL_snprintf(errbuf, SDL_arraysize(errbuf), | ||
396 | "%s: Unknown Multimedia system error: 0x%x", | ||
397 | function, code); | ||
398 | break; | ||
399 | } | ||
400 | |||
401 | if ( ! errbuf[0] ) { | ||
402 | SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); | ||
403 | } | ||
404 | SDL_SetError("%s", errbuf); | ||
405 | } | ||
406 | |||
407 | #endif /* SDL_JOYSTICK_WINMM */ | ||