1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 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 #ifndef NO_LOGICAL_JOYSTICKS
63
64 /*
65 Some USB HIDs show up as a single joystick even though they actually
66 control 2 or more joysticks.
67 */
68 /*
69 This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can
70 be identified by their transparent blue design. It's quite trivial
71 to add other joysticks with similar quirky behavior.
72 -id
73 */
74
75 struct joystick_logical_mapping {
76 int njoy;
77 int nthing;
78 };
79
80 /*
81 {logical joy, logical axis},
82 {logical joy, logical hat},
83 {logical joy, logical ball},
84 {logical joy, logical button}
85 */
86
87 static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = {
88 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}
89 };
90 static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = {
91 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}
92 };
93
94 static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = {
95 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
96 {1,2},{1,3},{0,4},{0,5},{1,4},{1,5}
97 };
98 static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = {
99 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
100 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}
101 };
102
103 static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = {
104 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
105 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
106 {0,4},{0,5},{1,4},{1,5},{2,4},{2,5}
107 };
108 static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = {
109 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
110 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
111 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}
112 };
113
114 static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = {
115 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
116 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
117 {3,0},{3,1},{3,2},{3,3},{0,4},{0,5},
118 {1,4},{1,5},{2,4},{2,5},{3,4},{3,5}
119 };
120 static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = {
121 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
122 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
123 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},
124 {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11}
125 };
126
127 struct joystick_logical_layout {
128 int naxes;
129 int nhats;
130 int nballs;
131 int nbuttons;
132 };
133
134 static struct joystick_logical_layout mp88xx_1_logical_layout[] = {
135 {6, 0, 0, 12}
136 };
137 static struct joystick_logical_layout mp88xx_2_logical_layout[] = {
138 {6, 0, 0, 12},
139 {6, 0, 0, 12}
140 };
141 static struct joystick_logical_layout mp88xx_3_logical_layout[] = {
142 {6, 0, 0, 12},
143 {6, 0, 0, 12},
144 {6, 0, 0, 12}
145 };
146 static struct joystick_logical_layout mp88xx_4_logical_layout[] = {
147 {6, 0, 0, 12},
148 {6, 0, 0, 12},
149 {6, 0, 0, 12},
150 {6, 0, 0, 12}
151 };
152
153 /*
154 This array sets up a means of mapping a single physical joystick to
155 multiple logical joysticks. (djm)
156
157 njoys
158 the number of logical joysticks
159
160 layouts
161 an array of layout structures, one to describe each logical joystick
162
163 axes, hats, balls, buttons
164 arrays that map a physical thingy to a logical thingy
165 */
166 struct joystick_logicalmap {
167 const char *name;
168 int nbuttons;
169 int njoys;
170 struct joystick_logical_layout *layout;
171 struct joystick_logical_mapping *axismap;
172 struct joystick_logical_mapping *hatmap;
173 struct joystick_logical_mapping *ballmap;
174 struct joystick_logical_mapping *buttonmap;
175 };
176
177 static struct joystick_logicalmap joystick_logicalmap[] = {
178 {
179 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
180 12,
181 1,
182 mp88xx_1_logical_layout,
183 mp88xx_1_logical_axismap,
184 NULL,
185 NULL,
186 mp88xx_1_logical_buttonmap
187 },
188 {
189 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
190 24,
191 2,
192 mp88xx_2_logical_layout,
193 mp88xx_2_logical_axismap,
194 NULL,
195 NULL,
196 mp88xx_2_logical_buttonmap
197 },
198 {
199 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
200 12,
201 1,
202 mp88xx_1_logical_layout,
203 mp88xx_1_logical_axismap,
204 NULL,
205 NULL,
206 mp88xx_1_logical_buttonmap
207 },
208 {
209 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
210 24,
211 2,
212 mp88xx_2_logical_layout,
213 mp88xx_2_logical_axismap,
214 NULL,
215 NULL,
216 mp88xx_2_logical_buttonmap
217 },
218 {
219 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
220 36,
221 3,
222 mp88xx_3_logical_layout,
223 mp88xx_3_logical_axismap,
224 NULL,
225 NULL,
226 mp88xx_3_logical_buttonmap
227 },
228 {
229 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
230 48,
231 4,
232 mp88xx_4_logical_layout,
233 mp88xx_4_logical_axismap,
234 NULL,
235 NULL,
236 mp88xx_4_logical_buttonmap
237 }
238 };
239
240 /* find the head of a linked list, given a point in it
241 */
242 #define SDL_joylist_head(i, start)\
243 for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev;
244
245 #define SDL_logical_joydecl(d) d
246
247
248 #else
249
250 #define SDL_logical_joydecl(d)
251
252 #endif /* USE_LOGICAL_JOYSTICKS */
253
254 /* The maximum number of joysticks we'll detect */
255 #define MAX_JOYSTICKS 32
256
257 /* A list of available joysticks */
258 static struct
259 {
260 char* fname;
261 #ifndef NO_LOGICAL_JOYSTICKS
262 SDL_Joystick* joy;
263 struct joystick_logicalmap* map;
264 int prev;
265 int next;
266 int logicalno;
267 #endif /* USE_LOGICAL_JOYSTICKS */
268 } SDL_joylist[MAX_JOYSTICKS];
269
270
271 /* The private structure used to keep track of a joystick */
272 struct joystick_hwdata {
273 int fd;
274 /* The current linux joystick driver maps hats to two axes */
275 struct hwdata_hat {
276 int axis[2];
277 } *hats;
278 /* The current linux joystick driver maps balls to two axes */
279 struct hwdata_ball {
280 int axis[2];
281 } *balls;
282
283 /* Support for the Linux 2.4 unified input interface */
284 #if SDL_INPUT_LINUXEV
285 SDL_bool is_hid;
286 Uint8 key_map[KEY_MAX-BTN_MISC];
287 Uint8 abs_map[ABS_MAX];
288 struct axis_correct {
289 int used;
290 int coef[3];
291 } abs_correct[ABS_MAX];
292 #endif
293 };
294
295
296 #ifndef NO_LOGICAL_JOYSTICKS
297
CountLogicalJoysticks(int max)298 static int CountLogicalJoysticks(int max)
299 {
300 register int i, j, k, ret, prev;
301 const char* name;
302 int nbuttons, fd;
303 unsigned char n;
304
305 ret = 0;
306
307 for(i = 0; i < max; i++) {
308 name = SDL_SYS_JoystickName(i);
309
310 fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
311 if ( fd >= 0 ) {
312 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
313 nbuttons = -1;
314 } else {
315 nbuttons = n;
316 }
317 close(fd);
318 }
319 else {
320 nbuttons=-1;
321 }
322
323 if (name) {
324 for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) {
325 if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) {
326 prev = i;
327 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
328
329 for(k = 1; k < joystick_logicalmap[j].njoys; k++) {
330 SDL_joylist[prev].next = max + ret;
331 SDL_joylist[max+ret].prev = prev;
332
333 prev = max + ret;
334 SDL_joylist[prev].logicalno = k;
335 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
336 ret++;
337 }
338
339 break;
340 }
341 }
342 }
343 }
344
345 return ret;
346 }
347
LogicalSuffix(int logicalno,char * namebuf,int len)348 static void LogicalSuffix(int logicalno, char* namebuf, int len)
349 {
350 register int slen;
351 const static char suffixs[] =
352 "01020304050607080910111213141516171819"
353 "20212223242526272829303132";
354 const char* suffix;
355 slen = SDL_strlen(namebuf);
356 suffix = NULL;
357
358 if (logicalno*2<sizeof(suffixs))
359 suffix = suffixs + (logicalno*2);
360
361 if (slen + 4 < len && suffix) {
362 namebuf[slen++] = ' ';
363 namebuf[slen++] = '#';
364 namebuf[slen++] = suffix[0];
365 namebuf[slen++] = suffix[1];
366 namebuf[slen++] = 0;
367 }
368 }
369
370 #endif /* USE_LOGICAL_JOYSTICKS */
371
372 #if SDL_INPUT_LINUXEV
373 #define test_bit(nr, addr) \
374 (((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)
375
EV_IsJoystick(int fd)376 static int EV_IsJoystick(int fd)
377 {
378 unsigned long evbit[40];
379 unsigned long keybit[40];
380 unsigned long absbit[40];
381
382 if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
383 (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
384 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) {
385 return(0);
386 }
387 if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
388 test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) &&
389 (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0;
390 return(1);
391 }
392
393 #endif /* SDL_INPUT_LINUXEV */
394
395 /* Function to scan the system for joysticks */
SDL_SYS_JoystickInit(void)396 int SDL_SYS_JoystickInit(void)
397 {
398 /* The base path of the joystick devices */
399 const char *joydev_pattern[] = {
400 #if SDL_INPUT_LINUXEV
401 "/dev/input/event%d",
402 #endif
403 "/dev/input/js%d",
404 "/dev/js%d"
405 };
406 int numjoysticks;
407 int i, j;
408 int fd;
409 char path[PATH_MAX];
410 dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */
411 struct stat sb;
412 int n, duplicate;
413
414 numjoysticks = 0;
415
416 /* First see if the user specified a joystick to use */
417 if ( SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL ) {
418 SDL_strlcpy(path, SDL_getenv("SDL_JOYSTICK_DEVICE"), sizeof(path));
419 if ( stat(path, &sb) == 0 ) {
420 fd = open(path, O_RDONLY, 0);
421 if ( fd >= 0 ) {
422 /* Assume the user knows what they're doing. */
423 SDL_joylist[numjoysticks].fname = SDL_strdup(path);
424 if ( SDL_joylist[numjoysticks].fname ) {
425 dev_nums[numjoysticks] = sb.st_rdev;
426 ++numjoysticks;
427 }
428 close(fd);
429 }
430 }
431 }
432
433 for ( i=0; i<SDL_arraysize(joydev_pattern); ++i ) {
434 for ( j=0; j < MAX_JOYSTICKS; ++j ) {
435 SDL_snprintf(path, SDL_arraysize(path), joydev_pattern[i], j);
436
437 /* rcg06302000 replaced access(F_OK) call with stat().
438 * stat() will fail if the file doesn't exist, so it's
439 * equivalent behaviour.
440 */
441 if ( stat(path, &sb) == 0 ) {
442 /* Check to make sure it's not already in list.
443 * This happens when we see a stick via symlink.
444 */
445 duplicate = 0;
446 for (n=0; (n<numjoysticks) && !duplicate; ++n) {
447 if ( sb.st_rdev == dev_nums[n] ) {
448 duplicate = 1;
449 }
450 }
451 if (duplicate) {
452 continue;
453 }
454
455 fd = open(path, O_RDONLY, 0);
456 if ( fd < 0 ) {
457 continue;
458 }
459 #if SDL_INPUT_LINUXEV
460 #ifdef DEBUG_INPUT_EVENTS
461 printf("Checking %s\n", path);
462 #endif
463 if ( (i == 0) && ! EV_IsJoystick(fd) ) {
464 close(fd);
465 continue;
466 }
467 #endif
468 close(fd);
469
470 /* We're fine, add this joystick */
471 SDL_joylist[numjoysticks].fname = SDL_strdup(path);
472 if ( SDL_joylist[numjoysticks].fname ) {
473 dev_nums[numjoysticks] = sb.st_rdev;
474 ++numjoysticks;
475 }
476 } else
477 break;
478 }
479
480 #if SDL_INPUT_LINUXEV
481 /* This is a special case...
482 If the event devices are valid then the joystick devices
483 will be duplicates but without extra information about their
484 hats or balls. Unfortunately, the event devices can't
485 currently be calibrated, so it's a win-lose situation.
486 So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
487 */
488 if ( (i == 0) && (numjoysticks > 0) )
489 break;
490 #endif
491 }
492 #ifndef NO_LOGICAL_JOYSTICKS
493 numjoysticks += CountLogicalJoysticks(numjoysticks);
494 #endif
495
496 return(numjoysticks);
497 }
498
499 /* Function to get the device-dependent name of a joystick */
SDL_SYS_JoystickName(int index)500 const char *SDL_SYS_JoystickName(int index)
501 {
502 int fd;
503 static char namebuf[128];
504 char *name;
505 SDL_logical_joydecl(int oindex = index);
506
507 #ifndef NO_LOGICAL_JOYSTICKS
508 SDL_joylist_head(index, index);
509 #endif
510 name = NULL;
511 fd = open(SDL_joylist[index].fname, O_RDONLY, 0);
512 if ( fd >= 0 ) {
513 if (
514 #if SDL_INPUT_LINUXEV
515 (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) &&
516 #endif
517 (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) {
518 name = SDL_joylist[index].fname;
519 } else {
520 name = namebuf;
521 }
522 close(fd);
523
524
525 #ifndef NO_LOGICAL_JOYSTICKS
526 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex)
527 {
528 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128);
529 }
530 #endif
531 }
532 return name;
533 }
534
allocate_hatdata(SDL_Joystick * joystick)535 static int allocate_hatdata(SDL_Joystick *joystick)
536 {
537 int i;
538
539 joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(
540 joystick->nhats * sizeof(struct hwdata_hat));
541 if ( joystick->hwdata->hats == NULL ) {
542 return(-1);
543 }
544 for ( i=0; i<joystick->nhats; ++i ) {
545 joystick->hwdata->hats[i].axis[0] = 1;
546 joystick->hwdata->hats[i].axis[1] = 1;
547 }
548 return(0);
549 }
550
allocate_balldata(SDL_Joystick * joystick)551 static int allocate_balldata(SDL_Joystick *joystick)
552 {
553 int i;
554
555 joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc(
556 joystick->nballs * sizeof(struct hwdata_ball));
557 if ( joystick->hwdata->balls == NULL ) {
558 return(-1);
559 }
560 for ( i=0; i<joystick->nballs; ++i ) {
561 joystick->hwdata->balls[i].axis[0] = 0;
562 joystick->hwdata->balls[i].axis[1] = 0;
563 }
564 return(0);
565 }
566
JS_ConfigJoystick(SDL_Joystick * joystick,int fd)567 static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd)
568 {
569 SDL_bool handled;
570 unsigned char n;
571 int old_axes, tmp_naxes, tmp_nhats, tmp_nballs;
572 const char *name;
573 char *env, env_name[128];
574 int i;
575
576 handled = SDL_FALSE;
577
578 /* Default joystick device settings */
579 if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
580 joystick->naxes = 2;
581 } else {
582 joystick->naxes = n;
583 }
584 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
585 joystick->nbuttons = 2;
586 } else {
587 joystick->nbuttons = n;
588 }
589
590 name = SDL_SYS_JoystickName(joystick->index);
591 old_axes = joystick->naxes;
592
593 /* Generic analog joystick support */
594 if ( SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat") ) {
595 if ( SDL_sscanf(name,"Analog %d-axis %*d-button %d-hat",
596 &tmp_naxes, &tmp_nhats) == 2 ) {
597
598 joystick->naxes = tmp_naxes;
599 joystick->nhats = tmp_nhats;
600
601 handled = SDL_TRUE;
602 }
603 }
604
605 /* Special joystick support */
606 for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) {
607 if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) {
608
609 joystick->naxes = special_joysticks[i].naxes;
610 joystick->nhats = special_joysticks[i].nhats;
611 joystick->nballs = special_joysticks[i].nballs;
612
613 handled = SDL_TRUE;
614 break;
615 }
616 }
617
618 /* User environment joystick support */
619 if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) {
620 *env_name = '\0';
621 if ( *env == '\'' && SDL_sscanf(env, "'%[^']s'", env_name) == 1 )
622 env += SDL_strlen(env_name)+2;
623 else if ( SDL_sscanf(env, "%s", env_name) == 1 )
624 env += SDL_strlen(env_name);
625
626 if ( SDL_strcmp(name, env_name) == 0 ) {
627
628 if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats,
629 &tmp_nballs) == 3 ) {
630
631 joystick->naxes = tmp_naxes;
632 joystick->nhats = tmp_nhats;
633 joystick->nballs = tmp_nballs;
634
635 handled = SDL_TRUE;
636 }
637 }
638 }
639
640 /* Remap hats and balls */
641 if (handled) {
642 if ( joystick->nhats > 0 ) {
643 if ( allocate_hatdata(joystick) < 0 ) {
644 joystick->nhats = 0;
645 }
646 }
647 if ( joystick->nballs > 0 ) {
648 if ( allocate_balldata(joystick) < 0 ) {
649 joystick->nballs = 0;
650 }
651 }
652 }
653
654 return(handled);
655 }
656
657 #if SDL_INPUT_LINUXEV
658
EV_ConfigJoystick(SDL_Joystick * joystick,int fd)659 static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
660 {
661 int i, t;
662 unsigned long keybit[40];
663 unsigned long absbit[40];
664 unsigned long relbit[40];
665
666 /* See if this device uses the new unified event API */
667 if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
668 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
669 (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) {
670 joystick->hwdata->is_hid = SDL_TRUE;
671
672 /* Get the number of buttons, axes, and other thingamajigs */
673 for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) {
674 if ( test_bit(i, keybit) ) {
675 #ifdef DEBUG_INPUT_EVENTS
676 printf("Joystick has button: 0x%x\n", i);
677 #endif
678 joystick->hwdata->key_map[i-BTN_MISC] =
679 joystick->nbuttons;
680 ++joystick->nbuttons;
681 }
682 }
683 for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) {
684 if ( test_bit(i, keybit) ) {
685 #ifdef DEBUG_INPUT_EVENTS
686 printf("Joystick has button: 0x%x\n", i);
687 #endif
688 joystick->hwdata->key_map[i-BTN_MISC] =
689 joystick->nbuttons;
690 ++joystick->nbuttons;
691 }
692 }
693 for ( i=0; i<ABS_MAX; ++i ) {
694 /* Skip hats */
695 if ( i == ABS_HAT0X ) {
696 i = ABS_HAT3Y;
697 continue;
698 }
699 if ( test_bit(i, absbit) ) {
700 int values[5];
701
702 if ( ioctl(fd, EVIOCGABS(i), values) < 0 )
703 continue;
704 #ifdef DEBUG_INPUT_EVENTS
705 printf("Joystick has absolute axis: %x\n", i);
706 printf("Values = { %d, %d, %d, %d, %d }\n",
707 values[0], values[1],
708 values[2], values[3], values[4]);
709 #endif /* DEBUG_INPUT_EVENTS */
710 joystick->hwdata->abs_map[i] = joystick->naxes;
711 if ( values[1] == values[2] ) {
712 joystick->hwdata->abs_correct[i].used = 0;
713 } else {
714 joystick->hwdata->abs_correct[i].used = 1;
715 joystick->hwdata->abs_correct[i].coef[0] =
716 (values[2] + values[1]) / 2 - values[4];
717 joystick->hwdata->abs_correct[i].coef[1] =
718 (values[2] + values[1]) / 2 + values[4];
719 t = ((values[2] - values[1]) / 2 - 2 * values[4]);
720 if ( t != 0 ) {
721 joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t;
722 } else {
723 joystick->hwdata->abs_correct[i].coef[2] = 0;
724 }
725 }
726 ++joystick->naxes;
727 }
728 }
729 for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) {
730 if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) {
731 #ifdef DEBUG_INPUT_EVENTS
732 printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2);
733 #endif
734 ++joystick->nhats;
735 }
736 }
737 if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) {
738 ++joystick->nballs;
739 }
740
741 /* Allocate data to keep track of these thingamajigs */
742 if ( joystick->nhats > 0 ) {
743 if ( allocate_hatdata(joystick) < 0 ) {
744 joystick->nhats = 0;
745 }
746 }
747 if ( joystick->nballs > 0 ) {
748 if ( allocate_balldata(joystick) < 0 ) {
749 joystick->nballs = 0;
750 }
751 }
752 }
753 return(joystick->hwdata->is_hid);
754 }
755
756 #endif /* SDL_INPUT_LINUXEV */
757
758 #ifndef NO_LOGICAL_JOYSTICKS
ConfigLogicalJoystick(SDL_Joystick * joystick)759 static void ConfigLogicalJoystick(SDL_Joystick *joystick)
760 {
761 struct joystick_logical_layout* layout;
762
763 layout = SDL_joylist[joystick->index].map->layout +
764 SDL_joylist[joystick->index].logicalno;
765
766 joystick->nbuttons = layout->nbuttons;
767 joystick->nhats = layout->nhats;
768 joystick->naxes = layout->naxes;
769 joystick->nballs = layout->nballs;
770 }
771 #endif
772
773
774 /* Function to open a joystick for use.
775 The joystick to open is specified by the index field of the joystick.
776 This should fill the nbuttons and naxes fields of the joystick structure.
777 It returns 0, or -1 if there is an error.
778 */
SDL_SYS_JoystickOpen(SDL_Joystick * joystick)779 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
780 {
781 int fd;
782 SDL_logical_joydecl(int realindex);
783 SDL_logical_joydecl(SDL_Joystick *realjoy = NULL);
784
785 /* Open the joystick and set the joystick file descriptor */
786 #ifndef NO_LOGICAL_JOYSTICKS
787 if (SDL_joylist[joystick->index].fname == NULL) {
788 SDL_joylist_head(realindex, joystick->index);
789 realjoy = SDL_JoystickOpen(realindex);
790
791 if (realjoy == NULL)
792 return(-1);
793
794 fd = realjoy->hwdata->fd;
795
796 } else {
797 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
798 }
799 SDL_joylist[joystick->index].joy = joystick;
800 #else
801 fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
802 #endif
803
804 if ( fd < 0 ) {
805 SDL_SetError("Unable to open %s\n",
806 SDL_joylist[joystick->index]);
807 return(-1);
808 }
809 joystick->hwdata = (struct joystick_hwdata *)
810 SDL_malloc(sizeof(*joystick->hwdata));
811 if ( joystick->hwdata == NULL ) {
812 SDL_OutOfMemory();
813 close(fd);
814 return(-1);
815 }
816 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
817 joystick->hwdata->fd = fd;
818
819 /* Set the joystick to non-blocking read mode */
820 fcntl(fd, F_SETFL, O_NONBLOCK);
821
822 /* Get the number of buttons and axes on the joystick */
823 #ifndef NO_LOGICAL_JOYSTICKS
824 if (realjoy)
825 ConfigLogicalJoystick(joystick);
826 else
827 #endif
828 #if SDL_INPUT_LINUXEV
829 if ( ! EV_ConfigJoystick(joystick, fd) )
830 #endif
831 JS_ConfigJoystick(joystick, fd);
832
833 return(0);
834 }
835
836 #ifndef NO_LOGICAL_JOYSTICKS
837
FindLogicalJoystick(SDL_Joystick * joystick,struct joystick_logical_mapping * v)838 static SDL_Joystick* FindLogicalJoystick(
839 SDL_Joystick *joystick, struct joystick_logical_mapping* v)
840 {
841 SDL_Joystick *logicaljoy;
842 register int i;
843
844 i = joystick->index;
845 logicaljoy = NULL;
846
847 /* get the fake joystick that will receive the event
848 */
849 for(;;) {
850
851 if (SDL_joylist[i].logicalno == v->njoy) {
852 logicaljoy = SDL_joylist[i].joy;
853 break;
854 }
855
856 if (SDL_joylist[i].next == 0)
857 break;
858
859 i = SDL_joylist[i].next;
860
861 }
862
863 return logicaljoy;
864 }
865
LogicalJoystickButton(SDL_Joystick * joystick,Uint8 button,Uint8 state)866 static int LogicalJoystickButton(
867 SDL_Joystick *joystick, Uint8 button, Uint8 state){
868 struct joystick_logical_mapping* buttons;
869 SDL_Joystick *logicaljoy = NULL;
870
871 /* if there's no map then this is just a regular joystick
872 */
873 if (SDL_joylist[joystick->index].map == NULL)
874 return 0;
875
876 /* get the logical joystick that will receive the event
877 */
878 buttons = SDL_joylist[joystick->index].map->buttonmap+button;
879 logicaljoy = FindLogicalJoystick(joystick, buttons);
880
881 if (logicaljoy == NULL)
882 return 1;
883
884 SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state);
885
886 return 1;
887 }
888
LogicalJoystickAxis(SDL_Joystick * joystick,Uint8 axis,Sint16 value)889 static int LogicalJoystickAxis(
890 SDL_Joystick *joystick, Uint8 axis, Sint16 value)
891 {
892 struct joystick_logical_mapping* axes;
893 SDL_Joystick *logicaljoy = NULL;
894
895 /* if there's no map then this is just a regular joystick
896 */
897 if (SDL_joylist[joystick->index].map == NULL)
898 return 0;
899
900 /* get the logical joystick that will receive the event
901 */
902 axes = SDL_joylist[joystick->index].map->axismap+axis;
903 logicaljoy = FindLogicalJoystick(joystick, axes);
904
905 if (logicaljoy == NULL)
906 return 1;
907
908 SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value);
909
910 return 1;
911 }
912 #endif /* USE_LOGICAL_JOYSTICKS */
913
914 static __inline__
HandleHat(SDL_Joystick * stick,Uint8 hat,int axis,int value)915 void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
916 {
917 struct hwdata_hat *the_hat;
918 const Uint8 position_map[3][3] = {
919 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP },
920 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT },
921 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN }
922 };
923 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL);
924 SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL);
925
926 the_hat = &stick->hwdata->hats[hat];
927 if ( value < 0 ) {
928 value = 0;
929 } else
930 if ( value == 0 ) {
931 value = 1;
932 } else
933 if ( value > 0 ) {
934 value = 2;
935 }
936 if ( value != the_hat->axis[axis] ) {
937 the_hat->axis[axis] = value;
938
939 #ifndef NO_LOGICAL_JOYSTICKS
940 /* if there's no map then this is just a regular joystick
941 */
942 if (SDL_joylist[stick->index].map != NULL) {
943
944 /* get the fake joystick that will receive the event
945 */
946 hats = SDL_joylist[stick->index].map->hatmap+hat;
947 logicaljoy = FindLogicalJoystick(stick, hats);
948 }
949
950 if (logicaljoy) {
951 stick = logicaljoy;
952 hat = hats->nthing;
953 }
954 #endif /* USE_LOGICAL_JOYSTICKS */
955
956 SDL_PrivateJoystickHat(stick, hat,
957 position_map[the_hat->axis[1]][the_hat->axis[0]]);
958 }
959 }
960
961 static __inline__
HandleBall(SDL_Joystick * stick,Uint8 ball,int axis,int value)962 void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
963 {
964 stick->hwdata->balls[ball].axis[axis] += value;
965 }
966
967 /* Function to update the state of a joystick - called as a device poll.
968 * This function shouldn't update the joystick structure directly,
969 * but instead should call SDL_PrivateJoystick*() to deliver events
970 * and update joystick device state.
971 */
JS_HandleEvents(SDL_Joystick * joystick)972 static __inline__ void JS_HandleEvents(SDL_Joystick *joystick)
973 {
974 struct js_event events[32];
975 int i, len;
976 Uint8 other_axis;
977
978 #ifndef NO_LOGICAL_JOYSTICKS
979 if (SDL_joylist[joystick->index].fname == NULL) {
980 SDL_joylist_head(i, joystick->index);
981 JS_HandleEvents(SDL_joylist[i].joy);
982 return;
983 }
984 #endif
985
986 while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
987 len /= sizeof(events[0]);
988 for ( i=0; i<len; ++i ) {
989 switch (events[i].type & ~JS_EVENT_INIT) {
990 case JS_EVENT_AXIS:
991 if ( events[i].number < joystick->naxes ) {
992 #ifndef NO_LOGICAL_JOYSTICKS
993 if (!LogicalJoystickAxis(joystick,
994 events[i].number, events[i].value))
995 #endif
996 SDL_PrivateJoystickAxis(joystick,
997 events[i].number, events[i].value);
998 break;
999 }
1000 events[i].number -= joystick->naxes;
1001 other_axis = (events[i].number / 2);
1002 if ( other_axis < joystick->nhats ) {
1003 HandleHat(joystick, other_axis,
1004 events[i].number%2,
1005 events[i].value);
1006 break;
1007 }
1008 events[i].number -= joystick->nhats*2;
1009 other_axis = (events[i].number / 2);
1010 if ( other_axis < joystick->nballs ) {
1011 HandleBall(joystick, other_axis,
1012 events[i].number%2,
1013 events[i].value);
1014 break;
1015 }
1016 break;
1017 case JS_EVENT_BUTTON:
1018 #ifndef NO_LOGICAL_JOYSTICKS
1019 if (!LogicalJoystickButton(joystick,
1020 events[i].number, events[i].value))
1021 #endif
1022 SDL_PrivateJoystickButton(joystick,
1023 events[i].number, events[i].value);
1024 break;
1025 default:
1026 /* ?? */
1027 break;
1028 }
1029 }
1030 }
1031 }
1032 #if SDL_INPUT_LINUXEV
EV_AxisCorrect(SDL_Joystick * joystick,int which,int value)1033 static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value)
1034 {
1035 struct axis_correct *correct;
1036
1037 correct = &joystick->hwdata->abs_correct[which];
1038 if ( correct->used ) {
1039 if ( value > correct->coef[0] ) {
1040 if ( value < correct->coef[1] ) {
1041 return 0;
1042 }
1043 value -= correct->coef[1];
1044 } else {
1045 value -= correct->coef[0];
1046 }
1047 value *= correct->coef[2];
1048 value >>= 14;
1049 }
1050
1051 /* Clamp and return */
1052 if ( value < -32768 ) return -32768;
1053 if ( value > 32767 ) return 32767;
1054
1055 return value;
1056 }
1057
EV_HandleEvents(SDL_Joystick * joystick)1058 static __inline__ void EV_HandleEvents(SDL_Joystick *joystick)
1059 {
1060 struct input_event events[32];
1061 int i, len;
1062 int code;
1063
1064 #ifndef NO_LOGICAL_JOYSTICKS
1065 if (SDL_joylist[joystick->index].fname == NULL) {
1066 SDL_joylist_head(i, joystick->index);
1067 return EV_HandleEvents(SDL_joylist[i].joy);
1068 }
1069 #endif
1070
1071 while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1072 len /= sizeof(events[0]);
1073 for ( i=0; i<len; ++i ) {
1074 code = events[i].code;
1075 switch (events[i].type) {
1076 case EV_KEY:
1077 if ( code >= BTN_MISC ) {
1078 code -= BTN_MISC;
1079 #ifndef NO_LOGICAL_JOYSTICKS
1080 if (!LogicalJoystickButton(joystick,
1081 joystick->hwdata->key_map[code],
1082 events[i].value))
1083 #endif
1084 SDL_PrivateJoystickButton(joystick,
1085 joystick->hwdata->key_map[code],
1086 events[i].value);
1087 }
1088 break;
1089 case EV_ABS:
1090 switch (code) {
1091 case ABS_HAT0X:
1092 case ABS_HAT0Y:
1093 case ABS_HAT1X:
1094 case ABS_HAT1Y:
1095 case ABS_HAT2X:
1096 case ABS_HAT2Y:
1097 case ABS_HAT3X:
1098 case ABS_HAT3Y:
1099 code -= ABS_HAT0X;
1100 HandleHat(joystick, code/2, code%2,
1101 events[i].value);
1102 break;
1103 default:
1104 events[i].value = EV_AxisCorrect(joystick, code, events[i].value);
1105 #ifndef NO_LOGICAL_JOYSTICKS
1106 if (!LogicalJoystickAxis(joystick,
1107 joystick->hwdata->abs_map[code],
1108 events[i].value))
1109 #endif
1110 SDL_PrivateJoystickAxis(joystick,
1111 joystick->hwdata->abs_map[code],
1112 events[i].value);
1113 break;
1114 }
1115 break;
1116 case EV_REL:
1117 switch (code) {
1118 case REL_X:
1119 case REL_Y:
1120 code -= REL_X;
1121 HandleBall(joystick, code/2, code%2,
1122 events[i].value);
1123 break;
1124 default:
1125 break;
1126 }
1127 break;
1128 default:
1129 break;
1130 }
1131 }
1132 }
1133 }
1134 #endif /* SDL_INPUT_LINUXEV */
1135
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)1136 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
1137 {
1138 int i;
1139
1140 #if SDL_INPUT_LINUXEV
1141 if ( joystick->hwdata->is_hid )
1142 EV_HandleEvents(joystick);
1143 else
1144 #endif
1145 JS_HandleEvents(joystick);
1146
1147 /* Deliver ball motion updates */
1148 for ( i=0; i<joystick->nballs; ++i ) {
1149 int xrel, yrel;
1150
1151 xrel = joystick->hwdata->balls[i].axis[0];
1152 yrel = joystick->hwdata->balls[i].axis[1];
1153 if ( xrel || yrel ) {
1154 joystick->hwdata->balls[i].axis[0] = 0;
1155 joystick->hwdata->balls[i].axis[1] = 0;
1156 SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel);
1157 }
1158 }
1159 }
1160
1161 /* Function to close a joystick after use */
SDL_SYS_JoystickClose(SDL_Joystick * joystick)1162 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
1163 {
1164 #ifndef NO_LOGICAL_JOYSTICKS
1165 register int i;
1166 if (SDL_joylist[joystick->index].fname == NULL) {
1167 SDL_joylist_head(i, joystick->index);
1168 SDL_JoystickClose(SDL_joylist[i].joy);
1169 }
1170 #endif
1171
1172 if ( joystick->hwdata ) {
1173 #ifndef NO_LOGICAL_JOYSTICKS
1174 if (SDL_joylist[joystick->index].fname != NULL)
1175 #endif
1176 close(joystick->hwdata->fd);
1177 if ( joystick->hwdata->hats ) {
1178 SDL_free(joystick->hwdata->hats);
1179 }
1180 if ( joystick->hwdata->balls ) {
1181 SDL_free(joystick->hwdata->balls);
1182 }
1183 SDL_free(joystick->hwdata);
1184 joystick->hwdata = NULL;
1185 }
1186 }
1187
1188 /* Function to perform any system-specific joystick related cleanup */
SDL_SYS_JoystickQuit(void)1189 void SDL_SYS_JoystickQuit(void)
1190 {
1191 int i;
1192
1193 for ( i=0; SDL_joylist[i].fname; ++i ) {
1194 SDL_free(SDL_joylist[i].fname);
1195 }
1196 SDL_joylist[0].fname = NULL;
1197 }
1198
1199 #endif /* SDL_JOYSTICK_LINUX */
1200