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