src/joystick/linux/SDL_sysjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Oct 2001 21:34:50 +0000
changeset 211 0cc95f442f3a
parent 0 74212992fb08
child 221 50620ec9c86a
permissions -rw-r--r--
If we're looking at the /dev/input event devices, and we found
at least one, then we don't want to look at the input joystick
devices, since they're built on top of devices that we've already
seen, so we're done.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@devolution.com
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* This is the system specific header for the SDL joystick API */
    29 
    30 #include <stdio.h>		/* For the definition of NULL */
    31 #include <stdlib.h>		/* For getenv() prototype */
    32 #include <string.h>
    33 #include <sys/stat.h>
    34 #include <unistd.h>
    35 #include <fcntl.h>
    36 #include <sys/ioctl.h>
    37 #include <limits.h>		/* For the definition of PATH_MAX */
    38 
    39 #include <linux/joystick.h>
    40 #ifdef USE_INPUT_EVENTS
    41 #include <linux/input.h>
    42 #endif
    43 
    44 #include "SDL_error.h"
    45 #include "SDL_joystick.h"
    46 #include "SDL_sysjoystick.h"
    47 #include "SDL_joystick_c.h"
    48 
    49 /* Define this if you want to map axes to hats and trackballs */
    50 #define FANCY_HATS_AND_BALLS
    51 
    52 #ifdef FANCY_HATS_AND_BALLS
    53 /* Special joystick configurations:
    54 	'JoystickName' Naxes Nhats Nballs
    55  */
    56 static const char *special_joysticks[] = {
    57 	"'MadCatz Panther XL' 3 2 1", /* We don't handle a rudder (axis 8) */
    58 	"'SideWinder Precision Pro' 4 1 0",
    59 	"'SideWinder 3D Pro' 4 1 0",
    60 	"'Microsoft SideWinder 3D Pro' 4 1 0",
    61 	"'Microsoft SideWinder Dual Strike USB version 1.0' 2 1 0",
    62 	"'WingMan Interceptor' 3 3 0",
    63 	/* WingMan Extreme Analog - not recognized by default
    64 	"'Analog 3-axis 4-button joystick' 2 1",
    65 	*/
    66 	"'WingMan Extreme Digital 3D' 4 1 0",
    67 	NULL
    68 };
    69 #else
    70 #undef USE_INPUT_EVENTS
    71 #endif
    72 
    73 /* The maximum number of joysticks we'll detect */
    74 #define MAX_JOYSTICKS	32
    75 
    76 /* A list of available joysticks */
    77 static char *SDL_joylist[MAX_JOYSTICKS];
    78 
    79 /* The private structure used to keep track of a joystick */
    80 struct joystick_hwdata {
    81 	int fd;
    82 	/* The current linux joystick driver maps hats to two axes */
    83 	int analog_hat;		/* Well, except for analog hats */
    84 	struct hwdata_hat {
    85 		int axis[2];
    86 	} *hats;
    87 	/* The current linux joystick driver maps balls to two axes */
    88 	struct hwdata_ball {
    89 		int axis[2];
    90 	} *balls;
    91 
    92 	/* Support for the Linux 2.4 unified input interface */
    93 	SDL_bool is_hid;
    94 #ifdef USE_INPUT_EVENTS
    95 	Uint8 key_map[KEY_MAX-BTN_MISC];
    96 	Uint8 abs_map[ABS_MAX];
    97 	struct axis_correct {
    98 		int used;
    99 		int coef[3];
   100 	} abs_correct[ABS_MAX];
   101 #endif
   102 };
   103 
   104 static char *mystrdup(const char *string)
   105 {
   106 	char *newstring;
   107 
   108 	newstring = (char *)malloc(strlen(string)+1);
   109 	if ( newstring ) {
   110 		strcpy(newstring, string);
   111 	}
   112 	return(newstring);
   113 }
   114 
   115 #ifdef USE_INPUT_EVENTS
   116 #define test_bit(nr, addr) \
   117 	(((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)
   118 
   119 static int EV_IsJoystick(int fd)
   120 {
   121 	unsigned long evbit[40];
   122 	unsigned long keybit[40];
   123 	unsigned long absbit[40];
   124 
   125 	if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
   126 	     (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
   127 	     (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) {
   128 		return(0);
   129 	}
   130 	if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
   131 	      test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) &&
   132 	     (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0;
   133 	return(1);
   134 }
   135 
   136 #endif /* USE_INPUT_EVENTS */
   137 
   138 /* Function to scan the system for joysticks */
   139 int SDL_SYS_JoystickInit(void)
   140 {
   141 	/* The base path of the joystick devices */
   142 	const char *joydev_pattern[2] = {
   143 		"/dev/js%d",
   144 #ifdef USE_INPUT_EVENTS
   145 		"/dev/input/event%d"
   146 #endif
   147 		"/dev/input/js%d"
   148 	};
   149 	int numjoysticks;
   150 	int i, j, done;
   151 	int fd;
   152 	char path[PATH_MAX];
   153 	dev_t dev_nums[MAX_JOYSTICKS];  /* major/minor device numbers */
   154 	struct stat sb;
   155 	int n, duplicate;
   156 
   157 	numjoysticks = 0;
   158 
   159 	/* First see if the user specified a joystick to use */
   160 	if ( getenv("SDL_JOYSTICK_DEVICE") != NULL ) {
   161 		strncpy(path, getenv("SDL_JOYSTICK_DEVICE"), sizeof(path));
   162 		path[sizeof(path)-1] = '\0';
   163 		if ( stat(path, &sb) == 0 ) {
   164 			fd = open(path, O_RDONLY, 0);
   165 			if ( fd >= 0 ) {
   166 				/* Assume the user knows what they're doing. */
   167 				SDL_joylist[numjoysticks] = mystrdup(path);
   168 				if ( SDL_joylist[numjoysticks] ) {
   169 					dev_nums[numjoysticks] = sb.st_rdev;
   170 					++numjoysticks;
   171 				}
   172 				close(fd);
   173 			}
   174 		}
   175 	}
   176 	for ( i=0; i<SDL_TABLESIZE(joydev_pattern); ++i ) {
   177 		done = 0;
   178 		for ( j=0; (j < MAX_JOYSTICKS) && !done; ++j ) {
   179 			sprintf(path, joydev_pattern[i], j);
   180 
   181 			/* rcg06302000 replaced access(F_OK) call with stat().
   182 			 * stat() will fail if the file doesn't exist, so it's
   183 			 * equivalent behaviour.
   184 			 */
   185 			if ( stat(path, &sb) == 0 ) {
   186 				/* Check to make sure it's not already in list.
   187 				 * This happens when we see a stick via symlink.
   188 				 */
   189 				duplicate = 0;
   190 				for (n=0; (n<numjoysticks) && !duplicate; ++n) {
   191 					if ( sb.st_rdev == dev_nums[n] ) {
   192 						duplicate = 1;
   193 					}
   194 				}
   195 				if (duplicate) {
   196 					continue;
   197 				}
   198 
   199 				fd = open(path, O_RDONLY, 0);
   200 				if ( fd < 0 ) {
   201 					continue;
   202 				}
   203 #ifdef USE_INPUT_EVENTS
   204 #ifdef DEBUG_INPUT_EVENTS
   205 				printf("Checking %s\n", path);
   206 #endif
   207 				if ( (i > 0) && ! EV_IsJoystick(fd) ) {
   208 					close(fd);
   209 					continue;
   210 				}
   211 #endif
   212 				close(fd);
   213 
   214 				/* We're fine, add this joystick */
   215 				SDL_joylist[numjoysticks] = mystrdup(path);
   216 				if ( SDL_joylist[numjoysticks] ) {
   217 					dev_nums[numjoysticks] = sb.st_rdev;
   218 					++numjoysticks;
   219 				}
   220 			} else {
   221 				done = 1;
   222 			}
   223 		}
   224         /* This is a special case...
   225            If we're looking at the /dev/input event devices, and we found
   226            at least one, then we don't want to look at the input joystick
   227            devices, since they're built on top of devices that we've already
   228            seen, so we're done.
   229          */
   230         if ( i > 0 && j > 0 ) {
   231             done = 1;
   232         }
   233 	}
   234 	return(numjoysticks);
   235 }
   236 
   237 /* Function to get the device-dependent name of a joystick */
   238 const char *SDL_SYS_JoystickName(int index)
   239 {
   240 	int fd;
   241 	static char namebuf[128];
   242 	char *name;
   243 
   244 	name = NULL;
   245 	fd = open(SDL_joylist[index], O_RDONLY, 0);
   246 	if ( fd >= 0 ) {
   247 		if ( 
   248 #ifdef USE_INPUT_EVENTS
   249 		     (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) &&
   250 #endif
   251 		     (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) {
   252 			name = SDL_joylist[index];
   253 		} else {
   254 			name = namebuf;
   255 		}
   256 		close(fd);
   257 	}
   258 	return name;
   259 }
   260 
   261 #ifdef FANCY_HATS_AND_BALLS
   262 
   263 static int allocate_hatdata(SDL_Joystick *joystick)
   264 {
   265 	int i;
   266 
   267 	joystick->hwdata->hats = (struct hwdata_hat *)malloc(
   268 		joystick->nhats * sizeof(struct hwdata_hat));
   269 	if ( joystick->hwdata->hats == NULL ) {
   270 		return(-1);
   271 	}
   272 	for ( i=0; i<joystick->nhats; ++i ) {
   273 		joystick->hwdata->hats[i].axis[0] = 1;
   274 		joystick->hwdata->hats[i].axis[1] = 1;
   275 	}
   276 	return(0);
   277 }
   278 
   279 static int allocate_balldata(SDL_Joystick *joystick)
   280 {
   281 	int i;
   282 
   283 	joystick->hwdata->balls = (struct hwdata_ball *)malloc(
   284 		joystick->nballs * sizeof(struct hwdata_ball));
   285 	if ( joystick->hwdata->balls == NULL ) {
   286 		return(-1);
   287 	}
   288 	for ( i=0; i<joystick->nballs; ++i ) {
   289 		joystick->hwdata->balls[i].axis[0] = 0;
   290 		joystick->hwdata->balls[i].axis[1] = 0;
   291 	}
   292 	return(0);
   293 }
   294 
   295 static SDL_bool ConfigJoystick(SDL_Joystick *joystick,
   296 			const char *name, const char *config)
   297 {
   298 	char cfg_name[128];
   299 	SDL_bool handled;
   300 
   301 	if ( config == NULL ) {
   302 		return(SDL_FALSE);
   303 	}
   304 	strcpy(cfg_name, "");
   305 	if ( *config == '\'' ) {
   306 		sscanf(config, "'%[^']s'", cfg_name);
   307 		config += strlen(cfg_name)+2;
   308 	} else {
   309 		sscanf(config, "%s", cfg_name);
   310 		config += strlen(cfg_name);
   311 	}
   312 	handled = SDL_FALSE;
   313 	if ( strcmp(cfg_name, name) == 0 ) {
   314 		/* Get the number of axes, hats and balls for this joystick */
   315 		int joystick_axes = joystick->naxes;
   316 		sscanf(config, "%d %d %d", 
   317 			&joystick->naxes, &joystick->nhats, &joystick->nballs);
   318 
   319 		/* Allocate the extra data for mapping them */
   320 		if ( joystick->nhats > 0 ) {
   321 			/* HACK: Analog hats map to only one axis */
   322 			if (joystick_axes == (joystick->naxes+joystick->nhats)){
   323 				joystick->hwdata->analog_hat = 1;
   324 			} else {
   325 				if ( allocate_hatdata(joystick) < 0 ) {
   326 					joystick->nhats = 0;
   327 				}
   328 				joystick->hwdata->analog_hat = 0;
   329 			}
   330 		}
   331 		if ( joystick->nballs > 0 ) {
   332 			if ( allocate_balldata(joystick) < 0 ) {
   333 				joystick->nballs = 0;
   334 			}
   335 		}
   336 		handled = SDL_TRUE;
   337 	}
   338 	return(handled);
   339 }
   340 
   341 #ifdef USE_INPUT_EVENTS
   342 
   343 static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
   344 {
   345 	int i;
   346 	unsigned long keybit[40];
   347 	unsigned long absbit[40];
   348 	unsigned long relbit[40];
   349 
   350 	/* See if this device uses the new unified event API */
   351 	if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
   352 	     (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
   353 	     (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) {
   354 		joystick->hwdata->is_hid = SDL_TRUE;
   355 
   356 		/* Get the number of buttons, axes, and other thingamajigs */
   357 		for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) {
   358 			if ( test_bit(i, keybit) ) {
   359 #ifdef DEBUG_INPUT_EVENTS
   360 				printf("Joystick has button: 0x%x\n", i);
   361 #endif
   362 				joystick->hwdata->key_map[i-BTN_MISC] =
   363 						joystick->nbuttons;
   364 				++joystick->nbuttons;
   365 			}
   366 		}
   367 		for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) {
   368 			if ( test_bit(i, keybit) ) {
   369 #ifdef DEBUG_INPUT_EVENTS
   370 				printf("Joystick has button: 0x%x\n", i);
   371 #endif
   372 				joystick->hwdata->key_map[i-BTN_MISC] =
   373 						joystick->nbuttons;
   374 				++joystick->nbuttons;
   375 			}
   376 		}
   377 		for ( i=0; i<ABS_MAX; ++i ) {
   378 			/* Skip hats */
   379 			if ( i == ABS_HAT0X ) {
   380 				i = ABS_HAT3Y;
   381 				continue;
   382 			}
   383 			if ( test_bit(i, absbit) ) {
   384 				int values[5];
   385 
   386 				ioctl(fd, EVIOCGABS(i), values);
   387 #ifdef DEBUG_INPUT_EVENTS
   388 				printf("Joystick has absolute axis: %x\n", i);
   389 				printf("Values = { %d, %d, %d, %d, %d }\n",
   390 					values[0], values[1],
   391 					values[2], values[3], values[4]);
   392 #endif /* DEBUG_INPUT_EVENTS */
   393 				joystick->hwdata->abs_map[i] = joystick->naxes;
   394 				if ( values[1] == values[2] ) {
   395 				    joystick->hwdata->abs_correct[i].used = 0;
   396 				} else {
   397 				    joystick->hwdata->abs_correct[i].used = 1;
   398 				    joystick->hwdata->abs_correct[i].coef[0] =
   399 					(values[2] + values[1]) / 2 - values[4];
   400 				    joystick->hwdata->abs_correct[i].coef[1] =
   401 					(values[2] + values[1]) / 2 + values[4];
   402 				    joystick->hwdata->abs_correct[i].coef[2] =
   403 					(1 << 29) / ((values[2] - values[1]) / 2 - 2 * values[4]);
   404 				}
   405 				++joystick->naxes;
   406 			}
   407 		}
   408 		for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) {
   409 			if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) {
   410 #ifdef DEBUG_INPUT_EVENTS
   411 				printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2);
   412 #endif
   413 				++joystick->nhats;
   414 			}
   415 		}
   416 		if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) {
   417 			++joystick->nballs;
   418 		}
   419 
   420 		/* Allocate data to keep track of these thingamajigs */
   421 		if ( joystick->nhats > 0 ) {
   422 			if ( allocate_hatdata(joystick) < 0 ) {
   423 				joystick->nhats = 0;
   424 			}
   425 		}
   426 		if ( joystick->nballs > 0 ) {
   427 			if ( allocate_balldata(joystick) < 0 ) {
   428 				joystick->nballs = 0;
   429 			}
   430 		}
   431 	}
   432 	return(joystick->hwdata->is_hid);
   433 }
   434 
   435 #endif /* USE_INPUT_EVENTS */
   436 
   437 #endif /* FANCY_HATS_AND_BALLS */
   438 
   439 /* Function to open a joystick for use.
   440    The joystick to open is specified by the index field of the joystick.
   441    This should fill the nbuttons and naxes fields of the joystick structure.
   442    It returns 0, or -1 if there is an error.
   443  */
   444 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
   445 {
   446 #ifdef FANCY_HATS_AND_BALLS
   447 	const char *name;
   448 	int i;
   449 #endif
   450 	int fd;
   451 	unsigned char n;
   452 
   453 	/* Open the joystick and set the joystick file descriptor */
   454 	fd = open(SDL_joylist[joystick->index], O_RDONLY, 0);
   455 	if ( fd < 0 ) {
   456 		SDL_SetError("Unable to open %s\n",
   457 		             SDL_joylist[joystick->index]);
   458 		return(-1);
   459 	}
   460 	joystick->hwdata = (struct joystick_hwdata *)
   461 	                   malloc(sizeof(*joystick->hwdata));
   462 	if ( joystick->hwdata == NULL ) {
   463 		SDL_OutOfMemory();
   464 		close(fd);
   465 		return(-1);
   466 	}
   467 	memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
   468 	joystick->hwdata->fd = fd;
   469 
   470 	/* Set the joystick to non-blocking read mode */
   471 	fcntl(fd, F_SETFL, O_NONBLOCK);
   472 
   473 	/* Get the number of buttons and axes on the joystick */
   474 #ifdef USE_INPUT_EVENTS
   475 	if ( ! EV_ConfigJoystick(joystick, fd) )
   476 #endif
   477 	{
   478 		if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
   479 			joystick->naxes = 2;
   480 		} else {
   481 			joystick->naxes = n;
   482 		}
   483 		if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
   484 			joystick->nbuttons = 2;
   485 		} else {
   486 			joystick->nbuttons = n;
   487 		}
   488 #ifdef FANCY_HATS_AND_BALLS
   489 		/* Check for special joystick support */
   490 		name = SDL_SYS_JoystickName(joystick->index);
   491 		for ( i=0; special_joysticks[i]; ++i ) {
   492 			if (ConfigJoystick(joystick,name,special_joysticks[i])){
   493 				break;
   494 			}
   495 		}
   496 		if ( special_joysticks[i] == NULL ) {
   497 			ConfigJoystick(joystick, name,
   498 					getenv("SDL_LINUX_JOYSTICK"));
   499 		}
   500 #endif /* FANCY_HATS_AND_BALLS */
   501 	}
   502 	return(0);
   503 }
   504 
   505 static __inline__
   506 void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
   507 {
   508 	struct hwdata_hat *the_hat;
   509 	const Uint8 position_map[3][3] = {
   510 		{ SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP },
   511 		{ SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT },
   512 		{ SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN }
   513 	};
   514 
   515 	the_hat = &stick->hwdata->hats[hat];
   516 	if ( value < 0 ) {
   517 		value = 0;
   518 	} else
   519 	if ( value == 0 ) {
   520 		value = 1;
   521 	} else
   522 	if ( value > 0 ) {
   523 		value = 2;
   524 	}
   525 	if ( value != the_hat->axis[axis] ) {
   526 		the_hat->axis[axis] = value;
   527 		SDL_PrivateJoystickHat(stick, hat,
   528 			position_map[the_hat->axis[1]][the_hat->axis[0]]);
   529 	}
   530 }
   531 
   532 /* This was necessary for the Wingman Extreme Analog joystick */
   533 static __inline__
   534 void HandleAnalogHat(SDL_Joystick *stick, Uint8 hat, int value)
   535 {
   536 	const Uint8 position_map[] = {
   537 		SDL_HAT_UP,
   538 		SDL_HAT_RIGHT,
   539 		SDL_HAT_DOWN,
   540 		SDL_HAT_LEFT,
   541 		SDL_HAT_CENTERED
   542 	};
   543 	SDL_PrivateJoystickHat(stick, hat, position_map[(value/16000)+2]);
   544 }
   545 
   546 static __inline__
   547 void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
   548 {
   549 	stick->hwdata->balls[ball].axis[axis] += value;
   550 }
   551 
   552 /* Function to update the state of a joystick - called as a device poll.
   553  * This function shouldn't update the joystick structure directly,
   554  * but instead should call SDL_PrivateJoystick*() to deliver events
   555  * and update joystick device state.
   556  */
   557 static __inline__ void JS_HandleEvents(SDL_Joystick *joystick)
   558 {
   559 	struct js_event events[32];
   560 	int i, len;
   561 	Uint8 other_axis;
   562 
   563 	while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
   564 		len /= sizeof(events[0]);
   565 		for ( i=0; i<len; ++i ) {
   566 			switch (events[i].type & ~JS_EVENT_INIT) {
   567 			    case JS_EVENT_AXIS:
   568 				if ( events[i].number < joystick->naxes ) {
   569 					SDL_PrivateJoystickAxis(joystick,
   570 				           events[i].number, events[i].value);
   571 					break;
   572 				}
   573 				events[i].number -= joystick->naxes;
   574 				if ( joystick->hwdata->analog_hat ) {
   575 					other_axis = events[i].number;
   576 					if ( other_axis < joystick->nhats ) {
   577 						HandleAnalogHat(joystick, other_axis,
   578 							events[i].value);
   579 						break;
   580 					}
   581 				} else {
   582 					other_axis = (events[i].number / 2);
   583 					if ( other_axis < joystick->nhats ) {
   584 						HandleHat(joystick, other_axis,
   585 							events[i].number%2,
   586 							events[i].value);
   587 						break;
   588 					}
   589 				}
   590 				events[i].number -= joystick->nhats*2;
   591 				other_axis = (events[i].number / 2);
   592 				if ( other_axis < joystick->nballs ) {
   593 					HandleBall(joystick, other_axis,
   594 						events[i].number%2,
   595 						events[i].value);
   596 					break;
   597 				}
   598 				break;
   599 			    case JS_EVENT_BUTTON:
   600 				SDL_PrivateJoystickButton(joystick,
   601 				           events[i].number, events[i].value);
   602 				break;
   603 			    default:
   604 				/* ?? */
   605 				break;
   606 			}
   607 		}
   608 	}
   609 }
   610 #ifdef USE_INPUT_EVENTS
   611 static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value)
   612 {
   613 	struct axis_correct *correct;
   614 
   615 	correct = &joystick->hwdata->abs_correct[which];
   616 	if ( correct->used ) {
   617 		if ( value > correct->coef[0] ) {
   618 			if ( value < correct->coef[1] ) {
   619 				return 0;
   620 			}
   621 			value -= correct->coef[1];
   622 		} else {
   623 			value -= correct->coef[0];
   624 		}
   625 		value *= correct->coef[2];
   626 		value >>= 14;
   627 	}
   628 	/* Clamp and return */
   629 	if ( value < -32767 ) {
   630 		value = -32767;
   631 	} else
   632 	if ( value > 32767 ) {
   633 		value = 32767;
   634 	}
   635 	return value;
   636 }
   637 
   638 static __inline__ void EV_HandleEvents(SDL_Joystick *joystick)
   639 {
   640 	struct input_event events[32];
   641 	int i, len;
   642 	int code;
   643 
   644 	while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
   645 		len /= sizeof(events[0]);
   646 		for ( i=0; i<len; ++i ) {
   647 			code = events[i].code;
   648 			switch (events[i].type) {
   649 			    case EV_KEY:
   650 				if ( code >= BTN_MISC ) {
   651 					code -= BTN_MISC;
   652 					SDL_PrivateJoystickButton(joystick,
   653 				           joystick->hwdata->key_map[code],
   654 					   events[i].value);
   655 				}
   656 				break;
   657 			    case EV_ABS:
   658 				switch (code) {
   659 				    case ABS_HAT0X:
   660 				    case ABS_HAT0Y:
   661 				    case ABS_HAT1X:
   662 				    case ABS_HAT1Y:
   663 				    case ABS_HAT2X:
   664 				    case ABS_HAT2Y:
   665 				    case ABS_HAT3X:
   666 				    case ABS_HAT3Y:
   667 					code -= ABS_HAT0X;
   668 					HandleHat(joystick, code/2, code%2,
   669 							events[i].value);
   670 					break;
   671 				    default:
   672 					events[i].value = EV_AxisCorrect(joystick, code, events[i].value);
   673 					SDL_PrivateJoystickAxis(joystick,
   674 				           joystick->hwdata->abs_map[code],
   675 					   events[i].value);
   676 					break;
   677 				}
   678 				break;
   679 			    case EV_REL:
   680 				switch (code) {
   681 				    case REL_X:
   682 				    case REL_Y:
   683 					code -= REL_X;
   684 					HandleBall(joystick, code/2, code%2,
   685 							events[i].value);
   686 					break;
   687 				    default:
   688 					break;
   689 				}
   690 				break;
   691 			    default:
   692 				break;
   693 			}
   694 		}
   695 	}
   696 }
   697 #endif /* USE_INPUT_EVENTS */
   698 
   699 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
   700 {
   701 	int i;
   702 	
   703 #ifdef USE_INPUT_EVENTS
   704 	if ( joystick->hwdata->is_hid )
   705 		EV_HandleEvents(joystick);
   706 	else
   707 #endif
   708 		JS_HandleEvents(joystick);
   709 
   710 	/* Deliver ball motion updates */
   711 	for ( i=0; i<joystick->nballs; ++i ) {
   712 		int xrel, yrel;
   713 
   714 		xrel = joystick->hwdata->balls[i].axis[0];
   715 		yrel = joystick->hwdata->balls[i].axis[1];
   716 		if ( xrel || yrel ) {
   717 			joystick->hwdata->balls[i].axis[0] = 0;
   718 			joystick->hwdata->balls[i].axis[1] = 0;
   719 			SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel);
   720 		}
   721 	}
   722 }
   723 
   724 /* Function to close a joystick after use */
   725 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
   726 {
   727 	if ( joystick->hwdata ) {
   728 		close(joystick->hwdata->fd);
   729 		if ( joystick->hwdata->hats ) {
   730 			free(joystick->hwdata->hats);
   731 		}
   732 		if ( joystick->hwdata->balls ) {
   733 			free(joystick->hwdata->balls);
   734 		}
   735 		free(joystick->hwdata);
   736 		joystick->hwdata = NULL;
   737 	}
   738 }
   739 
   740 /* Function to perform any system-specific joystick related cleanup */
   741 void SDL_SYS_JoystickQuit(void)
   742 {
   743 	int i;
   744 
   745 	for ( i=0; SDL_joylist[i]; ++i ) {
   746 		free(SDL_joylist[i]);
   747 	}
   748 	SDL_joylist[0] = NULL;
   749 }
   750