• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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