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