2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 #ifdef SDL_JOYSTICK_LINUX
26 /* This is the system specific header for the SDL joystick API */
31 #include <sys/ioctl.h>
32 #include <limits.h> /* For the definition of PATH_MAX */
33 #include <linux/joystick.h>
35 #include <linux/input.h>
38 #include "SDL_joystick.h"
39 #include "../SDL_sysjoystick.h"
40 #include "../SDL_joystick_c.h"
42 /* Special joystick configurations */
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 }
62 /* It looks like newer kernels have the logical mapping at the driver level */
63 #define NO_LOGICAL_JOYSTICKS
65 #ifndef NO_LOGICAL_JOYSTICKS
68 Some USB HIDs show up as a single joystick even though they actually
69 control 2 or more joysticks.
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.
78 struct joystick_logical_mapping {
84 {logical joy, logical axis},
85 {logical joy, logical hat},
86 {logical joy, logical ball},
87 {logical joy, logical button}
90 static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = {
91 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}
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}
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}
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}
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}
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}
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}
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}
130 struct joystick_logical_layout {
137 static struct joystick_logical_layout mp88xx_1_logical_layout[] = {
140 static struct joystick_logical_layout mp88xx_2_logical_layout[] = {
144 static struct joystick_logical_layout mp88xx_3_logical_layout[] = {
149 static struct joystick_logical_layout mp88xx_4_logical_layout[] = {
157 This array sets up a means of mapping a single physical joystick to
158 multiple logical joysticks. (djm)
161 the number of logical joysticks
164 an array of layout structures, one to describe each logical joystick
166 axes, hats, balls, buttons
167 arrays that map a physical thingy to a logical thingy
169 struct joystick_logicalmap {
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;
180 static struct joystick_logicalmap joystick_logicalmap[] = {
182 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
185 mp88xx_1_logical_layout,
186 mp88xx_1_logical_axismap,
189 mp88xx_1_logical_buttonmap
192 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
195 mp88xx_2_logical_layout,
196 mp88xx_2_logical_axismap,
199 mp88xx_2_logical_buttonmap
202 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
205 mp88xx_1_logical_layout,
206 mp88xx_1_logical_axismap,
209 mp88xx_1_logical_buttonmap
212 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
215 mp88xx_2_logical_layout,
216 mp88xx_2_logical_axismap,
219 mp88xx_2_logical_buttonmap
222 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
225 mp88xx_3_logical_layout,
226 mp88xx_3_logical_axismap,
229 mp88xx_3_logical_buttonmap
232 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
235 mp88xx_4_logical_layout,
236 mp88xx_4_logical_axismap,
239 mp88xx_4_logical_buttonmap
243 /* find the head of a linked list, given a point in it
245 #define SDL_joylist_head(i, start)\
246 for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev;
248 #define SDL_logical_joydecl(d) d
253 #define SDL_logical_joydecl(d)
255 #endif /* USE_LOGICAL_JOYSTICKS */
257 /* The maximum number of joysticks we'll detect */
258 #define MAX_JOYSTICKS 32
260 /* A list of available joysticks */
264 #ifndef NO_LOGICAL_JOYSTICKS
266 struct joystick_logicalmap* map;
270 #endif /* USE_LOGICAL_JOYSTICKS */
271 } SDL_joylist[MAX_JOYSTICKS];
274 /* The private structure used to keep track of a joystick */
275 struct joystick_hwdata {
277 /* The current linux joystick driver maps hats to two axes */
281 /* The current linux joystick driver maps balls to two axes */
286 /* Support for the Linux 2.4 unified input interface */
287 #if SDL_INPUT_LINUXEV
289 Uint8 key_map[KEY_MAX-BTN_MISC];
290 Uint8 abs_map[ABS_MAX];
291 struct axis_correct {
294 } abs_correct[ABS_MAX];
299 #ifndef NO_LOGICAL_JOYSTICKS
301 static int CountLogicalJoysticks(int max)
303 register int i, j, k, ret, prev;
310 for(i = 0; i < max; i++) {
311 name = SDL_SYS_JoystickName(i);
313 fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
315 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
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)) {
330 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
332 for(k = 1; k < joystick_logicalmap[j].njoys; k++) {
333 SDL_joylist[prev].next = max + ret;
334 SDL_joylist[max+ret].prev = prev;
337 SDL_joylist[prev].logicalno = k;
338 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
351 static void LogicalSuffix(int logicalno, char* namebuf, int len)
354 const static char suffixs[] =
355 "01020304050607080910111213141516171819"
356 "20212223242526272829303132";
358 slen = SDL_strlen(namebuf);
361 if (logicalno*2<sizeof(suffixs))
362 suffix = suffixs + (logicalno*2);
364 if (slen + 4 < len && suffix) {
365 namebuf[slen++] = ' ';
366 namebuf[slen++] = '#';
367 namebuf[slen++] = suffix[0];
368 namebuf[slen++] = suffix[1];
373 #endif /* USE_LOGICAL_JOYSTICKS */
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)
380 static int EV_IsJoystick(int fd)
382 unsigned long evbit[NBITS(EV_MAX)] = { 0 };
383 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
384 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
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) ) {
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;
397 #endif /* SDL_INPUT_LINUXEV */
399 /* Function to scan the system for joysticks */
400 int SDL_SYS_JoystickInit(void)
402 /* The base path of the joystick devices */
403 const char *joydev_pattern[] = {
404 #if SDL_INPUT_LINUXEV
405 "/dev/input/event%d",
414 dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */
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);
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;
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);
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.
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.
450 for (n=0; (n<numjoysticks) && !duplicate; ++n) {
451 if ( sb.st_rdev == dev_nums[n] ) {
459 fd = open(path, O_RDONLY, 0);
463 #if SDL_INPUT_LINUXEV
464 #ifdef DEBUG_INPUT_EVENTS
465 printf("Checking %s\n", path);
467 if ( (i == 0) && ! EV_IsJoystick(fd) ) {
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;
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
491 if ( (i == 0) && (numjoysticks > 0) )
495 #ifndef NO_LOGICAL_JOYSTICKS
496 numjoysticks += CountLogicalJoysticks(numjoysticks);
499 return(numjoysticks);
502 /* Function to get the device-dependent name of a joystick */
503 const char *SDL_SYS_JoystickName(int index)
506 static char namebuf[128];
508 SDL_logical_joydecl(int oindex = index);
510 #ifndef NO_LOGICAL_JOYSTICKS
511 SDL_joylist_head(index, index);
514 fd = open(SDL_joylist[index].fname, O_RDONLY, 0);
517 #if SDL_INPUT_LINUXEV
518 (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) &&
520 (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) {
521 name = SDL_joylist[index].fname;
528 #ifndef NO_LOGICAL_JOYSTICKS
529 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex)
531 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128);
538 static int allocate_hatdata(SDL_Joystick *joystick)
542 joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(
543 joystick->nhats * sizeof(struct hwdata_hat));
544 if ( joystick->hwdata->hats == NULL ) {
547 for ( i=0; i<joystick->nhats; ++i ) {
548 joystick->hwdata->hats[i].axis[0] = 1;
549 joystick->hwdata->hats[i].axis[1] = 1;
554 static int allocate_balldata(SDL_Joystick *joystick)
558 joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc(
559 joystick->nballs * sizeof(struct hwdata_ball));
560 if ( joystick->hwdata->balls == NULL ) {
563 for ( i=0; i<joystick->nballs; ++i ) {
564 joystick->hwdata->balls[i].axis[0] = 0;
565 joystick->hwdata->balls[i].axis[1] = 0;
570 static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd)
574 int old_axes, tmp_naxes, tmp_nhats, tmp_nballs;
576 char *env, env_name[128];
581 /* Default joystick device settings */
582 if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
587 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
588 joystick->nbuttons = 2;
590 joystick->nbuttons = n;
593 name = SDL_SYS_JoystickName(joystick->index);
594 old_axes = joystick->naxes;
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 ) {
601 joystick->naxes = tmp_naxes;
602 joystick->nhats = tmp_nhats;
608 /* Special joystick support */
609 for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) {
610 if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) {
612 joystick->naxes = special_joysticks[i].naxes;
613 joystick->nhats = special_joysticks[i].nhats;
614 joystick->nballs = special_joysticks[i].nballs;
621 /* User environment joystick support */
622 if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) {
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);
629 if ( SDL_strcmp(name, env_name) == 0 ) {
631 if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats,
632 &tmp_nballs) == 3 ) {
634 joystick->naxes = tmp_naxes;
635 joystick->nhats = tmp_nhats;
636 joystick->nballs = tmp_nballs;
643 /* Remap hats and balls */
645 if ( joystick->nhats > 0 ) {
646 if ( allocate_hatdata(joystick) < 0 ) {
650 if ( joystick->nballs > 0 ) {
651 if ( allocate_balldata(joystick) < 0 ) {
652 joystick->nballs = 0;
660 #if SDL_INPUT_LINUXEV
662 static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
665 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
666 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
667 unsigned long relbit[NBITS(REL_MAX)] = { 0 };
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;
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);
681 joystick->hwdata->key_map[i-BTN_MISC] =
683 ++joystick->nbuttons;
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);
691 joystick->hwdata->key_map[i-BTN_MISC] =
693 ++joystick->nbuttons;
696 for ( i=0; i<ABS_MAX; ++i ) {
698 if ( i == ABS_HAT0X ) {
702 if ( test_bit(i, absbit) ) {
705 if ( ioctl(fd, EVIOCGABS(i), values) < 0 )
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;
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]);
724 joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t;
726 joystick->hwdata->abs_correct[i].coef[2] = 0;
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);
740 if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) {
744 /* Allocate data to keep track of these thingamajigs */
745 if ( joystick->nhats > 0 ) {
746 if ( allocate_hatdata(joystick) < 0 ) {
750 if ( joystick->nballs > 0 ) {
751 if ( allocate_balldata(joystick) < 0 ) {
752 joystick->nballs = 0;
756 return(joystick->hwdata->is_hid);
759 #endif /* SDL_INPUT_LINUXEV */
761 #ifndef NO_LOGICAL_JOYSTICKS
762 static void ConfigLogicalJoystick(SDL_Joystick *joystick)
764 struct joystick_logical_layout* layout;
766 layout = SDL_joylist[joystick->index].map->layout +
767 SDL_joylist[joystick->index].logicalno;
769 joystick->nbuttons = layout->nbuttons;
770 joystick->nhats = layout->nhats;
771 joystick->naxes = layout->naxes;
772 joystick->nballs = layout->nballs;
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.
782 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
785 SDL_logical_joydecl(int realindex);
786 SDL_logical_joydecl(SDL_Joystick *realjoy = NULL);
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);
797 fd = realjoy->hwdata->fd;
800 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
802 SDL_joylist[joystick->index].joy = joystick;
804 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
808 SDL_SetError("Unable to open %s\n",
809 SDL_joylist[joystick->index]);
812 joystick->hwdata = (struct joystick_hwdata *)
813 SDL_malloc(sizeof(*joystick->hwdata));
814 if ( joystick->hwdata == NULL ) {
819 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
820 joystick->hwdata->fd = fd;
822 /* Set the joystick to non-blocking read mode */
823 fcntl(fd, F_SETFL, O_NONBLOCK);
825 /* Get the number of buttons and axes on the joystick */
826 #ifndef NO_LOGICAL_JOYSTICKS
828 ConfigLogicalJoystick(joystick);
831 #if SDL_INPUT_LINUXEV
832 if ( ! EV_ConfigJoystick(joystick, fd) )
834 JS_ConfigJoystick(joystick, fd);
839 #ifndef NO_LOGICAL_JOYSTICKS
841 static SDL_Joystick* FindLogicalJoystick(
842 SDL_Joystick *joystick, struct joystick_logical_mapping* v)
844 SDL_Joystick *logicaljoy;
850 /* get the fake joystick that will receive the event
854 if (SDL_joylist[i].logicalno == v->njoy) {
855 logicaljoy = SDL_joylist[i].joy;
859 if (SDL_joylist[i].next == 0)
862 i = SDL_joylist[i].next;
869 static int LogicalJoystickButton(
870 SDL_Joystick *joystick, Uint8 button, Uint8 state){
871 struct joystick_logical_mapping* buttons;
872 SDL_Joystick *logicaljoy = NULL;
874 /* if there's no map then this is just a regular joystick
876 if (SDL_joylist[joystick->index].map == NULL)
879 /* get the logical joystick that will receive the event
881 buttons = SDL_joylist[joystick->index].map->buttonmap+button;
882 logicaljoy = FindLogicalJoystick(joystick, buttons);
884 if (logicaljoy == NULL)
887 SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state);
892 static int LogicalJoystickAxis(
893 SDL_Joystick *joystick, Uint8 axis, Sint16 value)
895 struct joystick_logical_mapping* axes;
896 SDL_Joystick *logicaljoy = NULL;
898 /* if there's no map then this is just a regular joystick
900 if (SDL_joylist[joystick->index].map == NULL)
903 /* get the logical joystick that will receive the event
905 axes = SDL_joylist[joystick->index].map->axismap+axis;
906 logicaljoy = FindLogicalJoystick(joystick, axes);
908 if (logicaljoy == NULL)
911 SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value);
915 #endif /* USE_LOGICAL_JOYSTICKS */
918 void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
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 }
926 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL);
927 SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL);
929 the_hat = &stick->hwdata->hats[hat];
939 if ( value != the_hat->axis[axis] ) {
940 the_hat->axis[axis] = value;
942 #ifndef NO_LOGICAL_JOYSTICKS
943 /* if there's no map then this is just a regular joystick
945 if (SDL_joylist[stick->index].map != NULL) {
947 /* get the fake joystick that will receive the event
949 hats = SDL_joylist[stick->index].map->hatmap+hat;
950 logicaljoy = FindLogicalJoystick(stick, hats);
957 #endif /* USE_LOGICAL_JOYSTICKS */
959 SDL_PrivateJoystickHat(stick, hat,
960 position_map[the_hat->axis[1]][the_hat->axis[0]]);
965 void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
967 stick->hwdata->balls[ball].axis[axis] += value;
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.
975 static __inline__ void JS_HandleEvents(SDL_Joystick *joystick)
977 struct js_event events[32];
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);
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) {
994 if ( events[i].number < joystick->naxes ) {
995 #ifndef NO_LOGICAL_JOYSTICKS
996 if (!LogicalJoystickAxis(joystick,
997 events[i].number, events[i].value))
999 SDL_PrivateJoystickAxis(joystick,
1000 events[i].number, events[i].value);
1003 events[i].number -= joystick->naxes;
1004 other_axis = (events[i].number / 2);
1005 if ( other_axis < joystick->nhats ) {
1006 HandleHat(joystick, other_axis,
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,
1020 case JS_EVENT_BUTTON:
1021 #ifndef NO_LOGICAL_JOYSTICKS
1022 if (!LogicalJoystickButton(joystick,
1023 events[i].number, events[i].value))
1025 SDL_PrivateJoystickButton(joystick,
1026 events[i].number, events[i].value);
1035 #if SDL_INPUT_LINUXEV
1036 static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value)
1038 struct axis_correct *correct;
1040 correct = &joystick->hwdata->abs_correct[which];
1041 if ( correct->used ) {
1042 if ( value > correct->coef[0] ) {
1043 if ( value < correct->coef[1] ) {
1046 value -= correct->coef[1];
1048 value -= correct->coef[0];
1050 value *= correct->coef[2];
1054 /* Clamp and return */
1055 if ( value < -32768 ) return -32768;
1056 if ( value > 32767 ) return 32767;
1061 static __inline__ void EV_HandleEvents(SDL_Joystick *joystick)
1063 struct input_event events[32];
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);
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) {
1080 if ( code >= BTN_MISC ) {
1082 #ifndef NO_LOGICAL_JOYSTICKS
1083 if (!LogicalJoystickButton(joystick,
1084 joystick->hwdata->key_map[code],
1087 SDL_PrivateJoystickButton(joystick,
1088 joystick->hwdata->key_map[code],
1103 HandleHat(joystick, code/2, code%2,
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],
1113 SDL_PrivateJoystickAxis(joystick,
1114 joystick->hwdata->abs_map[code],
1124 HandleBall(joystick, code/2, code%2,
1137 #endif /* SDL_INPUT_LINUXEV */
1139 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
1143 #if SDL_INPUT_LINUXEV
1144 if ( joystick->hwdata->is_hid )
1145 EV_HandleEvents(joystick);
1148 JS_HandleEvents(joystick);
1150 /* Deliver ball motion updates */
1151 for ( i=0; i<joystick->nballs; ++i ) {
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);
1164 /* Function to close a joystick after use */
1165 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
1167 #ifndef NO_LOGICAL_JOYSTICKS
1169 if (SDL_joylist[joystick->index].fname == NULL) {
1170 SDL_joylist_head(i, joystick->index);
1171 SDL_JoystickClose(SDL_joylist[i].joy);
1175 if ( joystick->hwdata ) {
1176 #ifndef NO_LOGICAL_JOYSTICKS
1177 if (SDL_joylist[joystick->index].fname != NULL)
1179 close(joystick->hwdata->fd);
1180 if ( joystick->hwdata->hats ) {
1181 SDL_free(joystick->hwdata->hats);
1183 if ( joystick->hwdata->balls ) {
1184 SDL_free(joystick->hwdata->balls);
1186 SDL_free(joystick->hwdata);
1187 joystick->hwdata = NULL;
1191 /* Function to perform any system-specific joystick related cleanup */
1192 void SDL_SYS_JoystickQuit(void)
1196 for ( i=0; SDL_joylist[i].fname; ++i ) {
1197 SDL_free(SDL_joylist[i].fname);
1198 SDL_joylist[i].fname = NULL;
1202 #endif /* SDL_JOYSTICK_LINUX */