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