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