src/joystick/linux/SDL_sysjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 27 Aug 2008 15:10:03 +0000
changeset 2735 204be4fc2726
parent 2713 0906692aa6a4
child 2859 99210400e8b9
permissions -rw-r--r--
Final merge of Google Summer of Code 2008 work...

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