Mercurial > sdl-ios-xcode
comparison src/joystick/linux/SDL_sysjoystick.c @ 554:38b1a98aeb11
Linux joystick cleanups from Alan Swanson
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 02 Dec 2002 03:11:36 +0000 |
parents | b2c97d579dfe |
children | 2e58ece48b61 |
comparison
equal
deleted
inserted
replaced
553:417f8709e648 | 554:38b1a98aeb11 |
---|---|
46 #include "SDL_error.h" | 46 #include "SDL_error.h" |
47 #include "SDL_joystick.h" | 47 #include "SDL_joystick.h" |
48 #include "SDL_sysjoystick.h" | 48 #include "SDL_sysjoystick.h" |
49 #include "SDL_joystick_c.h" | 49 #include "SDL_joystick_c.h" |
50 | 50 |
51 /* Define this if you want to map axes to hats and trackballs */ | 51 /* Special joystick configurations */ |
52 #define FANCY_HATS_AND_BALLS | 52 static struct { |
53 | 53 const char *name; |
54 #ifdef FANCY_HATS_AND_BALLS | 54 int naxes; |
55 /* Special joystick configurations: | 55 int nhats; |
56 'JoystickName' Naxes Nhats Nballs | 56 int nballs; |
57 */ | 57 } special_joysticks[] = { |
58 static const char *special_joysticks[] = { | 58 { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */ |
59 "'MadCatz Panther XL' 3 2 1", /* We don't handle a rudder (axis 8) */ | 59 { "SideWinder Precision Pro", 4, 1, 0 }, |
60 "'SideWinder Precision Pro' 4 1 0", | 60 { "SideWinder 3D Pro", 4, 1, 0 }, |
61 "'SideWinder 3D Pro' 4 1 0", | 61 { "Microsoft SideWinder 3D Pro", 4, 1, 0 }, |
62 "'Microsoft SideWinder 3D Pro' 4 1 0", | 62 { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 }, |
63 "'Microsoft SideWinder Dual Strike USB version 1.0' 2 1 0", | 63 { "WingMan Interceptor", 3, 3, 0 }, |
64 "'WingMan Interceptor' 3 3 0", | 64 { "WingMan Extreme Digital 3D", 4, 1, 0 }, |
65 /* WingMan Extreme Analog - not recognized by default | 65 { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 }, |
66 "'Analog 3-axis 4-button joystick' 2 1 0", | 66 { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 }, |
67 */ | 67 { "Saitek Saitek X45", 6, 1, 0 } |
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 }; | 68 }; |
75 #else | |
76 #undef USE_INPUT_EVENTS | |
77 #endif | |
78 | 69 |
79 /* The maximum number of joysticks we'll detect */ | 70 /* The maximum number of joysticks we'll detect */ |
80 #define MAX_JOYSTICKS 32 | 71 #define MAX_JOYSTICKS 32 |
81 | 72 |
82 /* A list of available joysticks */ | 73 /* A list of available joysticks */ |
94 struct hwdata_ball { | 85 struct hwdata_ball { |
95 int axis[2]; | 86 int axis[2]; |
96 } *balls; | 87 } *balls; |
97 | 88 |
98 /* Support for the Linux 2.4 unified input interface */ | 89 /* Support for the Linux 2.4 unified input interface */ |
90 #ifdef USE_INPUT_EVENTS | |
99 SDL_bool is_hid; | 91 SDL_bool is_hid; |
100 #ifdef USE_INPUT_EVENTS | |
101 Uint8 key_map[KEY_MAX-BTN_MISC]; | 92 Uint8 key_map[KEY_MAX-BTN_MISC]; |
102 Uint8 abs_map[ABS_MAX]; | 93 Uint8 abs_map[ABS_MAX]; |
103 struct axis_correct { | 94 struct axis_correct { |
104 int used; | 95 int used; |
105 int coef[3]; | 96 int coef[3]; |
144 /* Function to scan the system for joysticks */ | 135 /* Function to scan the system for joysticks */ |
145 int SDL_SYS_JoystickInit(void) | 136 int SDL_SYS_JoystickInit(void) |
146 { | 137 { |
147 /* The base path of the joystick devices */ | 138 /* The base path of the joystick devices */ |
148 const char *joydev_pattern[] = { | 139 const char *joydev_pattern[] = { |
149 "/dev/js%d", | |
150 #ifdef USE_INPUT_EVENTS | 140 #ifdef USE_INPUT_EVENTS |
151 "/dev/input/event%d", | 141 "/dev/input/event%d", |
152 #endif | 142 #endif |
153 "/dev/input/js%d" | 143 "/dev/input/js%d", |
144 "/dev/js%d" | |
154 }; | 145 }; |
155 int numjoysticks; | 146 int numjoysticks; |
156 int i, j, done; | 147 int i, j; |
157 int fd; | 148 int fd; |
158 char path[PATH_MAX]; | 149 char path[PATH_MAX]; |
159 dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ | 150 dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ |
160 struct stat sb; | 151 struct stat sb; |
161 int n, duplicate; | 152 int n, duplicate; |
177 } | 168 } |
178 close(fd); | 169 close(fd); |
179 } | 170 } |
180 } | 171 } |
181 } | 172 } |
173 | |
182 for ( i=0; i<SDL_TABLESIZE(joydev_pattern); ++i ) { | 174 for ( i=0; i<SDL_TABLESIZE(joydev_pattern); ++i ) { |
183 done = 0; | 175 for ( j=0; j < MAX_JOYSTICKS; ++j ) { |
184 for ( j=0; (j < MAX_JOYSTICKS) && !done; ++j ) { | |
185 sprintf(path, joydev_pattern[i], j); | 176 sprintf(path, joydev_pattern[i], j); |
186 | 177 |
187 /* rcg06302000 replaced access(F_OK) call with stat(). | 178 /* rcg06302000 replaced access(F_OK) call with stat(). |
188 * stat() will fail if the file doesn't exist, so it's | 179 * stat() will fail if the file doesn't exist, so it's |
189 * equivalent behaviour. | 180 * equivalent behaviour. |
208 } | 199 } |
209 #ifdef USE_INPUT_EVENTS | 200 #ifdef USE_INPUT_EVENTS |
210 #ifdef DEBUG_INPUT_EVENTS | 201 #ifdef DEBUG_INPUT_EVENTS |
211 printf("Checking %s\n", path); | 202 printf("Checking %s\n", path); |
212 #endif | 203 #endif |
213 if ( (i > 0) && ! EV_IsJoystick(fd) ) { | 204 if ( (i == 0) && ! EV_IsJoystick(fd) ) { |
214 close(fd); | 205 close(fd); |
215 continue; | 206 continue; |
216 } | 207 } |
217 #endif | 208 #endif |
218 close(fd); | 209 close(fd); |
221 SDL_joylist[numjoysticks] = mystrdup(path); | 212 SDL_joylist[numjoysticks] = mystrdup(path); |
222 if ( SDL_joylist[numjoysticks] ) { | 213 if ( SDL_joylist[numjoysticks] ) { |
223 dev_nums[numjoysticks] = sb.st_rdev; | 214 dev_nums[numjoysticks] = sb.st_rdev; |
224 ++numjoysticks; | 215 ++numjoysticks; |
225 } | 216 } |
226 } else { | 217 } else |
227 done = 1; | 218 break; |
228 } | 219 } |
229 } | 220 |
230 /* This is a special case... | 221 #ifdef USE_INPUT_EVENTS |
231 If we're looking at the /dev/input event devices, and we found | 222 /* This is a special case... |
232 at least one, then we don't want to look at the input joystick | 223 If the event devices are valid then the joystick devices |
233 devices, since they're built on top of devices that we've already | 224 will be duplicates but without extra information about their |
234 seen, so we're done. | 225 hats or balls. Unfortunately, the event devices can't |
235 */ | 226 currently be calibrated, so it's a win-lose situation. |
236 if ( i > 0 && j > 0 ) { | 227 So : /dev/input/eventX = /dev/input/jsY = /dev/jsY |
237 done = 1; | 228 */ |
238 } | 229 if ( (i == 0) && (numjoysticks > 0) ) |
239 } | 230 break; |
231 #endif | |
232 } | |
233 | |
240 return(numjoysticks); | 234 return(numjoysticks); |
241 } | 235 } |
242 | 236 |
243 /* Function to get the device-dependent name of a joystick */ | 237 /* Function to get the device-dependent name of a joystick */ |
244 const char *SDL_SYS_JoystickName(int index) | 238 const char *SDL_SYS_JoystickName(int index) |
262 close(fd); | 256 close(fd); |
263 } | 257 } |
264 return name; | 258 return name; |
265 } | 259 } |
266 | 260 |
267 #ifdef FANCY_HATS_AND_BALLS | |
268 | |
269 static int allocate_hatdata(SDL_Joystick *joystick) | 261 static int allocate_hatdata(SDL_Joystick *joystick) |
270 { | 262 { |
271 int i; | 263 int i; |
272 | 264 |
273 joystick->hwdata->hats = (struct hwdata_hat *)malloc( | 265 joystick->hwdata->hats = (struct hwdata_hat *)malloc( |
296 joystick->hwdata->balls[i].axis[1] = 0; | 288 joystick->hwdata->balls[i].axis[1] = 0; |
297 } | 289 } |
298 return(0); | 290 return(0); |
299 } | 291 } |
300 | 292 |
301 static SDL_bool ConfigJoystick(SDL_Joystick *joystick, | 293 static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd) |
302 const char *name, const char *config) | 294 { |
303 { | |
304 char cfg_name[128]; | |
305 SDL_bool handled; | 295 SDL_bool handled; |
306 | 296 unsigned char n; |
307 if ( config == NULL ) { | 297 int old_axes, tmp_naxes, tmp_nhats, tmp_nballs; |
308 return(SDL_FALSE); | 298 const char *name; |
309 } | 299 char *env, env_name[128]; |
310 strcpy(cfg_name, ""); | 300 int i; |
311 if ( *config == '\'' ) { | 301 |
312 sscanf(config, "'%[^']s'", cfg_name); | 302 handled = SDL_FALSE; |
313 config += strlen(cfg_name)+2; | 303 |
304 /* Default joystick device settings */ | |
305 if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) { | |
306 joystick->naxes = 2; | |
314 } else { | 307 } else { |
315 sscanf(config, "%s", cfg_name); | 308 joystick->naxes = n; |
316 config += strlen(cfg_name); | 309 } |
317 } | 310 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { |
318 handled = SDL_FALSE; | 311 joystick->nbuttons = 2; |
319 if ( strcmp(cfg_name, name) == 0 ) { | 312 } else { |
320 /* Get the number of axes, hats and balls for this joystick */ | 313 joystick->nbuttons = n; |
321 int joystick_axes = joystick->naxes; | 314 } |
322 sscanf(config, "%d %d %d", | 315 |
323 &joystick->naxes, &joystick->nhats, &joystick->nballs); | 316 name = SDL_SYS_JoystickName(joystick->index); |
324 | 317 old_axes = joystick->naxes; |
325 /* Allocate the extra data for mapping them */ | 318 |
319 /* Generic analog joystick support */ | |
320 if ( strstr(name, "Analog") == name && strstr(name, "-hat") ) { | |
321 if ( sscanf(name,"Analog %d-axis %*d-button %d-hat", | |
322 &tmp_naxes, &tmp_nhats) == 2 ) { | |
323 | |
324 joystick->naxes = tmp_naxes; | |
325 joystick->nhats = tmp_nhats; | |
326 | |
327 handled = SDL_TRUE; | |
328 } | |
329 } | |
330 | |
331 /* Special joystick support */ | |
332 for ( i=0; i < SDL_TABLESIZE(special_joysticks); ++i ) { | |
333 if ( strcmp(name, special_joysticks[i].name) == 0 ) { | |
334 | |
335 joystick->naxes = special_joysticks[i].naxes; | |
336 joystick->nhats = special_joysticks[i].nhats; | |
337 joystick->nballs = special_joysticks[i].nballs; | |
338 | |
339 handled = SDL_TRUE; | |
340 break; | |
341 } | |
342 } | |
343 | |
344 /* User environment joystick support */ | |
345 if ( (env = getenv("SDL_LINUX_JOYSTICK")) ) { | |
346 strcpy(env_name, ""); | |
347 if ( *env == '\'' && sscanf(env, "'%[^']s'", env_name) == 1 ) | |
348 env += strlen(env_name)+2; | |
349 else if ( sscanf(env, "%s", env_name) == 1 ) | |
350 env += strlen(env_name); | |
351 | |
352 if ( strcmp(name, env_name) == 0 ) { | |
353 | |
354 if ( sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats, | |
355 &tmp_nballs) == 3 ) { | |
356 | |
357 joystick->naxes = tmp_naxes; | |
358 joystick->nhats = tmp_nhats; | |
359 joystick->nballs = tmp_nballs; | |
360 | |
361 handled = SDL_TRUE; | |
362 } | |
363 } | |
364 } | |
365 | |
366 /* Remap hats and balls */ | |
367 if (handled) { | |
326 if ( joystick->nhats > 0 ) { | 368 if ( joystick->nhats > 0 ) { |
327 /* HACK: Analog hats map to only one axis */ | 369 /* HACK: Analog hats map to only one axis */ |
328 if (joystick_axes == (joystick->naxes+joystick->nhats)){ | 370 if (old_axes == (joystick->naxes+joystick->nhats)){ |
329 joystick->hwdata->analog_hat = 1; | 371 joystick->hwdata->analog_hat = 1; |
330 } else { | 372 } else { |
331 if ( allocate_hatdata(joystick) < 0 ) { | 373 if ( allocate_hatdata(joystick) < 0 ) { |
332 joystick->nhats = 0; | 374 joystick->nhats = 0; |
333 } | 375 } |
337 if ( joystick->nballs > 0 ) { | 379 if ( joystick->nballs > 0 ) { |
338 if ( allocate_balldata(joystick) < 0 ) { | 380 if ( allocate_balldata(joystick) < 0 ) { |
339 joystick->nballs = 0; | 381 joystick->nballs = 0; |
340 } | 382 } |
341 } | 383 } |
342 handled = SDL_TRUE; | 384 } |
343 } | 385 |
344 return(handled); | 386 return(handled); |
345 } | 387 } |
346 | 388 |
347 #ifdef USE_INPUT_EVENTS | 389 #ifdef USE_INPUT_EVENTS |
348 | 390 |
438 return(joystick->hwdata->is_hid); | 480 return(joystick->hwdata->is_hid); |
439 } | 481 } |
440 | 482 |
441 #endif /* USE_INPUT_EVENTS */ | 483 #endif /* USE_INPUT_EVENTS */ |
442 | 484 |
443 #endif /* FANCY_HATS_AND_BALLS */ | |
444 | |
445 /* Function to open a joystick for use. | 485 /* Function to open a joystick for use. |
446 The joystick to open is specified by the index field of the joystick. | 486 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. | 487 This should fill the nbuttons and naxes fields of the joystick structure. |
448 It returns 0, or -1 if there is an error. | 488 It returns 0, or -1 if there is an error. |
449 */ | 489 */ |
450 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | 490 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) |
451 { | 491 { |
452 #ifdef FANCY_HATS_AND_BALLS | |
453 const char *name; | |
454 int i; | |
455 #endif | |
456 int fd; | 492 int fd; |
457 unsigned char n; | |
458 | 493 |
459 /* Open the joystick and set the joystick file descriptor */ | 494 /* Open the joystick and set the joystick file descriptor */ |
460 fd = open(SDL_joylist[joystick->index], O_RDONLY, 0); | 495 fd = open(SDL_joylist[joystick->index], O_RDONLY, 0); |
461 if ( fd < 0 ) { | 496 if ( fd < 0 ) { |
462 SDL_SetError("Unable to open %s\n", | 497 SDL_SetError("Unable to open %s\n", |
478 | 513 |
479 /* Get the number of buttons and axes on the joystick */ | 514 /* Get the number of buttons and axes on the joystick */ |
480 #ifdef USE_INPUT_EVENTS | 515 #ifdef USE_INPUT_EVENTS |
481 if ( ! EV_ConfigJoystick(joystick, fd) ) | 516 if ( ! EV_ConfigJoystick(joystick, fd) ) |
482 #endif | 517 #endif |
483 { | 518 JS_ConfigJoystick(joystick, fd); |
484 if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) { | 519 |
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); | 520 return(0); |
509 } | 521 } |
510 | 522 |
511 static __inline__ | 523 static __inline__ |
512 void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) | 524 void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) |
629 value -= correct->coef[0]; | 641 value -= correct->coef[0]; |
630 } | 642 } |
631 value *= correct->coef[2]; | 643 value *= correct->coef[2]; |
632 value >>= 14; | 644 value >>= 14; |
633 } | 645 } |
646 | |
634 /* Clamp and return */ | 647 /* Clamp and return */ |
635 if ( value < -32767 ) { | 648 if ( value < -32767 ) return -32767; |
636 value = -32767; | 649 if ( value > 32767 ) return 32767; |
637 } else | 650 |
638 if ( value > 32767 ) { | |
639 value = 32767; | |
640 } | |
641 return value; | 651 return value; |
642 } | 652 } |
643 | 653 |
644 static __inline__ void EV_HandleEvents(SDL_Joystick *joystick) | 654 static __inline__ void EV_HandleEvents(SDL_Joystick *joystick) |
645 { | 655 { |