handle multibuffering better
[sdl_omap.git] / src / joystick / linux / SDL_sysjoystick.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 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 */
43static 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
78struct 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
90static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = {
91 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}
92};
93static 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
97static 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};
101static 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
106static 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};
111static 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
117static 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};
123static 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
130struct joystick_logical_layout {
131 int naxes;
132 int nhats;
133 int nballs;
134 int nbuttons;
135};
136
137static struct joystick_logical_layout mp88xx_1_logical_layout[] = {
138 {6, 0, 0, 12}
139};
140static struct joystick_logical_layout mp88xx_2_logical_layout[] = {
141 {6, 0, 0, 12},
142 {6, 0, 0, 12}
143};
144static struct joystick_logical_layout mp88xx_3_logical_layout[] = {
145 {6, 0, 0, 12},
146 {6, 0, 0, 12},
147 {6, 0, 0, 12}
148};
149static 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 */
169struct 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
180static 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 */
261static 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 */
275struct 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
301static 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
351static 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
380static 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 */
400int 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 a joystick to use */
421 if ( SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL ) {
422 SDL_strlcpy(path, SDL_getenv("SDL_JOYSTICK_DEVICE"), sizeof(path));
423 if ( stat(path, &sb) == 0 ) {
424 fd = open(path, O_RDONLY, 0);
425 if ( fd >= 0 ) {
426 /* Assume the user knows what they're doing. */
427 SDL_joylist[numjoysticks].fname = SDL_strdup(path);
428 if ( SDL_joylist[numjoysticks].fname ) {
429 dev_nums[numjoysticks] = sb.st_rdev;
430 ++numjoysticks;
431 }
432 close(fd);
433 }
434 }
435 }
436
437 for ( i=0; i<SDL_arraysize(joydev_pattern); ++i ) {
438 for ( j=0; j < MAX_JOYSTICKS; ++j ) {
439 SDL_snprintf(path, SDL_arraysize(path), joydev_pattern[i], j);
440
441 /* rcg06302000 replaced access(F_OK) call with stat().
442 * stat() will fail if the file doesn't exist, so it's
443 * equivalent behaviour.
444 */
445 if ( stat(path, &sb) == 0 ) {
446 /* Check to make sure it's not already in list.
447 * This happens when we see a stick via symlink.
448 */
449 duplicate = 0;
450 for (n=0; (n<numjoysticks) && !duplicate; ++n) {
451 if ( sb.st_rdev == dev_nums[n] ) {
452 duplicate = 1;
453 }
454 }
455 if (duplicate) {
456 continue;
457 }
458
459 fd = open(path, O_RDONLY, 0);
460 if ( fd < 0 ) {
461 continue;
462 }
463#if SDL_INPUT_LINUXEV
464#ifdef DEBUG_INPUT_EVENTS
465 printf("Checking %s\n", path);
466#endif
467 if ( (i == 0) && ! EV_IsJoystick(fd) ) {
468 close(fd);
469 continue;
470 }
471#endif
472 close(fd);
473
474 /* We're fine, add this joystick */
475 SDL_joylist[numjoysticks].fname = SDL_strdup(path);
476 if ( SDL_joylist[numjoysticks].fname ) {
477 dev_nums[numjoysticks] = sb.st_rdev;
478 ++numjoysticks;
479 }
480 }
481 }
482
483#if SDL_INPUT_LINUXEV
484 /* This is a special case...
485 If the event devices are valid then the joystick devices
486 will be duplicates but without extra information about their
487 hats or balls. Unfortunately, the event devices can't
488 currently be calibrated, so it's a win-lose situation.
489 So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
490 */
491 if ( (i == 0) && (numjoysticks > 0) )
492 break;
493#endif
494 }
495#ifndef NO_LOGICAL_JOYSTICKS
496 numjoysticks += CountLogicalJoysticks(numjoysticks);
497#endif
498
499 return(numjoysticks);
500}
501
502/* Function to get the device-dependent name of a joystick */
503const char *SDL_SYS_JoystickName(int index)
504{
505 int fd;
506 static char namebuf[128];
507 char *name;
508 SDL_logical_joydecl(int oindex = index);
509
510#ifndef NO_LOGICAL_JOYSTICKS
511 SDL_joylist_head(index, index);
512#endif
513 name = NULL;
514 fd = open(SDL_joylist[index].fname, O_RDONLY, 0);
515 if ( fd >= 0 ) {
516 if (
517#if SDL_INPUT_LINUXEV
518 (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) &&
519#endif
520 (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) {
521 name = SDL_joylist[index].fname;
522 } else {
523 name = namebuf;
524 }
525 close(fd);
526
527
528#ifndef NO_LOGICAL_JOYSTICKS
529 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex)
530 {
531 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128);
532 }
533#endif
534 }
535 return name;
536}
537
538static int allocate_hatdata(SDL_Joystick *joystick)
539{
540 int i;
541
542 joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(
543 joystick->nhats * sizeof(struct hwdata_hat));
544 if ( joystick->hwdata->hats == NULL ) {
545 return(-1);
546 }
547 for ( i=0; i<joystick->nhats; ++i ) {
548 joystick->hwdata->hats[i].axis[0] = 1;
549 joystick->hwdata->hats[i].axis[1] = 1;
550 }
551 return(0);
552}
553
554static int allocate_balldata(SDL_Joystick *joystick)
555{
556 int i;
557
558 joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc(
559 joystick->nballs * sizeof(struct hwdata_ball));
560 if ( joystick->hwdata->balls == NULL ) {
561 return(-1);
562 }
563 for ( i=0; i<joystick->nballs; ++i ) {
564 joystick->hwdata->balls[i].axis[0] = 0;
565 joystick->hwdata->balls[i].axis[1] = 0;
566 }
567 return(0);
568}
569
570static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd)
571{
572 SDL_bool handled;
573 unsigned char n;
574 int old_axes, tmp_naxes, tmp_nhats, tmp_nballs;
575 const char *name;
576 char *env, env_name[128];
577 int i;
578
579 handled = SDL_FALSE;
580
581 /* Default joystick device settings */
582 if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
583 joystick->naxes = 2;
584 } else {
585 joystick->naxes = n;
586 }
587 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
588 joystick->nbuttons = 2;
589 } else {
590 joystick->nbuttons = n;
591 }
592
593 name = SDL_SYS_JoystickName(joystick->index);
594 old_axes = joystick->naxes;
595
596 /* Generic analog joystick support */
597 if ( SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat") ) {
598 if ( SDL_sscanf(name,"Analog %d-axis %*d-button %d-hat",
599 &tmp_naxes, &tmp_nhats) == 2 ) {
600
601 joystick->naxes = tmp_naxes;
602 joystick->nhats = tmp_nhats;
603
604 handled = SDL_TRUE;
605 }
606 }
607
608 /* Special joystick support */
609 for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) {
610 if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) {
611
612 joystick->naxes = special_joysticks[i].naxes;
613 joystick->nhats = special_joysticks[i].nhats;
614 joystick->nballs = special_joysticks[i].nballs;
615
616 handled = SDL_TRUE;
617 break;
618 }
619 }
620
621 /* User environment joystick support */
622 if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) {
623 *env_name = '\0';
624 if ( *env == '\'' && SDL_sscanf(env, "'%[^']s'", env_name) == 1 )
625 env += SDL_strlen(env_name)+2;
626 else if ( SDL_sscanf(env, "%s", env_name) == 1 )
627 env += SDL_strlen(env_name);
628
629 if ( SDL_strcmp(name, env_name) == 0 ) {
630
631 if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats,
632 &tmp_nballs) == 3 ) {
633
634 joystick->naxes = tmp_naxes;
635 joystick->nhats = tmp_nhats;
636 joystick->nballs = tmp_nballs;
637
638 handled = SDL_TRUE;
639 }
640 }
641 }
642
643 /* Remap hats and balls */
644 if (handled) {
645 if ( joystick->nhats > 0 ) {
646 if ( allocate_hatdata(joystick) < 0 ) {
647 joystick->nhats = 0;
648 }
649 }
650 if ( joystick->nballs > 0 ) {
651 if ( allocate_balldata(joystick) < 0 ) {
652 joystick->nballs = 0;
653 }
654 }
655 }
656
657 return(handled);
658}
659
660#if SDL_INPUT_LINUXEV
661
662static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
663{
664 int i, t;
665 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
666 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
667 unsigned long relbit[NBITS(REL_MAX)] = { 0 };
668
669 /* See if this device uses the new unified event API */
670 if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
671 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
672 (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) {
673 joystick->hwdata->is_hid = SDL_TRUE;
674
675 /* Get the number of buttons, axes, and other thingamajigs */
676 for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) {
677 if ( test_bit(i, keybit) ) {
678#ifdef DEBUG_INPUT_EVENTS
679 printf("Joystick has button: 0x%x\n", i);
680#endif
681 joystick->hwdata->key_map[i-BTN_MISC] =
682 joystick->nbuttons;
683 ++joystick->nbuttons;
684 }
685 }
686 for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) {
687 if ( test_bit(i, keybit) ) {
688#ifdef DEBUG_INPUT_EVENTS
689 printf("Joystick has button: 0x%x\n", i);
690#endif
691 joystick->hwdata->key_map[i-BTN_MISC] =
692 joystick->nbuttons;
693 ++joystick->nbuttons;
694 }
695 }
696 for ( i=0; i<ABS_MAX; ++i ) {
697 /* Skip hats */
698 if ( i == ABS_HAT0X ) {
699 i = ABS_HAT3Y;
700 continue;
701 }
702 if ( test_bit(i, absbit) ) {
703 int values[5];
704
705 if ( ioctl(fd, EVIOCGABS(i), values) < 0 )
706 continue;
707#ifdef DEBUG_INPUT_EVENTS
708 printf("Joystick has absolute axis: %x\n", i);
709 printf("Values = { %d, %d, %d, %d, %d }\n",
710 values[0], values[1],
711 values[2], values[3], values[4]);
712#endif /* DEBUG_INPUT_EVENTS */
713 joystick->hwdata->abs_map[i] = joystick->naxes;
714 if ( values[1] == values[2] ) {
715 joystick->hwdata->abs_correct[i].used = 0;
716 } else {
717 joystick->hwdata->abs_correct[i].used = 1;
718 joystick->hwdata->abs_correct[i].coef[0] =
719 (values[2] + values[1]) / 2 - values[4];
720 joystick->hwdata->abs_correct[i].coef[1] =
721 (values[2] + values[1]) / 2 + values[4];
722 t = ((values[2] - values[1]) / 2 - 2 * values[4]);
723 if ( t != 0 ) {
724 joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t;
725 } else {
726 joystick->hwdata->abs_correct[i].coef[2] = 0;
727 }
728 }
729 ++joystick->naxes;
730 }
731 }
732 for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) {
733 if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) {
734#ifdef DEBUG_INPUT_EVENTS
735 printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2);
736#endif
737 ++joystick->nhats;
738 }
739 }
740 if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) {
741 ++joystick->nballs;
742 }
743
744 /* Allocate data to keep track of these thingamajigs */
745 if ( joystick->nhats > 0 ) {
746 if ( allocate_hatdata(joystick) < 0 ) {
747 joystick->nhats = 0;
748 }
749 }
750 if ( joystick->nballs > 0 ) {
751 if ( allocate_balldata(joystick) < 0 ) {
752 joystick->nballs = 0;
753 }
754 }
755 }
756 return(joystick->hwdata->is_hid);
757}
758
759#endif /* SDL_INPUT_LINUXEV */
760
761#ifndef NO_LOGICAL_JOYSTICKS
762static void ConfigLogicalJoystick(SDL_Joystick *joystick)
763{
764 struct joystick_logical_layout* layout;
765
766 layout = SDL_joylist[joystick->index].map->layout +
767 SDL_joylist[joystick->index].logicalno;
768
769 joystick->nbuttons = layout->nbuttons;
770 joystick->nhats = layout->nhats;
771 joystick->naxes = layout->naxes;
772 joystick->nballs = layout->nballs;
773}
774#endif
775
776
777/* Function to open a joystick for use.
778 The joystick to open is specified by the index field of the joystick.
779 This should fill the nbuttons and naxes fields of the joystick structure.
780 It returns 0, or -1 if there is an error.
781 */
782int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
783{
784 int fd;
785 SDL_logical_joydecl(int realindex);
786 SDL_logical_joydecl(SDL_Joystick *realjoy = NULL);
787
788 /* Open the joystick and set the joystick file descriptor */
789#ifndef NO_LOGICAL_JOYSTICKS
790 if (SDL_joylist[joystick->index].fname == NULL) {
791 SDL_joylist_head(realindex, joystick->index);
792 realjoy = SDL_JoystickOpen(realindex);
793
794 if (realjoy == NULL)
795 return(-1);
796
797 fd = realjoy->hwdata->fd;
798
799 } else {
800 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
801 }
802 SDL_joylist[joystick->index].joy = joystick;
803#else
804 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
805#endif
806
807 if ( fd < 0 ) {
808 SDL_SetError("Unable to open %s\n",
809 SDL_joylist[joystick->index]);
810 return(-1);
811 }
812 joystick->hwdata = (struct joystick_hwdata *)
813 SDL_malloc(sizeof(*joystick->hwdata));
814 if ( joystick->hwdata == NULL ) {
815 SDL_OutOfMemory();
816 close(fd);
817 return(-1);
818 }
819 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
820 joystick->hwdata->fd = fd;
821
822 /* Set the joystick to non-blocking read mode */
823 fcntl(fd, F_SETFL, O_NONBLOCK);
824
825 /* Get the number of buttons and axes on the joystick */
826#ifndef NO_LOGICAL_JOYSTICKS
827 if (realjoy)
828 ConfigLogicalJoystick(joystick);
829 else
830#endif
831#if SDL_INPUT_LINUXEV
832 if ( ! EV_ConfigJoystick(joystick, fd) )
833#endif
834 JS_ConfigJoystick(joystick, fd);
835
836 return(0);
837}
838
839#ifndef NO_LOGICAL_JOYSTICKS
840
841static SDL_Joystick* FindLogicalJoystick(
842 SDL_Joystick *joystick, struct joystick_logical_mapping* v)
843{
844 SDL_Joystick *logicaljoy;
845 register int i;
846
847 i = joystick->index;
848 logicaljoy = NULL;
849
850 /* get the fake joystick that will receive the event
851 */
852 for(;;) {
853
854 if (SDL_joylist[i].logicalno == v->njoy) {
855 logicaljoy = SDL_joylist[i].joy;
856 break;
857 }
858
859 if (SDL_joylist[i].next == 0)
860 break;
861
862 i = SDL_joylist[i].next;
863
864 }
865
866 return logicaljoy;
867}
868
869static int LogicalJoystickButton(
870 SDL_Joystick *joystick, Uint8 button, Uint8 state){
871 struct joystick_logical_mapping* buttons;
872 SDL_Joystick *logicaljoy = NULL;
873
874 /* if there's no map then this is just a regular joystick
875 */
876 if (SDL_joylist[joystick->index].map == NULL)
877 return 0;
878
879 /* get the logical joystick that will receive the event
880 */
881 buttons = SDL_joylist[joystick->index].map->buttonmap+button;
882 logicaljoy = FindLogicalJoystick(joystick, buttons);
883
884 if (logicaljoy == NULL)
885 return 1;
886
887 SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state);
888
889 return 1;
890}
891
892static int LogicalJoystickAxis(
893 SDL_Joystick *joystick, Uint8 axis, Sint16 value)
894{
895 struct joystick_logical_mapping* axes;
896 SDL_Joystick *logicaljoy = NULL;
897
898 /* if there's no map then this is just a regular joystick
899 */
900 if (SDL_joylist[joystick->index].map == NULL)
901 return 0;
902
903 /* get the logical joystick that will receive the event
904 */
905 axes = SDL_joylist[joystick->index].map->axismap+axis;
906 logicaljoy = FindLogicalJoystick(joystick, axes);
907
908 if (logicaljoy == NULL)
909 return 1;
910
911 SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value);
912
913 return 1;
914}
915#endif /* USE_LOGICAL_JOYSTICKS */
916
917static __inline__
918void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
919{
920 struct hwdata_hat *the_hat;
921 const Uint8 position_map[3][3] = {
922 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP },
923 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT },
924 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN }
925 };
926 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL);
927 SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL);
928
929 the_hat = &stick->hwdata->hats[hat];
930 if ( value < 0 ) {
931 value = 0;
932 } else
933 if ( value == 0 ) {
934 value = 1;
935 } else
936 if ( value > 0 ) {
937 value = 2;
938 }
939 if ( value != the_hat->axis[axis] ) {
940 the_hat->axis[axis] = value;
941
942#ifndef NO_LOGICAL_JOYSTICKS
943 /* if there's no map then this is just a regular joystick
944 */
945 if (SDL_joylist[stick->index].map != NULL) {
946
947 /* get the fake joystick that will receive the event
948 */
949 hats = SDL_joylist[stick->index].map->hatmap+hat;
950 logicaljoy = FindLogicalJoystick(stick, hats);
951 }
952
953 if (logicaljoy) {
954 stick = logicaljoy;
955 hat = hats->nthing;
956 }
957#endif /* USE_LOGICAL_JOYSTICKS */
958
959 SDL_PrivateJoystickHat(stick, hat,
960 position_map[the_hat->axis[1]][the_hat->axis[0]]);
961 }
962}
963
964static __inline__
965void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
966{
967 stick->hwdata->balls[ball].axis[axis] += value;
968}
969
970/* Function to update the state of a joystick - called as a device poll.
971 * This function shouldn't update the joystick structure directly,
972 * but instead should call SDL_PrivateJoystick*() to deliver events
973 * and update joystick device state.
974 */
975static __inline__ void JS_HandleEvents(SDL_Joystick *joystick)
976{
977 struct js_event events[32];
978 int i, len;
979 Uint8 other_axis;
980
981#ifndef NO_LOGICAL_JOYSTICKS
982 if (SDL_joylist[joystick->index].fname == NULL) {
983 SDL_joylist_head(i, joystick->index);
984 JS_HandleEvents(SDL_joylist[i].joy);
985 return;
986 }
987#endif
988
989 while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
990 len /= sizeof(events[0]);
991 for ( i=0; i<len; ++i ) {
992 switch (events[i].type & ~JS_EVENT_INIT) {
993 case JS_EVENT_AXIS:
994 if ( events[i].number < joystick->naxes ) {
995#ifndef NO_LOGICAL_JOYSTICKS
996 if (!LogicalJoystickAxis(joystick,
997 events[i].number, events[i].value))
998#endif
999 SDL_PrivateJoystickAxis(joystick,
1000 events[i].number, events[i].value);
1001 break;
1002 }
1003 events[i].number -= joystick->naxes;
1004 other_axis = (events[i].number / 2);
1005 if ( other_axis < joystick->nhats ) {
1006 HandleHat(joystick, other_axis,
1007 events[i].number%2,
1008 events[i].value);
1009 break;
1010 }
1011 events[i].number -= joystick->nhats*2;
1012 other_axis = (events[i].number / 2);
1013 if ( other_axis < joystick->nballs ) {
1014 HandleBall(joystick, other_axis,
1015 events[i].number%2,
1016 events[i].value);
1017 break;
1018 }
1019 break;
1020 case JS_EVENT_BUTTON:
1021#ifndef NO_LOGICAL_JOYSTICKS
1022 if (!LogicalJoystickButton(joystick,
1023 events[i].number, events[i].value))
1024#endif
1025 SDL_PrivateJoystickButton(joystick,
1026 events[i].number, events[i].value);
1027 break;
1028 default:
1029 /* ?? */
1030 break;
1031 }
1032 }
1033 }
1034}
1035#if SDL_INPUT_LINUXEV
1036static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value)
1037{
1038 struct axis_correct *correct;
1039
1040 correct = &joystick->hwdata->abs_correct[which];
1041 if ( correct->used ) {
1042 if ( value > correct->coef[0] ) {
1043 if ( value < correct->coef[1] ) {
1044 return 0;
1045 }
1046 value -= correct->coef[1];
1047 } else {
1048 value -= correct->coef[0];
1049 }
1050 value *= correct->coef[2];
1051 value >>= 14;
1052 }
1053
1054 /* Clamp and return */
1055 if ( value < -32768 ) return -32768;
1056 if ( value > 32767 ) return 32767;
1057
1058 return value;
1059}
1060
1061static __inline__ void EV_HandleEvents(SDL_Joystick *joystick)
1062{
1063 struct input_event events[32];
1064 int i, len;
1065 int code;
1066
1067#ifndef NO_LOGICAL_JOYSTICKS
1068 if (SDL_joylist[joystick->index].fname == NULL) {
1069 SDL_joylist_head(i, joystick->index);
1070 return EV_HandleEvents(SDL_joylist[i].joy);
1071 }
1072#endif
1073
1074 while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1075 len /= sizeof(events[0]);
1076 for ( i=0; i<len; ++i ) {
1077 code = events[i].code;
1078 switch (events[i].type) {
1079 case EV_KEY:
1080 if ( code >= BTN_MISC ) {
1081 code -= BTN_MISC;
1082#ifndef NO_LOGICAL_JOYSTICKS
1083 if (!LogicalJoystickButton(joystick,
1084 joystick->hwdata->key_map[code],
1085 events[i].value))
1086#endif
1087 SDL_PrivateJoystickButton(joystick,
1088 joystick->hwdata->key_map[code],
1089 events[i].value);
1090 }
1091 break;
1092 case EV_ABS:
1093 switch (code) {
1094 case ABS_HAT0X:
1095 case ABS_HAT0Y:
1096 case ABS_HAT1X:
1097 case ABS_HAT1Y:
1098 case ABS_HAT2X:
1099 case ABS_HAT2Y:
1100 case ABS_HAT3X:
1101 case ABS_HAT3Y:
1102 code -= ABS_HAT0X;
1103 HandleHat(joystick, code/2, code%2,
1104 events[i].value);
1105 break;
1106 default:
1107 events[i].value = EV_AxisCorrect(joystick, code, events[i].value);
1108#ifndef NO_LOGICAL_JOYSTICKS
1109 if (!LogicalJoystickAxis(joystick,
1110 joystick->hwdata->abs_map[code],
1111 events[i].value))
1112#endif
1113 SDL_PrivateJoystickAxis(joystick,
1114 joystick->hwdata->abs_map[code],
1115 events[i].value);
1116 break;
1117 }
1118 break;
1119 case EV_REL:
1120 switch (code) {
1121 case REL_X:
1122 case REL_Y:
1123 code -= REL_X;
1124 HandleBall(joystick, code/2, code%2,
1125 events[i].value);
1126 break;
1127 default:
1128 break;
1129 }
1130 break;
1131 default:
1132 break;
1133 }
1134 }
1135 }
1136}
1137#endif /* SDL_INPUT_LINUXEV */
1138
1139void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
1140{
1141 int i;
1142
1143#if SDL_INPUT_LINUXEV
1144 if ( joystick->hwdata->is_hid )
1145 EV_HandleEvents(joystick);
1146 else
1147#endif
1148 JS_HandleEvents(joystick);
1149
1150 /* Deliver ball motion updates */
1151 for ( i=0; i<joystick->nballs; ++i ) {
1152 int xrel, yrel;
1153
1154 xrel = joystick->hwdata->balls[i].axis[0];
1155 yrel = joystick->hwdata->balls[i].axis[1];
1156 if ( xrel || yrel ) {
1157 joystick->hwdata->balls[i].axis[0] = 0;
1158 joystick->hwdata->balls[i].axis[1] = 0;
1159 SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel);
1160 }
1161 }
1162}
1163
1164/* Function to close a joystick after use */
1165void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
1166{
1167#ifndef NO_LOGICAL_JOYSTICKS
1168 register int i;
1169 if (SDL_joylist[joystick->index].fname == NULL) {
1170 SDL_joylist_head(i, joystick->index);
1171 SDL_JoystickClose(SDL_joylist[i].joy);
1172 }
1173#endif
1174
1175 if ( joystick->hwdata ) {
1176#ifndef NO_LOGICAL_JOYSTICKS
1177 if (SDL_joylist[joystick->index].fname != NULL)
1178#endif
1179 close(joystick->hwdata->fd);
1180 if ( joystick->hwdata->hats ) {
1181 SDL_free(joystick->hwdata->hats);
1182 }
1183 if ( joystick->hwdata->balls ) {
1184 SDL_free(joystick->hwdata->balls);
1185 }
1186 SDL_free(joystick->hwdata);
1187 joystick->hwdata = NULL;
1188 }
1189}
1190
1191/* Function to perform any system-specific joystick related cleanup */
1192void SDL_SYS_JoystickQuit(void)
1193{
1194 int i;
1195
1196 for ( i=0; SDL_joylist[i].fname; ++i ) {
1197 SDL_free(SDL_joylist[i].fname);
1198 SDL_joylist[i].fname = NULL;
1199 }
1200}
1201
1202#endif /* SDL_JOYSTICK_LINUX */