Commit 241cf391 authored by Sam Lantinga's avatar Sam Lantinga

Linux joystick cleanups from Alan Swanson

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40555
parent 72f052bb
...@@ -48,33 +48,24 @@ static char rcsid = ...@@ -48,33 +48,24 @@ static char rcsid =
#include "SDL_sysjoystick.h" #include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h" #include "SDL_joystick_c.h"
/* Define this if you want to map axes to hats and trackballs */ /* Special joystick configurations */
#define FANCY_HATS_AND_BALLS static struct {
const char *name;
#ifdef FANCY_HATS_AND_BALLS int naxes;
/* Special joystick configurations: int nhats;
'JoystickName' Naxes Nhats Nballs int nballs;
*/ } special_joysticks[] = {
static const char *special_joysticks[] = { { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */
"'MadCatz Panther XL' 3 2 1", /* We don't handle a rudder (axis 8) */ { "SideWinder Precision Pro", 4, 1, 0 },
"'SideWinder Precision Pro' 4 1 0", { "SideWinder 3D Pro", 4, 1, 0 },
"'SideWinder 3D Pro' 4 1 0", { "Microsoft SideWinder 3D Pro", 4, 1, 0 },
"'Microsoft SideWinder 3D Pro' 4 1 0", { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 },
"'Microsoft SideWinder Dual Strike USB version 1.0' 2 1 0", { "WingMan Interceptor", 3, 3, 0 },
"'WingMan Interceptor' 3 3 0", { "WingMan Extreme Digital 3D", 4, 1, 0 },
/* WingMan Extreme Analog - not recognized by default { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 },
"'Analog 3-axis 4-button joystick' 2 1 0", { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 },
*/ { "Saitek Saitek X45", 6, 1, 0 }
"'WingMan Extreme Digital 3D' 4 1 0",
"'Analog 2-axis 4-button 1-hat FCS joystick' 2 1 0",
"'Microsoft SideWinder Precision 2 Joystick' 4 1 0",
"'Logitech Inc. WingMan Extreme Digital 3D' 4 1 0",
"'Saitek Saitek X45' 6 1 0",
NULL
}; };
#else
#undef USE_INPUT_EVENTS
#endif
/* The maximum number of joysticks we'll detect */ /* The maximum number of joysticks we'll detect */
#define MAX_JOYSTICKS 32 #define MAX_JOYSTICKS 32
...@@ -96,8 +87,8 @@ struct joystick_hwdata { ...@@ -96,8 +87,8 @@ struct joystick_hwdata {
} *balls; } *balls;
/* Support for the Linux 2.4 unified input interface */ /* Support for the Linux 2.4 unified input interface */
SDL_bool is_hid;
#ifdef USE_INPUT_EVENTS #ifdef USE_INPUT_EVENTS
SDL_bool is_hid;
Uint8 key_map[KEY_MAX-BTN_MISC]; Uint8 key_map[KEY_MAX-BTN_MISC];
Uint8 abs_map[ABS_MAX]; Uint8 abs_map[ABS_MAX];
struct axis_correct { struct axis_correct {
...@@ -146,14 +137,14 @@ int SDL_SYS_JoystickInit(void) ...@@ -146,14 +137,14 @@ int SDL_SYS_JoystickInit(void)
{ {
/* The base path of the joystick devices */ /* The base path of the joystick devices */
const char *joydev_pattern[] = { const char *joydev_pattern[] = {
"/dev/js%d",
#ifdef USE_INPUT_EVENTS #ifdef USE_INPUT_EVENTS
"/dev/input/event%d", "/dev/input/event%d",
#endif #endif
"/dev/input/js%d" "/dev/input/js%d",
"/dev/js%d"
}; };
int numjoysticks; int numjoysticks;
int i, j, done; int i, j;
int fd; int fd;
char path[PATH_MAX]; char path[PATH_MAX];
dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */
...@@ -179,9 +170,9 @@ int SDL_SYS_JoystickInit(void) ...@@ -179,9 +170,9 @@ int SDL_SYS_JoystickInit(void)
} }
} }
} }
for ( i=0; i<SDL_TABLESIZE(joydev_pattern); ++i ) { for ( i=0; i<SDL_TABLESIZE(joydev_pattern); ++i ) {
done = 0; for ( j=0; j < MAX_JOYSTICKS; ++j ) {
for ( j=0; (j < MAX_JOYSTICKS) && !done; ++j ) {
sprintf(path, joydev_pattern[i], j); sprintf(path, joydev_pattern[i], j);
/* rcg06302000 replaced access(F_OK) call with stat(). /* rcg06302000 replaced access(F_OK) call with stat().
...@@ -210,7 +201,7 @@ int SDL_SYS_JoystickInit(void) ...@@ -210,7 +201,7 @@ int SDL_SYS_JoystickInit(void)
#ifdef DEBUG_INPUT_EVENTS #ifdef DEBUG_INPUT_EVENTS
printf("Checking %s\n", path); printf("Checking %s\n", path);
#endif #endif
if ( (i > 0) && ! EV_IsJoystick(fd) ) { if ( (i == 0) && ! EV_IsJoystick(fd) ) {
close(fd); close(fd);
continue; continue;
} }
...@@ -223,20 +214,23 @@ int SDL_SYS_JoystickInit(void) ...@@ -223,20 +214,23 @@ int SDL_SYS_JoystickInit(void)
dev_nums[numjoysticks] = sb.st_rdev; dev_nums[numjoysticks] = sb.st_rdev;
++numjoysticks; ++numjoysticks;
} }
} else { } else
done = 1; break;
}
} }
#ifdef USE_INPUT_EVENTS
/* This is a special case... /* This is a special case...
If we're looking at the /dev/input event devices, and we found If the event devices are valid then the joystick devices
at least one, then we don't want to look at the input joystick will be duplicates but without extra information about their
devices, since they're built on top of devices that we've already hats or balls. Unfortunately, the event devices can't
seen, so we're done. currently be calibrated, so it's a win-lose situation.
So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
*/ */
if ( i > 0 && j > 0 ) { if ( (i == 0) && (numjoysticks > 0) )
done = 1; break;
} #endif
} }
return(numjoysticks); return(numjoysticks);
} }
...@@ -264,8 +258,6 @@ const char *SDL_SYS_JoystickName(int index) ...@@ -264,8 +258,6 @@ const char *SDL_SYS_JoystickName(int index)
return name; return name;
} }
#ifdef FANCY_HATS_AND_BALLS
static int allocate_hatdata(SDL_Joystick *joystick) static int allocate_hatdata(SDL_Joystick *joystick)
{ {
int i; int i;
...@@ -298,34 +290,84 @@ static int allocate_balldata(SDL_Joystick *joystick) ...@@ -298,34 +290,84 @@ static int allocate_balldata(SDL_Joystick *joystick)
return(0); return(0);
} }
static SDL_bool ConfigJoystick(SDL_Joystick *joystick, static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd)
const char *name, const char *config)
{ {
char cfg_name[128];
SDL_bool handled; SDL_bool handled;
unsigned char n;
int old_axes, tmp_naxes, tmp_nhats, tmp_nballs;
const char *name;
char *env, env_name[128];
int i;
handled = SDL_FALSE;
if ( config == NULL ) { /* Default joystick device settings */
return(SDL_FALSE); if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
joystick->naxes = 2;
} else {
joystick->naxes = n;
} }
strcpy(cfg_name, ""); if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
if ( *config == '\'' ) { joystick->nbuttons = 2;
sscanf(config, "'%[^']s'", cfg_name);
config += strlen(cfg_name)+2;
} else { } else {
sscanf(config, "%s", cfg_name); joystick->nbuttons = n;
config += strlen(cfg_name);
} }
handled = SDL_FALSE;
if ( strcmp(cfg_name, name) == 0 ) {
/* Get the number of axes, hats and balls for this joystick */
int joystick_axes = joystick->naxes;
sscanf(config, "%d %d %d",
&joystick->naxes, &joystick->nhats, &joystick->nballs);
/* Allocate the extra data for mapping them */ name = SDL_SYS_JoystickName(joystick->index);
old_axes = joystick->naxes;
/* Generic analog joystick support */
if ( strstr(name, "Analog") == name && strstr(name, "-hat") ) {
if ( sscanf(name,"Analog %d-axis %*d-button %d-hat",
&tmp_naxes, &tmp_nhats) == 2 ) {
joystick->naxes = tmp_naxes;
joystick->nhats = tmp_nhats;
handled = SDL_TRUE;
}
}
/* Special joystick support */
for ( i=0; i < SDL_TABLESIZE(special_joysticks); ++i ) {
if ( strcmp(name, special_joysticks[i].name) == 0 ) {
joystick->naxes = special_joysticks[i].naxes;
joystick->nhats = special_joysticks[i].nhats;
joystick->nballs = special_joysticks[i].nballs;
handled = SDL_TRUE;
break;
}
}
/* User environment joystick support */
if ( (env = getenv("SDL_LINUX_JOYSTICK")) ) {
strcpy(env_name, "");
if ( *env == '\'' && sscanf(env, "'%[^']s'", env_name) == 1 )
env += strlen(env_name)+2;
else if ( sscanf(env, "%s", env_name) == 1 )
env += strlen(env_name);
if ( strcmp(name, env_name) == 0 ) {
if ( sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats,
&tmp_nballs) == 3 ) {
joystick->naxes = tmp_naxes;
joystick->nhats = tmp_nhats;
joystick->nballs = tmp_nballs;
handled = SDL_TRUE;
}
}
}
/* Remap hats and balls */
if (handled) {
if ( joystick->nhats > 0 ) { if ( joystick->nhats > 0 ) {
/* HACK: Analog hats map to only one axis */ /* HACK: Analog hats map to only one axis */
if (joystick_axes == (joystick->naxes+joystick->nhats)){ if (old_axes == (joystick->naxes+joystick->nhats)){
joystick->hwdata->analog_hat = 1; joystick->hwdata->analog_hat = 1;
} else { } else {
if ( allocate_hatdata(joystick) < 0 ) { if ( allocate_hatdata(joystick) < 0 ) {
...@@ -339,8 +381,8 @@ static SDL_bool ConfigJoystick(SDL_Joystick *joystick, ...@@ -339,8 +381,8 @@ static SDL_bool ConfigJoystick(SDL_Joystick *joystick,
joystick->nballs = 0; joystick->nballs = 0;
} }
} }
handled = SDL_TRUE;
} }
return(handled); return(handled);
} }
...@@ -440,8 +482,6 @@ static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd) ...@@ -440,8 +482,6 @@ static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
#endif /* USE_INPUT_EVENTS */ #endif /* USE_INPUT_EVENTS */
#endif /* FANCY_HATS_AND_BALLS */
/* Function to open a joystick for use. /* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick. The joystick to open is specified by the index field of the joystick.
This should fill the nbuttons and naxes fields of the joystick structure. This should fill the nbuttons and naxes fields of the joystick structure.
...@@ -449,12 +489,7 @@ static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd) ...@@ -449,12 +489,7 @@ static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
*/ */
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
{ {
#ifdef FANCY_HATS_AND_BALLS
const char *name;
int i;
#endif
int fd; int fd;
unsigned char n;
/* Open the joystick and set the joystick file descriptor */ /* Open the joystick and set the joystick file descriptor */
fd = open(SDL_joylist[joystick->index], O_RDONLY, 0); fd = open(SDL_joylist[joystick->index], O_RDONLY, 0);
...@@ -480,31 +515,8 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) ...@@ -480,31 +515,8 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
#ifdef USE_INPUT_EVENTS #ifdef USE_INPUT_EVENTS
if ( ! EV_ConfigJoystick(joystick, fd) ) if ( ! EV_ConfigJoystick(joystick, fd) )
#endif #endif
{ JS_ConfigJoystick(joystick, fd);
if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
joystick->naxes = 2;
} else {
joystick->naxes = n;
}
if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
joystick->nbuttons = 2;
} else {
joystick->nbuttons = n;
}
#ifdef FANCY_HATS_AND_BALLS
/* Check for special joystick support */
name = SDL_SYS_JoystickName(joystick->index);
for ( i=0; special_joysticks[i]; ++i ) {
if (ConfigJoystick(joystick,name,special_joysticks[i])){
break;
}
}
if ( special_joysticks[i] == NULL ) {
ConfigJoystick(joystick, name,
getenv("SDL_LINUX_JOYSTICK"));
}
#endif /* FANCY_HATS_AND_BALLS */
}
return(0); return(0);
} }
...@@ -631,13 +643,11 @@ static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int valu ...@@ -631,13 +643,11 @@ static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int valu
value *= correct->coef[2]; value *= correct->coef[2];
value >>= 14; value >>= 14;
} }
/* Clamp and return */ /* Clamp and return */
if ( value < -32767 ) { if ( value < -32767 ) return -32767;
value = -32767; if ( value > 32767 ) return 32767;
} else
if ( value > 32767 ) {
value = 32767;
}
return value; return value;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment