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