src/joystick/SDL_joystick.c
author Sam Lantinga
Mon, 28 Sep 2020 21:19:45 -0700
changeset 14058 13382e1092cd
parent 13872 75c33f89d791
permissions -rw-r--r--
Added support for the MOGA XP5-X Plus
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../SDL_internal.h"
    22 
    23 /* This is the joystick API for Simple DirectMedia Layer */
    24 
    25 #include "SDL.h"
    26 #include "SDL_atomic.h"
    27 #include "SDL_events.h"
    28 #include "SDL_sysjoystick.h"
    29 #include "SDL_assert.h"
    30 #include "SDL_hints.h"
    31 
    32 #if !SDL_EVENTS_DISABLED
    33 #include "../events/SDL_events_c.h"
    34 #endif
    35 #include "../video/SDL_sysvideo.h"
    36 #include "hidapi/SDL_hidapijoystick_c.h"
    37 
    38 /* This is included in only one place because it has a large static list of controllers */
    39 #include "controller_type.h"
    40 
    41 #ifdef __WIN32__
    42 /* Needed for checking for input remapping programs */
    43 #include "../core/windows/SDL_windows.h"
    44 
    45 #undef UNICODE          /* We want ASCII functions */
    46 #include <tlhelp32.h>
    47 #endif
    48 
    49 #if SDL_JOYSTICK_VIRTUAL
    50 #include "./virtual/SDL_virtualjoystick_c.h"
    51 #endif
    52 
    53 static SDL_JoystickDriver *SDL_joystick_drivers[] = {
    54 #ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
    55     /* Also before HIDAPI, as HIDAPI wants to check if this driver is handling things */
    56     &SDL_RAWINPUT_JoystickDriver,
    57 #endif
    58 #ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
    59     &SDL_HIDAPI_JoystickDriver,
    60 #endif
    61 #if defined(SDL_JOYSTICK_WGI)
    62     &SDL_WGI_JoystickDriver,
    63 #endif
    64 #if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
    65     &SDL_WINDOWS_JoystickDriver,
    66 #endif
    67 #ifdef SDL_JOYSTICK_LINUX
    68     &SDL_LINUX_JoystickDriver,
    69 #endif
    70 #ifdef SDL_JOYSTICK_IOKIT
    71     &SDL_DARWIN_JoystickDriver,
    72 #endif
    73 #if (defined(__IPHONEOS__) || defined(__TVOS__)) && !defined(SDL_JOYSTICK_DISABLED)
    74     &SDL_IOS_JoystickDriver,
    75 #endif
    76 #ifdef SDL_JOYSTICK_ANDROID
    77     &SDL_ANDROID_JoystickDriver,
    78 #endif
    79 #ifdef SDL_JOYSTICK_EMSCRIPTEN
    80     &SDL_EMSCRIPTEN_JoystickDriver,
    81 #endif
    82 #ifdef SDL_JOYSTICK_HAIKU
    83     &SDL_HAIKU_JoystickDriver,
    84 #endif
    85 #ifdef SDL_JOYSTICK_USBHID  /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
    86     &SDL_BSD_JoystickDriver,
    87 #endif
    88 #ifdef SDL_JOYSTICK_VIRTUAL
    89     &SDL_VIRTUAL_JoystickDriver,
    90 #endif
    91 #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
    92     &SDL_DUMMY_JoystickDriver
    93 #endif
    94 };
    95 static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
    96 static SDL_Joystick *SDL_joysticks = NULL;
    97 static SDL_bool SDL_updating_joystick = SDL_FALSE;
    98 static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
    99 static SDL_atomic_t SDL_next_joystick_instance_id;
   100 static int SDL_joystick_player_count = 0;
   101 static SDL_JoystickID *SDL_joystick_players = NULL;
   102 
   103 void
   104 SDL_LockJoysticks(void)
   105 {
   106     if (SDL_joystick_lock) {
   107         SDL_LockMutex(SDL_joystick_lock);
   108     }
   109 }
   110 
   111 void
   112 SDL_UnlockJoysticks(void)
   113 {
   114     if (SDL_joystick_lock) {
   115         SDL_UnlockMutex(SDL_joystick_lock);
   116     }
   117 }
   118 
   119 static int
   120 SDL_FindFreePlayerIndex()
   121 {
   122     int player_index;
   123 
   124     for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
   125         if (SDL_joystick_players[player_index] == -1) {
   126             return player_index;
   127         }
   128     }
   129     return player_index;
   130 }
   131 
   132 static int
   133 SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)
   134 {
   135     int player_index;
   136 
   137     for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
   138         if (instance_id == SDL_joystick_players[player_index]) {
   139             break;
   140         }
   141     }
   142     if (player_index == SDL_joystick_player_count) {
   143         player_index = -1;
   144     }
   145     return player_index;
   146 }
   147 
   148 static SDL_JoystickID
   149 SDL_GetJoystickIDForPlayerIndex(int player_index)
   150 {
   151     if (player_index < 0 || player_index >= SDL_joystick_player_count) {
   152         return -1;
   153     }
   154     return SDL_joystick_players[player_index];
   155 }
   156 
   157 static SDL_bool
   158 SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
   159 {
   160     SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
   161     SDL_JoystickDriver *driver;
   162     int device_index;
   163     int existing_player_index;
   164 
   165     if (player_index < 0) {
   166         return SDL_FALSE;
   167     }
   168     if (player_index >= SDL_joystick_player_count) {
   169         SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players));
   170         if (!new_players) {
   171             SDL_OutOfMemory();
   172             return SDL_FALSE;
   173         }
   174 
   175         SDL_joystick_players = new_players;
   176         SDL_memset(&SDL_joystick_players[SDL_joystick_player_count], 0xFF, (player_index - SDL_joystick_player_count + 1) * sizeof(SDL_joystick_players[0]));
   177         SDL_joystick_player_count = player_index + 1;
   178     } else if (SDL_joystick_players[player_index] == instance_id) {
   179         /* Joystick is already assigned the requested player index */
   180         return SDL_TRUE;
   181     }
   182 
   183     /* Clear the old player index */
   184     existing_player_index = SDL_GetPlayerIndexForJoystickID(instance_id);
   185     if (existing_player_index >= 0) {
   186         SDL_joystick_players[existing_player_index] = -1;
   187     }
   188 
   189     SDL_joystick_players[player_index] = instance_id;
   190 
   191     /* Update the driver with the new index */
   192     device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
   193     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   194         driver->SetDevicePlayerIndex(device_index, player_index);
   195     }
   196 
   197     /* Move any existing joystick to another slot */
   198     if (existing_instance >= 0) {
   199         SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance);
   200     }
   201     return SDL_TRUE;
   202 }
   203 
   204 static void SDLCALL
   205 SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
   206 {
   207     if (hint && *hint == '1') {
   208         SDL_joystick_allows_background_events = SDL_TRUE;
   209     } else {
   210         SDL_joystick_allows_background_events = SDL_FALSE;
   211     }
   212 }
   213 
   214 int
   215 SDL_JoystickInit(void)
   216 {
   217     int i, status;
   218 
   219     SDL_GameControllerInitMappings();
   220 
   221     /* Create the joystick list lock */
   222     if (!SDL_joystick_lock) {
   223         SDL_joystick_lock = SDL_CreateMutex();
   224     }
   225 
   226     /* See if we should allow joystick events while in the background */
   227     SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
   228                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
   229 
   230 #if !SDL_EVENTS_DISABLED
   231     if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
   232         return -1;
   233     }
   234 #endif /* !SDL_EVENTS_DISABLED */
   235 
   236     status = -1;
   237     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   238         if (SDL_joystick_drivers[i]->Init() >= 0) {
   239             status = 0;
   240         }
   241     }
   242     return status;
   243 }
   244 
   245 /*
   246  * Count the number of joysticks attached to the system
   247  */
   248 int
   249 SDL_NumJoysticks(void)
   250 {
   251     int i, total_joysticks = 0;
   252     SDL_LockJoysticks();
   253     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   254         total_joysticks += SDL_joystick_drivers[i]->GetCount();
   255     }
   256     SDL_UnlockJoysticks();
   257     return total_joysticks;
   258 }
   259 
   260 /*
   261  * Return the next available joystick instance ID
   262  * This may be called by drivers from multiple threads, unprotected by any locks
   263  */
   264 SDL_JoystickID SDL_GetNextJoystickInstanceID()
   265 {
   266     return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
   267 }
   268 
   269 /*
   270  * Get the driver and device index for an API device index
   271  * This should be called while the joystick lock is held, to prevent another thread from updating the list
   272  */
   273 SDL_bool
   274 SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index)
   275 {
   276     int i, num_joysticks, total_joysticks = 0;
   277 
   278     if (device_index >= 0) {
   279         for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   280             num_joysticks = SDL_joystick_drivers[i]->GetCount();
   281             if (device_index < num_joysticks) {
   282                 *driver = SDL_joystick_drivers[i];
   283                 *driver_index = device_index;
   284                 return SDL_TRUE;
   285             }
   286             device_index -= num_joysticks;
   287             total_joysticks += num_joysticks;
   288         }
   289     }
   290 
   291     SDL_SetError("There are %d joysticks available", total_joysticks);
   292     return SDL_FALSE;
   293 }
   294 
   295 /*
   296  * Get the implementation dependent name of a joystick
   297  */
   298 const char *
   299 SDL_JoystickNameForIndex(int device_index)
   300 {
   301     SDL_JoystickDriver *driver;
   302     const char *name = NULL;
   303 
   304     SDL_LockJoysticks();
   305     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   306         name = driver->GetDeviceName(device_index);
   307     }
   308     SDL_UnlockJoysticks();
   309 
   310     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */
   311     return name;
   312 }
   313 
   314 /*
   315  *  Get the player index of a joystick, or -1 if it's not available
   316  */
   317 int
   318 SDL_JoystickGetDevicePlayerIndex(int device_index)
   319 {
   320     int player_index;
   321 
   322     SDL_LockJoysticks();
   323     player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index));
   324     SDL_UnlockJoysticks();
   325 
   326     return player_index;
   327 }
   328 
   329 /*
   330  * Return true if this joystick is known to have all axes centered at zero
   331  * This isn't generally needed unless the joystick never generates an initial axis value near zero,
   332  * e.g. it's emulating axes with digital buttons
   333  */
   334 static SDL_bool
   335 SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
   336 {
   337     static Uint32 zero_centered_joysticks[] = {
   338         MAKE_VIDPID(0x0e8f, 0x3013),    /* HuiJia SNES USB adapter */
   339         MAKE_VIDPID(0x05a0, 0x3232),    /* 8Bitdo Zero Gamepad */
   340     };
   341 
   342     int i;
   343     Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick),
   344                             SDL_JoystickGetProduct(joystick));
   345 
   346 /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
   347 
   348     if (joystick->naxes == 2) {
   349         /* Assume D-pad or thumbstick style axes are centered at 0 */
   350         return SDL_TRUE;
   351     }
   352 
   353     for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
   354         if (id == zero_centered_joysticks[i]) {
   355             return SDL_TRUE;
   356         }
   357     }
   358     return SDL_FALSE;
   359 }
   360 
   361 /*
   362  * Open a joystick for use - the index passed as an argument refers to
   363  * the N'th joystick on the system.  This index is the value which will
   364  * identify this joystick in future joystick events.
   365  *
   366  * This function returns a joystick identifier, or NULL if an error occurred.
   367  */
   368 SDL_Joystick *
   369 SDL_JoystickOpen(int device_index)
   370 {
   371     SDL_JoystickDriver *driver;
   372     SDL_JoystickID instance_id;
   373     SDL_Joystick *joystick;
   374     SDL_Joystick *joysticklist;
   375     const char *joystickname = NULL;
   376 
   377     SDL_LockJoysticks();
   378 
   379     if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   380         SDL_UnlockJoysticks();
   381         return NULL;
   382     }
   383 
   384     joysticklist = SDL_joysticks;
   385     /* If the joystick is already open, return it
   386      * it is important that we have a single joystick * for each instance id
   387      */
   388     instance_id = driver->GetDeviceInstanceID(device_index);
   389     while (joysticklist) {
   390         if (instance_id == joysticklist->instance_id) {
   391                 joystick = joysticklist;
   392                 ++joystick->ref_count;
   393                 SDL_UnlockJoysticks();
   394                 return joystick;
   395         }
   396         joysticklist = joysticklist->next;
   397     }
   398 
   399     /* Create and initialize the joystick */
   400     joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
   401     if (joystick == NULL) {
   402         SDL_OutOfMemory();
   403         SDL_UnlockJoysticks();
   404         return NULL;
   405     }
   406     joystick->driver = driver;
   407     joystick->instance_id = instance_id;
   408     joystick->attached = SDL_TRUE;
   409     joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
   410 
   411     if (driver->Open(joystick, device_index) < 0) {
   412         SDL_free(joystick);
   413         SDL_UnlockJoysticks();
   414         return NULL;
   415     }
   416 
   417     joystickname = driver->GetDeviceName(device_index);
   418     if (joystickname) {
   419         joystick->name = SDL_strdup(joystickname);
   420     } else {
   421         joystick->name = NULL;
   422     }
   423 
   424     joystick->guid = driver->GetDeviceGUID(device_index);
   425 
   426     if (joystick->naxes > 0) {
   427         joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
   428     }
   429     if (joystick->nhats > 0) {
   430         joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8));
   431     }
   432     if (joystick->nballs > 0) {
   433         joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls));
   434     }
   435     if (joystick->nbuttons > 0) {
   436         joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8));
   437     }
   438     if (((joystick->naxes > 0) && !joystick->axes)
   439         || ((joystick->nhats > 0) && !joystick->hats)
   440         || ((joystick->nballs > 0) && !joystick->balls)
   441         || ((joystick->nbuttons > 0) && !joystick->buttons)) {
   442         SDL_OutOfMemory();
   443         SDL_JoystickClose(joystick);
   444         SDL_UnlockJoysticks();
   445         return NULL;
   446     }
   447 
   448     /* If this joystick is known to have all zero centered axes, skip the auto-centering code */
   449     if (SDL_JoystickAxesCenteredAtZero(joystick)) {
   450         int i;
   451 
   452         for (i = 0; i < joystick->naxes; ++i) {
   453             joystick->axes[i].has_initial_value = SDL_TRUE;
   454         }
   455     }
   456 
   457     joystick->is_game_controller = SDL_IsGameController(device_index);
   458 
   459     /* Add joystick to list */
   460     ++joystick->ref_count;
   461     /* Link the joystick in the list */
   462     joystick->next = SDL_joysticks;
   463     SDL_joysticks = joystick;
   464 
   465     SDL_UnlockJoysticks();
   466 
   467     driver->Update(joystick);
   468 
   469     return joystick;
   470 }
   471 
   472 
   473 int
   474 SDL_JoystickAttachVirtual(SDL_JoystickType type,
   475                           int naxes,
   476                           int nbuttons,
   477                           int nhats)
   478 {
   479 #if SDL_JOYSTICK_VIRTUAL
   480     return SDL_JoystickAttachVirtualInner(type,
   481                                           naxes,
   482                                           nbuttons,
   483                                           nhats);
   484 #else
   485     return SDL_SetError("SDL not built with virtual-joystick support");
   486 #endif
   487 }
   488 
   489 
   490 int
   491 SDL_JoystickDetachVirtual(int device_index)
   492 {
   493 #if SDL_JOYSTICK_VIRTUAL
   494     SDL_JoystickDriver *driver;
   495 
   496     SDL_LockJoysticks();
   497     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   498         if (driver == &SDL_VIRTUAL_JoystickDriver) {
   499             const int result = SDL_JoystickDetachVirtualInner(device_index);
   500             SDL_UnlockJoysticks();
   501             return result;
   502         }
   503     }
   504     SDL_UnlockJoysticks();
   505 
   506     return SDL_SetError("Virtual joystick not found at provided index");
   507 #else
   508     return SDL_SetError("SDL not built with virtual-joystick support");
   509 #endif
   510 }
   511 
   512 
   513 SDL_bool
   514 SDL_JoystickIsVirtual(int device_index)
   515 {
   516 #if SDL_JOYSTICK_VIRTUAL
   517     SDL_JoystickDriver *driver;
   518     int driver_device_index;
   519     SDL_bool is_virtual = SDL_FALSE;
   520 
   521     SDL_LockJoysticks();
   522     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
   523         if (driver == &SDL_VIRTUAL_JoystickDriver) {
   524             is_virtual = SDL_TRUE;
   525         }
   526     }
   527     SDL_UnlockJoysticks();
   528 
   529     return is_virtual;
   530 #else
   531     return SDL_FALSE;
   532 #endif
   533 }
   534 
   535 
   536 int
   537 SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value)
   538 {
   539 #if SDL_JOYSTICK_VIRTUAL
   540     return SDL_JoystickSetVirtualAxisInner(joystick, axis, value);
   541 #else
   542     return SDL_SetError("SDL not built with virtual-joystick support");
   543 #endif
   544 }
   545 
   546 
   547 int
   548 SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value)
   549 {
   550 #if SDL_JOYSTICK_VIRTUAL
   551     return SDL_JoystickSetVirtualButtonInner(joystick, button, value);
   552 #else
   553     return SDL_SetError("SDL not built with virtual-joystick support");
   554 #endif
   555 }
   556 
   557 
   558 int
   559 SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value)
   560 {
   561 #if SDL_JOYSTICK_VIRTUAL
   562     return SDL_JoystickSetVirtualHatInner(joystick, hat, value);
   563 #else
   564     return SDL_SetError("SDL not built with virtual-joystick support");
   565 #endif
   566 }
   567 
   568 
   569 /*
   570  * Checks to make sure the joystick is valid.
   571  */
   572 SDL_bool
   573 SDL_PrivateJoystickValid(SDL_Joystick * joystick)
   574 {
   575     SDL_bool valid;
   576 
   577     if (joystick == NULL) {
   578         SDL_SetError("Joystick hasn't been opened yet");
   579         valid = SDL_FALSE;
   580     } else {
   581         valid = SDL_TRUE;
   582     }
   583 
   584     return valid;
   585 }
   586 
   587 SDL_bool
   588 SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping * out)
   589 {
   590     SDL_JoystickDriver *driver;
   591     SDL_bool is_ok = SDL_FALSE;
   592 
   593     SDL_LockJoysticks();
   594     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   595         is_ok = driver->GetGamepadMapping(device_index, out);
   596     }
   597     SDL_UnlockJoysticks();
   598 
   599     return is_ok;
   600 }
   601 
   602 /*
   603  * Get the number of multi-dimensional axis controls on a joystick
   604  */
   605 int
   606 SDL_JoystickNumAxes(SDL_Joystick * joystick)
   607 {
   608     if (!SDL_PrivateJoystickValid(joystick)) {
   609         return -1;
   610     }
   611     return joystick->naxes;
   612 }
   613 
   614 /*
   615  * Get the number of hats on a joystick
   616  */
   617 int
   618 SDL_JoystickNumHats(SDL_Joystick * joystick)
   619 {
   620     if (!SDL_PrivateJoystickValid(joystick)) {
   621         return -1;
   622     }
   623     return joystick->nhats;
   624 }
   625 
   626 /*
   627  * Get the number of trackballs on a joystick
   628  */
   629 int
   630 SDL_JoystickNumBalls(SDL_Joystick * joystick)
   631 {
   632     if (!SDL_PrivateJoystickValid(joystick)) {
   633         return -1;
   634     }
   635     return joystick->nballs;
   636 }
   637 
   638 /*
   639  * Get the number of buttons on a joystick
   640  */
   641 int
   642 SDL_JoystickNumButtons(SDL_Joystick * joystick)
   643 {
   644     if (!SDL_PrivateJoystickValid(joystick)) {
   645         return -1;
   646     }
   647     return joystick->nbuttons;
   648 }
   649 
   650 /*
   651  * Get the current state of an axis control on a joystick
   652  */
   653 Sint16
   654 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
   655 {
   656     Sint16 state;
   657 
   658     if (!SDL_PrivateJoystickValid(joystick)) {
   659         return 0;
   660     }
   661     if (axis < joystick->naxes) {
   662         state = joystick->axes[axis].value;
   663     } else {
   664         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   665         state = 0;
   666     }
   667     return state;
   668 }
   669 
   670 /*
   671  * Get the initial state of an axis control on a joystick
   672  */
   673 SDL_bool
   674 SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick, int axis, Sint16 *state)
   675 {
   676     if (!SDL_PrivateJoystickValid(joystick)) {
   677         return SDL_FALSE;
   678     }
   679     if (axis >= joystick->naxes) {
   680         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   681         return SDL_FALSE;
   682     }
   683     if (state) {
   684         *state = joystick->axes[axis].initial_value;
   685     }
   686     return joystick->axes[axis].has_initial_value;
   687 }
   688 
   689 /*
   690  * Get the current state of a hat on a joystick
   691  */
   692 Uint8
   693 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
   694 {
   695     Uint8 state;
   696 
   697     if (!SDL_PrivateJoystickValid(joystick)) {
   698         return 0;
   699     }
   700     if (hat < joystick->nhats) {
   701         state = joystick->hats[hat];
   702     } else {
   703         SDL_SetError("Joystick only has %d hats", joystick->nhats);
   704         state = 0;
   705     }
   706     return state;
   707 }
   708 
   709 /*
   710  * Get the ball axis change since the last poll
   711  */
   712 int
   713 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
   714 {
   715     int retval;
   716 
   717     if (!SDL_PrivateJoystickValid(joystick)) {
   718         return -1;
   719     }
   720 
   721     retval = 0;
   722     if (ball < joystick->nballs) {
   723         if (dx) {
   724             *dx = joystick->balls[ball].dx;
   725         }
   726         if (dy) {
   727             *dy = joystick->balls[ball].dy;
   728         }
   729         joystick->balls[ball].dx = 0;
   730         joystick->balls[ball].dy = 0;
   731     } else {
   732         return SDL_SetError("Joystick only has %d balls", joystick->nballs);
   733     }
   734     return retval;
   735 }
   736 
   737 /*
   738  * Get the current state of a button on a joystick
   739  */
   740 Uint8
   741 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
   742 {
   743     Uint8 state;
   744 
   745     if (!SDL_PrivateJoystickValid(joystick)) {
   746         return 0;
   747     }
   748     if (button < joystick->nbuttons) {
   749         state = joystick->buttons[button];
   750     } else {
   751         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
   752         state = 0;
   753     }
   754     return state;
   755 }
   756 
   757 /*
   758  * Return if the joystick in question is currently attached to the system,
   759  *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
   760  */
   761 SDL_bool
   762 SDL_JoystickGetAttached(SDL_Joystick * joystick)
   763 {
   764     if (!SDL_PrivateJoystickValid(joystick)) {
   765         return SDL_FALSE;
   766     }
   767 
   768     return joystick->attached;
   769 }
   770 
   771 /*
   772  * Get the instance id for this opened joystick
   773  */
   774 SDL_JoystickID
   775 SDL_JoystickInstanceID(SDL_Joystick * joystick)
   776 {
   777     if (!SDL_PrivateJoystickValid(joystick)) {
   778         return -1;
   779     }
   780 
   781     return joystick->instance_id;
   782 }
   783 
   784 /*
   785  * Return the SDL_Joystick associated with an instance id.
   786  */
   787 SDL_Joystick *
   788 SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)
   789 {
   790     SDL_Joystick *joystick;
   791 
   792     SDL_LockJoysticks();
   793     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   794         if (joystick->instance_id == instance_id) {
   795             break;
   796         }
   797     }
   798     SDL_UnlockJoysticks();
   799     return joystick;
   800 }
   801 
   802 /**
   803  * Return the SDL_Joystick associated with a player index.
   804  */
   805 SDL_Joystick *
   806 SDL_JoystickFromPlayerIndex(int player_index)
   807 {
   808     SDL_JoystickID instance_id;
   809     SDL_Joystick *joystick;
   810 
   811     SDL_LockJoysticks();
   812     instance_id = SDL_GetJoystickIDForPlayerIndex(player_index);
   813     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   814         if (joystick->instance_id == instance_id) {
   815             break;
   816         }
   817     }
   818     SDL_UnlockJoysticks();
   819     return joystick;
   820 }
   821 
   822 /*
   823  * Get the friendly name of this joystick
   824  */
   825 const char *
   826 SDL_JoystickName(SDL_Joystick * joystick)
   827 {
   828     if (!SDL_PrivateJoystickValid(joystick)) {
   829         return NULL;
   830     }
   831 
   832     return joystick->name;
   833 }
   834 
   835 /**
   836  *  Get the player index of an opened joystick, or -1 if it's not available
   837  */
   838 int
   839 SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)
   840 {
   841     int player_index;
   842 
   843     if (!SDL_PrivateJoystickValid(joystick)) {
   844         return -1;
   845     }
   846 
   847     SDL_LockJoysticks();
   848     player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id);
   849     SDL_UnlockJoysticks();
   850 
   851     return player_index;
   852 }
   853 
   854 /**
   855  *  Set the player index of an opened joystick
   856  */
   857 void
   858 SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
   859 {
   860     if (!SDL_PrivateJoystickValid(joystick)) {
   861         return;
   862     }
   863 
   864     SDL_LockJoysticks();
   865     SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id);
   866     SDL_UnlockJoysticks();
   867 }
   868 
   869 int
   870 SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   871 {
   872     int result;
   873 
   874     if (!SDL_PrivateJoystickValid(joystick)) {
   875         return -1;
   876     }
   877 
   878     SDL_LockJoysticks();
   879     if (low_frequency_rumble == joystick->low_frequency_rumble &&
   880         high_frequency_rumble == joystick->high_frequency_rumble) {
   881         /* Just update the expiration */
   882         result = 0;
   883     } else {
   884         result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
   885     }
   886 
   887     /* Save the rumble value regardless of success, so we don't spam the driver */
   888     joystick->low_frequency_rumble = low_frequency_rumble;
   889     joystick->high_frequency_rumble = high_frequency_rumble;
   890 
   891     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   892         joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
   893         if (!joystick->rumble_expiration) {
   894             joystick->rumble_expiration = 1;
   895         }
   896     } else {
   897         joystick->rumble_expiration = 0;
   898     }
   899     SDL_UnlockJoysticks();
   900 
   901     return result;
   902 }
   903 
   904 /*
   905  * Close a joystick previously opened with SDL_JoystickOpen()
   906  */
   907 void
   908 SDL_JoystickClose(SDL_Joystick * joystick)
   909 {
   910     SDL_Joystick *joysticklist;
   911     SDL_Joystick *joysticklistprev;
   912 
   913     if (!SDL_PrivateJoystickValid(joystick)) {
   914         return;
   915     }
   916 
   917     SDL_LockJoysticks();
   918 
   919     /* First decrement ref count */
   920     if (--joystick->ref_count > 0) {
   921         SDL_UnlockJoysticks();
   922         return;
   923     }
   924 
   925     if (SDL_updating_joystick) {
   926         SDL_UnlockJoysticks();
   927         return;
   928     }
   929 
   930     if (joystick->rumble_expiration) {
   931         SDL_JoystickRumble(joystick, 0, 0, 0);
   932     }
   933 
   934     joystick->driver->Close(joystick);
   935     joystick->hwdata = NULL;
   936 
   937     joysticklist = SDL_joysticks;
   938     joysticklistprev = NULL;
   939     while (joysticklist) {
   940         if (joystick == joysticklist) {
   941             if (joysticklistprev) {
   942                 /* unlink this entry */
   943                 joysticklistprev->next = joysticklist->next;
   944             } else {
   945                 SDL_joysticks = joystick->next;
   946             }
   947             break;
   948         }
   949         joysticklistprev = joysticklist;
   950         joysticklist = joysticklist->next;
   951     }
   952 
   953     SDL_free(joystick->name);
   954 
   955     /* Free the data associated with this joystick */
   956     SDL_free(joystick->axes);
   957     SDL_free(joystick->hats);
   958     SDL_free(joystick->balls);
   959     SDL_free(joystick->buttons);
   960     SDL_free(joystick);
   961 
   962     SDL_UnlockJoysticks();
   963 }
   964 
   965 void
   966 SDL_JoystickQuit(void)
   967 {
   968     int i;
   969 
   970     /* Make sure we're not getting called in the middle of updating joysticks */
   971     SDL_LockJoysticks();
   972     while (SDL_updating_joystick) {
   973         SDL_UnlockJoysticks();
   974         SDL_Delay(1);
   975         SDL_LockJoysticks();
   976     }
   977 
   978     /* Stop the event polling */
   979     while (SDL_joysticks) {
   980         SDL_joysticks->ref_count = 1;
   981         SDL_JoystickClose(SDL_joysticks);
   982     }
   983 
   984     /* Quit the joystick setup */
   985     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   986        SDL_joystick_drivers[i]->Quit();
   987     }
   988 
   989     if (SDL_joystick_players) {
   990         SDL_free(SDL_joystick_players);
   991         SDL_joystick_players = NULL;
   992         SDL_joystick_player_count = 0;
   993     }
   994     SDL_UnlockJoysticks();
   995 
   996 #if !SDL_EVENTS_DISABLED
   997     SDL_QuitSubSystem(SDL_INIT_EVENTS);
   998 #endif
   999 
  1000     SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
  1001                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
  1002 
  1003     if (SDL_joystick_lock) {
  1004         SDL_mutex *mutex = SDL_joystick_lock;
  1005         SDL_joystick_lock = NULL;
  1006         SDL_DestroyMutex(mutex);
  1007     }
  1008 
  1009     SDL_GameControllerQuitMappings();
  1010 }
  1011 
  1012 
  1013 static SDL_bool
  1014 SDL_PrivateJoystickShouldIgnoreEvent()
  1015 {
  1016     if (SDL_joystick_allows_background_events) {
  1017         return SDL_FALSE;
  1018     }
  1019 
  1020     if (SDL_HasWindows() && SDL_GetKeyboardFocus() == NULL) {
  1021         /* We have windows but we don't have focus, ignore the event. */
  1022         return SDL_TRUE;
  1023     }
  1024     return SDL_FALSE;
  1025 }
  1026 
  1027 /* These are global for SDL_sysjoystick.c and SDL_events.c */
  1028 
  1029 void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
  1030 {
  1031     SDL_JoystickDriver *driver;
  1032     int driver_device_index;
  1033     int player_index = -1;
  1034     int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
  1035     if (device_index < 0) {
  1036         return;
  1037     }
  1038 
  1039     SDL_LockJoysticks();
  1040     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
  1041         player_index = driver->GetDevicePlayerIndex(driver_device_index);
  1042     }
  1043     if (player_index < 0 && SDL_IsGameController(device_index)) {
  1044         player_index = SDL_FindFreePlayerIndex();
  1045     }
  1046     if (player_index >= 0) {
  1047         SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
  1048     }
  1049     SDL_UnlockJoysticks();
  1050 
  1051 #if !SDL_EVENTS_DISABLED
  1052     {
  1053         SDL_Event event;
  1054 
  1055         event.type = SDL_JOYDEVICEADDED;
  1056 
  1057         if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  1058             event.jdevice.which = device_index;
  1059             SDL_PushEvent(&event);
  1060         }
  1061     }
  1062 #endif /* !SDL_EVENTS_DISABLED */
  1063 }
  1064 
  1065 /*
  1066  * If there is an existing add event in the queue, it needs to be modified
  1067  * to have the right value for which, because the number of controllers in
  1068  * the system is now one less.
  1069  */
  1070 static void UpdateEventsForDeviceRemoval()
  1071 {
  1072     int i, num_events;
  1073     SDL_Event *events;
  1074     SDL_bool isstack;
  1075 
  1076     num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
  1077     if (num_events <= 0) {
  1078         return;
  1079     }
  1080 
  1081     events = SDL_small_alloc(SDL_Event, num_events, &isstack);
  1082     if (!events) {
  1083         return;
  1084     }
  1085 
  1086     num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
  1087     for (i = 0; i < num_events; ++i) {
  1088         --events[i].jdevice.which;
  1089     }
  1090     SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
  1091 
  1092     SDL_small_free(events, isstack);
  1093 }
  1094 
  1095 static void
  1096 SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
  1097 {
  1098     int i;
  1099 
  1100     /* Tell the app that everything is centered/unpressed... */
  1101     for (i = 0; i < joystick->naxes; i++) {
  1102         if (joystick->axes[i].has_initial_value) {
  1103             SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
  1104         }
  1105     }
  1106 
  1107     for (i = 0; i < joystick->nbuttons; i++) {
  1108         SDL_PrivateJoystickButton(joystick, i, 0);
  1109     }
  1110 
  1111     for (i = 0; i < joystick->nhats; i++) {
  1112         SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
  1113     }
  1114 }
  1115 
  1116 void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
  1117 {
  1118     SDL_Joystick *joystick = NULL;
  1119     int player_index;
  1120 #if !SDL_EVENTS_DISABLED
  1121     SDL_Event event;
  1122 #endif
  1123 
  1124     /* Find this joystick... */
  1125     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
  1126         if (joystick->instance_id == device_instance) {
  1127             SDL_PrivateJoystickForceRecentering(joystick);
  1128             joystick->attached = SDL_FALSE;
  1129             break;
  1130         }
  1131     }
  1132 
  1133 #if !SDL_EVENTS_DISABLED
  1134     SDL_zero(event);
  1135     event.type = SDL_JOYDEVICEREMOVED;
  1136 
  1137     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  1138         event.jdevice.which = device_instance;
  1139         SDL_PushEvent(&event);
  1140     }
  1141 
  1142     UpdateEventsForDeviceRemoval();
  1143 #endif /* !SDL_EVENTS_DISABLED */
  1144 
  1145     SDL_LockJoysticks();
  1146     player_index = SDL_GetPlayerIndexForJoystickID(device_instance);
  1147     if (player_index >= 0) {
  1148         SDL_joystick_players[player_index] = -1;
  1149     }
  1150     SDL_UnlockJoysticks();
  1151 }
  1152 
  1153 int
  1154 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
  1155 {
  1156     int posted;
  1157     SDL_JoystickAxisInfo *info;
  1158 
  1159     /* Make sure we're not getting garbage or duplicate events */
  1160     if (axis >= joystick->naxes) {
  1161         return 0;
  1162     }
  1163 
  1164     info = &joystick->axes[axis];
  1165     if (!info->has_initial_value ||
  1166         (!info->has_second_value && (info->initial_value <= -32767 || info->initial_value == 32767) && SDL_abs(value) < (SDL_JOYSTICK_AXIS_MAX / 4))) {
  1167         info->initial_value = value;
  1168         info->value = value;
  1169         info->zero = value;
  1170         info->has_initial_value = SDL_TRUE;
  1171     } else if (value == info->value) {
  1172         return 0;
  1173     } else {
  1174         info->has_second_value = SDL_TRUE;
  1175     }
  1176     if (!info->sent_initial_value) {
  1177         /* Make sure we don't send motion until there's real activity on this axis */
  1178         const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
  1179         if (SDL_abs(value - info->value) <= MAX_ALLOWED_JITTER) {
  1180             return 0;
  1181         }
  1182         info->sent_initial_value = SDL_TRUE;
  1183         info->value = ~value; /* Just so we pass the check above */
  1184         SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
  1185     }
  1186 
  1187     /* We ignore events if we don't have keyboard focus, except for centering
  1188      * events.
  1189      */
  1190     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
  1191         if ((value > info->zero && value >= info->value) ||
  1192             (value < info->zero && value <= info->value)) {
  1193             return 0;
  1194         }
  1195     }
  1196 
  1197     /* Update internal joystick state */
  1198     info->value = value;
  1199 
  1200     /* Post the event, if desired */
  1201     posted = 0;
  1202 #if !SDL_EVENTS_DISABLED
  1203     if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
  1204         SDL_Event event;
  1205         event.type = SDL_JOYAXISMOTION;
  1206         event.jaxis.which = joystick->instance_id;
  1207         event.jaxis.axis = axis;
  1208         event.jaxis.value = value;
  1209         posted = SDL_PushEvent(&event) == 1;
  1210     }
  1211 #endif /* !SDL_EVENTS_DISABLED */
  1212     return posted;
  1213 }
  1214 
  1215 int
  1216 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
  1217 {
  1218     int posted;
  1219 
  1220     /* Make sure we're not getting garbage or duplicate events */
  1221     if (hat >= joystick->nhats) {
  1222         return 0;
  1223     }
  1224     if (value == joystick->hats[hat]) {
  1225         return 0;
  1226     }
  1227 
  1228     /* We ignore events if we don't have keyboard focus, except for centering
  1229      * events.
  1230      */
  1231     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
  1232         if (value != SDL_HAT_CENTERED) {
  1233             return 0;
  1234         }
  1235     }
  1236 
  1237     /* Update internal joystick state */
  1238     joystick->hats[hat] = value;
  1239 
  1240     /* Post the event, if desired */
  1241     posted = 0;
  1242 #if !SDL_EVENTS_DISABLED
  1243     if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
  1244         SDL_Event event;
  1245         event.jhat.type = SDL_JOYHATMOTION;
  1246         event.jhat.which = joystick->instance_id;
  1247         event.jhat.hat = hat;
  1248         event.jhat.value = value;
  1249         posted = SDL_PushEvent(&event) == 1;
  1250     }
  1251 #endif /* !SDL_EVENTS_DISABLED */
  1252     return posted;
  1253 }
  1254 
  1255 int
  1256 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
  1257                         Sint16 xrel, Sint16 yrel)
  1258 {
  1259     int posted;
  1260 
  1261     /* Make sure we're not getting garbage events */
  1262     if (ball >= joystick->nballs) {
  1263         return 0;
  1264     }
  1265 
  1266     /* We ignore events if we don't have keyboard focus. */
  1267     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
  1268         return 0;
  1269     }
  1270 
  1271     /* Update internal mouse state */
  1272     joystick->balls[ball].dx += xrel;
  1273     joystick->balls[ball].dy += yrel;
  1274 
  1275     /* Post the event, if desired */
  1276     posted = 0;
  1277 #if !SDL_EVENTS_DISABLED
  1278     if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
  1279         SDL_Event event;
  1280         event.jball.type = SDL_JOYBALLMOTION;
  1281         event.jball.which = joystick->instance_id;
  1282         event.jball.ball = ball;
  1283         event.jball.xrel = xrel;
  1284         event.jball.yrel = yrel;
  1285         posted = SDL_PushEvent(&event) == 1;
  1286     }
  1287 #endif /* !SDL_EVENTS_DISABLED */
  1288     return posted;
  1289 }
  1290 
  1291 int
  1292 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
  1293 {
  1294     int posted;
  1295 #if !SDL_EVENTS_DISABLED
  1296     SDL_Event event;
  1297 
  1298     switch (state) {
  1299     case SDL_PRESSED:
  1300         event.type = SDL_JOYBUTTONDOWN;
  1301         break;
  1302     case SDL_RELEASED:
  1303         event.type = SDL_JOYBUTTONUP;
  1304         break;
  1305     default:
  1306         /* Invalid state -- bail */
  1307         return 0;
  1308     }
  1309 #endif /* !SDL_EVENTS_DISABLED */
  1310 
  1311     /* Make sure we're not getting garbage or duplicate events */
  1312     if (button >= joystick->nbuttons) {
  1313         return 0;
  1314     }
  1315     if (state == joystick->buttons[button]) {
  1316         return 0;
  1317     }
  1318 
  1319     /* We ignore events if we don't have keyboard focus, except for button
  1320      * release. */
  1321     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
  1322         if (state == SDL_PRESSED) {
  1323             return 0;
  1324         }
  1325     }
  1326 
  1327     /* Update internal joystick state */
  1328     joystick->buttons[button] = state;
  1329 
  1330     /* Post the event, if desired */
  1331     posted = 0;
  1332 #if !SDL_EVENTS_DISABLED
  1333     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  1334         event.jbutton.which = joystick->instance_id;
  1335         event.jbutton.button = button;
  1336         event.jbutton.state = state;
  1337         posted = SDL_PushEvent(&event) == 1;
  1338     }
  1339 #endif /* !SDL_EVENTS_DISABLED */
  1340     return posted;
  1341 }
  1342 
  1343 void
  1344 SDL_JoystickUpdate(void)
  1345 {
  1346     int i;
  1347     SDL_Joystick *joystick, *next;
  1348 
  1349     if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
  1350         return;
  1351     }
  1352 
  1353     SDL_LockJoysticks();
  1354 
  1355     if (SDL_updating_joystick) {
  1356         /* The joysticks are already being updated */
  1357         SDL_UnlockJoysticks();
  1358         return;
  1359     }
  1360 
  1361     SDL_updating_joystick = SDL_TRUE;
  1362 
  1363     /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
  1364     SDL_UnlockJoysticks();
  1365 
  1366 #ifdef SDL_JOYSTICK_HIDAPI
  1367     /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
  1368     HIDAPI_UpdateDevices();
  1369 #endif /* SDL_JOYSTICK_HIDAPI */
  1370 
  1371     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
  1372         if (joystick->attached) {
  1373             /* This should always be true, but seeing a crash in the wild...? */
  1374             if (joystick->driver) {
  1375                 joystick->driver->Update(joystick);
  1376             }
  1377 
  1378             if (joystick->delayed_guide_button) {
  1379                 SDL_GameControllerHandleDelayedGuideButton(joystick);
  1380             }
  1381         }
  1382 
  1383         if (joystick->rumble_expiration) {
  1384             SDL_LockJoysticks();
  1385             /* Double check now that the lock is held */
  1386             if (joystick->rumble_expiration &&
  1387                 SDL_TICKS_PASSED(SDL_GetTicks(), joystick->rumble_expiration)) {
  1388                 SDL_JoystickRumble(joystick, 0, 0, 0);
  1389             }
  1390             SDL_UnlockJoysticks();
  1391         }
  1392     }
  1393 
  1394     SDL_LockJoysticks();
  1395 
  1396     SDL_updating_joystick = SDL_FALSE;
  1397 
  1398     /* If any joysticks were closed while updating, free them here */
  1399     for (joystick = SDL_joysticks; joystick; joystick = next) {
  1400         next = joystick->next;
  1401         if (joystick->ref_count <= 0) {
  1402             SDL_JoystickClose(joystick);
  1403         }
  1404     }
  1405 
  1406     /* this needs to happen AFTER walking the joystick list above, so that any
  1407        dangling hardware data from removed devices can be free'd
  1408      */
  1409     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
  1410         SDL_joystick_drivers[i]->Detect();
  1411     }
  1412 
  1413     SDL_UnlockJoysticks();
  1414 }
  1415 
  1416 int
  1417 SDL_JoystickEventState(int state)
  1418 {
  1419 #if SDL_EVENTS_DISABLED
  1420     return SDL_DISABLE;
  1421 #else
  1422     const Uint32 event_list[] = {
  1423         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
  1424         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
  1425     };
  1426     unsigned int i;
  1427 
  1428     switch (state) {
  1429     case SDL_QUERY:
  1430         state = SDL_DISABLE;
  1431         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1432             state = SDL_EventState(event_list[i], SDL_QUERY);
  1433             if (state == SDL_ENABLE) {
  1434                 break;
  1435             }
  1436         }
  1437         break;
  1438     default:
  1439         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1440             SDL_EventState(event_list[i], state);
  1441         }
  1442         break;
  1443     }
  1444     return state;
  1445 #endif /* SDL_EVENTS_DISABLED */
  1446 }
  1447 
  1448 void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
  1449 {
  1450     Uint16 *guid16 = (Uint16 *)guid.data;
  1451 
  1452     /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
  1453     if (/* guid16[0] is device bus type */
  1454         guid16[1] == 0x0000 &&
  1455         /* guid16[2] is vendor ID */
  1456         guid16[3] == 0x0000 &&
  1457         /* guid16[4] is product ID */
  1458         guid16[5] == 0x0000
  1459         /* guid16[6] is product version */
  1460    ) {
  1461         if (vendor) {
  1462             *vendor = guid16[2];
  1463         }
  1464         if (product) {
  1465             *product = guid16[4];
  1466         }
  1467         if (version) {
  1468             *version = guid16[6];
  1469         }
  1470     } else {
  1471         if (vendor) {
  1472             *vendor = 0;
  1473         }
  1474         if (product) {
  1475             *product = 0;
  1476         }
  1477         if (version) {
  1478             *version = 0;
  1479         }
  1480     }
  1481 }
  1482 
  1483 static int
  1484 PrefixMatch(const char *a, const char *b)
  1485 {
  1486     int matchlen = 0;
  1487     while (*a && *b) {
  1488         if (SDL_tolower(*a++) == SDL_tolower(*b++)) {
  1489             ++matchlen;
  1490         } else {
  1491             break;
  1492         }
  1493     }
  1494     return matchlen;
  1495 }
  1496 
  1497 char *
  1498 SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name)
  1499 {
  1500     static struct {
  1501         const char *prefix;
  1502         const char *replacement;
  1503     } replacements[] = {
  1504         { "NVIDIA Corporation ", "" },
  1505         { "Performance Designed Products", "PDP" },
  1506         { "HORI CO.,LTD", "HORI" },
  1507     };
  1508     const char *custom_name;
  1509     char *name;
  1510     size_t i, len;
  1511 
  1512     custom_name = GuessControllerName(vendor, product);
  1513     if (custom_name) {
  1514         return SDL_strdup(custom_name);
  1515     }
  1516 
  1517     if (!vendor_name) {
  1518         vendor_name = "";
  1519     }
  1520     if (!product_name) {
  1521         product_name = "";
  1522     }
  1523 
  1524     while (*vendor_name == ' ') {
  1525         ++vendor_name;
  1526     }
  1527     while (*product_name == ' ') {
  1528         ++product_name;
  1529     }
  1530 
  1531     if (*vendor_name && *product_name) {
  1532         len = (SDL_strlen(vendor_name) + 1 + SDL_strlen(product_name) + 1);
  1533         name = (char *)SDL_malloc(len);
  1534         if (!name) {
  1535             return NULL;
  1536         }
  1537         SDL_snprintf(name, len, "%s %s", vendor_name, product_name);
  1538     } else if (*product_name) {
  1539         name = SDL_strdup(product_name);
  1540     } else if (vendor || product) {
  1541         len = (6 + 1 + 6 + 1);
  1542         name = (char *)SDL_malloc(len);
  1543         if (!name) {
  1544             return NULL;
  1545         }
  1546         SDL_snprintf(name, len, "0x%.4x/0x%.4x", vendor, product);
  1547     } else {
  1548         name = SDL_strdup("Controller");
  1549     }
  1550 
  1551     /* Trim trailing whitespace */
  1552     for (len = SDL_strlen(name); (len > 0 && name[len - 1] == ' '); --len) {
  1553         /* continue */
  1554     }
  1555     name[len] = '\0';
  1556 
  1557     /* Compress duplicate spaces */
  1558     for (i = 0; i < (len - 1); ) {
  1559         if (name[i] == ' ' && name[i+1] == ' ') {
  1560             SDL_memmove(&name[i], &name[i+1], (len - i));
  1561             --len;
  1562         } else {
  1563             ++i;
  1564         }
  1565     }
  1566 
  1567     /* Remove duplicate manufacturer or product in the name */
  1568     for (i = 1; i < (len - 1); ++i) {
  1569         int matchlen = PrefixMatch(name, &name[i]);
  1570         if (matchlen > 0 && name[matchlen-1] == ' ') {
  1571             SDL_memmove(name, name+matchlen, len-matchlen+1);
  1572             len -= matchlen;
  1573             break;
  1574         } else if (matchlen > 0 && name[matchlen] == ' ') {
  1575             SDL_memmove(name, name+matchlen+1, len-matchlen);
  1576             len -= (matchlen + 1);
  1577             break;
  1578         }
  1579     }
  1580 
  1581     /* Perform any manufacturer replacements */
  1582     for (i = 0; i < SDL_arraysize(replacements); ++i) {
  1583         size_t prefixlen = SDL_strlen(replacements[i].prefix);
  1584         if (SDL_strncasecmp(name, replacements[i].prefix, prefixlen) == 0) {
  1585             size_t replacementlen = SDL_strlen(replacements[i].replacement);
  1586             SDL_memcpy(name, replacements[i].replacement, replacementlen);
  1587             SDL_memmove(name+replacementlen, name+prefixlen, (len-prefixlen+1));
  1588             break;
  1589         }
  1590     }
  1591 
  1592     return name;
  1593 }
  1594 
  1595 SDL_GameControllerType
  1596 SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name)
  1597 {
  1598     SDL_GameControllerType type;
  1599     Uint16 vendor, product;
  1600 
  1601     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
  1602     type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
  1603     if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
  1604         if (SDL_IsJoystickXInput(guid)) {
  1605             /* This is probably an Xbox One controller */
  1606             return SDL_CONTROLLER_TYPE_XBOXONE;
  1607         }
  1608     }
  1609     return type;
  1610 }
  1611 
  1612 SDL_GameControllerType
  1613 SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  1614 {
  1615     static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
  1616     static const int XB360_IFACE_SUBCLASS = 93;
  1617     static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
  1618     static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
  1619     static const int XBONE_IFACE_SUBCLASS = 71;
  1620     static const int XBONE_IFACE_PROTOCOL = 208;
  1621 
  1622     SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
  1623 
  1624     /* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
  1625     if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
  1626         interface_subclass == XB360_IFACE_SUBCLASS &&
  1627         (interface_protocol == XB360_IFACE_PROTOCOL ||
  1628          interface_protocol == XB360W_IFACE_PROTOCOL)) {
  1629 
  1630         static const int SUPPORTED_VENDORS[] = {
  1631             0x0079, /* GPD Win 2 */
  1632             0x044f, /* Thrustmaster */
  1633             0x045e, /* Microsoft */
  1634             0x046d, /* Logitech */
  1635             0x056e, /* Elecom */
  1636             0x06a3, /* Saitek */
  1637             0x0738, /* Mad Catz */
  1638             0x07ff, /* Mad Catz */
  1639             0x0e6f, /* PDP */
  1640             0x0f0d, /* Hori */
  1641             0x1038, /* SteelSeries */
  1642             0x11c9, /* Nacon */
  1643             0x12ab, /* Unknown */
  1644             0x1430, /* RedOctane */
  1645             0x146b, /* BigBen */
  1646             0x1532, /* Razer Sabertooth */
  1647             0x15e4, /* Numark */
  1648             0x162e, /* Joytech */
  1649             0x1689, /* Razer Onza */
  1650             0x1bad, /* Harmonix */
  1651             0x24c6, /* PowerA */
  1652         };
  1653 
  1654         int i;
  1655         for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
  1656             if (vendor == SUPPORTED_VENDORS[i]) {
  1657                 type = SDL_CONTROLLER_TYPE_XBOX360;
  1658                 break;
  1659             }
  1660         }
  1661     }
  1662 
  1663     if (interface_number == 0 &&
  1664         interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
  1665         interface_subclass == XBONE_IFACE_SUBCLASS &&
  1666         interface_protocol == XBONE_IFACE_PROTOCOL) {
  1667 
  1668         static const int SUPPORTED_VENDORS[] = {
  1669             0x045e, /* Microsoft */
  1670             0x0738, /* Mad Catz */
  1671             0x0e6f, /* PDP */
  1672             0x0f0d, /* Hori */
  1673             0x1532, /* Razer Wildcat */
  1674             0x24c6, /* PowerA */
  1675             0x2e24, /* Hyperkin */
  1676         };
  1677 
  1678         int i;
  1679         for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
  1680             if (vendor == SUPPORTED_VENDORS[i]) {
  1681                 type = SDL_CONTROLLER_TYPE_XBOXONE;
  1682                 break;
  1683             }
  1684         }
  1685     }
  1686 
  1687     if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
  1688         if (vendor == 0x0000 && product == 0x0000) {
  1689             /* Some devices are only identifiable by their name */
  1690             if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
  1691                 SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
  1692                 SDL_strcmp(name, "Wireless Gamepad") == 0) {
  1693                 /* HORI or PowerA Switch Pro Controller clone */
  1694                 type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
  1695             } else if (SDL_strcmp(name, "Virtual Joystick") == 0) {
  1696                 type = SDL_CONTROLLER_TYPE_VIRTUAL;
  1697             } else {
  1698                 type = SDL_CONTROLLER_TYPE_UNKNOWN;
  1699             }
  1700 
  1701         } else if (vendor == 0x0001 && product == 0x0001) {
  1702             type = SDL_CONTROLLER_TYPE_UNKNOWN;
  1703 
  1704         } else {
  1705             switch (GuessControllerType(vendor, product)) {
  1706             case k_eControllerType_XBox360Controller:
  1707                 type = SDL_CONTROLLER_TYPE_XBOX360;
  1708                 break;
  1709             case k_eControllerType_XBoxOneController:
  1710                 type = SDL_CONTROLLER_TYPE_XBOXONE;
  1711                 break;
  1712             case k_eControllerType_PS3Controller:
  1713                 type = SDL_CONTROLLER_TYPE_PS3;
  1714                 break;
  1715             case k_eControllerType_PS4Controller:
  1716                 type = SDL_CONTROLLER_TYPE_PS4;
  1717                 break;
  1718             case k_eControllerType_SwitchProController:
  1719             case k_eControllerType_SwitchInputOnlyController:
  1720                 type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
  1721                 break;
  1722             default:
  1723                 type = SDL_CONTROLLER_TYPE_UNKNOWN;
  1724                 break;
  1725             }
  1726         }
  1727     }
  1728     return type;
  1729 }
  1730 
  1731 SDL_bool
  1732 SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product)
  1733 {
  1734     EControllerType eType = GuessControllerType(vendor, product);
  1735     return (eType == k_eControllerType_SwitchInputOnlyController);
  1736 }
  1737 
  1738 SDL_bool
  1739 SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product)
  1740 {
  1741     EControllerType eType = GuessControllerType(vendor, product);
  1742     return (eType == k_eControllerType_SteamController ||
  1743             eType == k_eControllerType_SteamControllerV2);
  1744 }
  1745 
  1746 SDL_bool
  1747 SDL_IsJoystickXInput(SDL_JoystickGUID guid)
  1748 {
  1749     return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
  1750 }
  1751 
  1752 SDL_bool
  1753 SDL_IsJoystickWGI(SDL_JoystickGUID guid)
  1754 {
  1755     return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE;
  1756 }
  1757 
  1758 SDL_bool
  1759 SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
  1760 {
  1761     return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
  1762 }
  1763 
  1764 SDL_bool
  1765 SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid)
  1766 {
  1767     return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE;
  1768 }
  1769 
  1770 SDL_bool
  1771 SDL_IsJoystickVirtual(SDL_JoystickGUID guid)
  1772 {
  1773     return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE;
  1774 }
  1775 
  1776 static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
  1777 {
  1778     static Uint32 wheel_joysticks[] = {
  1779         MAKE_VIDPID(0x046d, 0xc294),    /* Logitech generic wheel */
  1780         MAKE_VIDPID(0x046d, 0xc295),    /* Logitech Momo Force */
  1781         MAKE_VIDPID(0x046d, 0xc298),    /* Logitech Driving Force Pro */
  1782         MAKE_VIDPID(0x046d, 0xc299),    /* Logitech G25 */
  1783         MAKE_VIDPID(0x046d, 0xc29a),    /* Logitech Driving Force GT */
  1784         MAKE_VIDPID(0x046d, 0xc29b),    /* Logitech G27 */
  1785         MAKE_VIDPID(0x046d, 0xc24f),    /* Logitech G29 */
  1786         MAKE_VIDPID(0x046d, 0xc261),    /* Logitech G920 (initial mode) */
  1787         MAKE_VIDPID(0x046d, 0xc262),    /* Logitech G920 (active mode) */
  1788         MAKE_VIDPID(0x044f, 0xb65d),    /* Thrustmaster Wheel FFB */
  1789         MAKE_VIDPID(0x044f, 0xb66d),    /* Thrustmaster Wheel FFB */
  1790         MAKE_VIDPID(0x044f, 0xb677),    /* Thrustmaster T150 */
  1791         MAKE_VIDPID(0x044f, 0xb664),    /* Thrustmaster TX (initial mode) */
  1792         MAKE_VIDPID(0x044f, 0xb669),    /* Thrustmaster TX (active mode) */
  1793     };
  1794     int i;
  1795 
  1796     for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) {
  1797         if (vidpid == wheel_joysticks[i]) {
  1798             return SDL_TRUE;
  1799         }
  1800     }
  1801     return SDL_FALSE;
  1802 }
  1803 
  1804 static SDL_bool SDL_IsJoystickProductFlightStick(Uint32 vidpid)
  1805 {
  1806     static Uint32 flightstick_joysticks[] = {
  1807         MAKE_VIDPID(0x044f, 0x0402),    /* HOTAS Warthog Joystick */
  1808         MAKE_VIDPID(0x0738, 0x2221),    /* Saitek Pro Flight X-56 Rhino Stick */
  1809     };
  1810     int i;
  1811 
  1812     for (i = 0; i < SDL_arraysize(flightstick_joysticks); ++i) {
  1813         if (vidpid == flightstick_joysticks[i]) {
  1814             return SDL_TRUE;
  1815         }
  1816     }
  1817     return SDL_FALSE;
  1818 }
  1819 
  1820 static SDL_bool SDL_IsJoystickProductThrottle(Uint32 vidpid)
  1821 {
  1822     static Uint32 throttle_joysticks[] = {
  1823         MAKE_VIDPID(0x044f, 0x0404),    /* HOTAS Warthog Throttle */
  1824         MAKE_VIDPID(0x0738, 0xa221),    /* Saitek Pro Flight X-56 Rhino Throttle */
  1825     };
  1826     int i;
  1827 
  1828     for (i = 0; i < SDL_arraysize(throttle_joysticks); ++i) {
  1829         if (vidpid == throttle_joysticks[i]) {
  1830             return SDL_TRUE;
  1831         }
  1832     }
  1833     return SDL_FALSE;
  1834 }
  1835 
  1836 static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
  1837 {
  1838     Uint16 vendor;
  1839     Uint16 product;
  1840     Uint32 vidpid;
  1841 
  1842     if (SDL_IsJoystickXInput(guid)) {
  1843         /* XInput GUID, get the type based on the XInput device subtype */
  1844         switch (guid.data[15]) {
  1845         case 0x01:  /* XINPUT_DEVSUBTYPE_GAMEPAD */
  1846             return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1847         case 0x02:  /* XINPUT_DEVSUBTYPE_WHEEL */
  1848             return SDL_JOYSTICK_TYPE_WHEEL;
  1849         case 0x03:  /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
  1850             return SDL_JOYSTICK_TYPE_ARCADE_STICK;
  1851         case 0x04:  /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
  1852             return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
  1853         case 0x05:  /* XINPUT_DEVSUBTYPE_DANCE_PAD */
  1854             return SDL_JOYSTICK_TYPE_DANCE_PAD;
  1855         case 0x06:  /* XINPUT_DEVSUBTYPE_GUITAR */
  1856         case 0x07:  /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
  1857         case 0x0B:  /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
  1858             return SDL_JOYSTICK_TYPE_GUITAR;
  1859         case 0x08:  /* XINPUT_DEVSUBTYPE_DRUM_KIT */
  1860             return SDL_JOYSTICK_TYPE_DRUM_KIT;
  1861         case 0x13:  /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
  1862             return SDL_JOYSTICK_TYPE_ARCADE_PAD;
  1863         default:
  1864             return SDL_JOYSTICK_TYPE_UNKNOWN;
  1865         }
  1866     }
  1867 
  1868     if (SDL_IsJoystickWGI(guid)) {
  1869         return (SDL_JoystickType)guid.data[15];
  1870     }
  1871 
  1872     if (SDL_IsJoystickVirtual(guid)) {
  1873         return (SDL_JoystickType)guid.data[15];
  1874     }
  1875 
  1876     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
  1877     vidpid = MAKE_VIDPID(vendor, product);
  1878 
  1879     if (SDL_IsJoystickProductWheel(vidpid)) {
  1880         return SDL_JOYSTICK_TYPE_WHEEL;
  1881     }
  1882 
  1883     if (SDL_IsJoystickProductFlightStick(vidpid)) {
  1884         return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
  1885     }
  1886 
  1887     if (SDL_IsJoystickProductThrottle(vidpid)) {
  1888         return SDL_JOYSTICK_TYPE_THROTTLE;
  1889     }
  1890 
  1891     if (GuessControllerType(vendor, product) != k_eControllerType_UnknownNonSteamController) {
  1892         return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1893     }
  1894 
  1895     return SDL_JOYSTICK_TYPE_UNKNOWN;
  1896 }
  1897 
  1898 static SDL_bool SDL_IsPS4RemapperRunning(void)
  1899 {
  1900 #ifdef __WIN32__
  1901     const char *mapper_processes[] = {
  1902         "DS4Windows.exe",
  1903         "InputMapper.exe",
  1904     };
  1905     int i;
  1906     PROCESSENTRY32 pe32;
  1907     SDL_bool found = SDL_FALSE;
  1908 
  1909     /* Take a snapshot of all processes in the system */
  1910     HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1911     if (hProcessSnap != INVALID_HANDLE_VALUE) {
  1912         pe32.dwSize = sizeof(PROCESSENTRY32);
  1913         if (Process32First(hProcessSnap, &pe32)) {
  1914             do
  1915             {
  1916                 for (i = 0; i < SDL_arraysize(mapper_processes); ++i) {
  1917                     if (SDL_strcasecmp(pe32.szExeFile, mapper_processes[i]) == 0) {
  1918                         found = SDL_TRUE;
  1919                     }
  1920                 }
  1921             } while (Process32Next(hProcessSnap, &pe32) && !found);
  1922         }
  1923         CloseHandle(hProcessSnap);
  1924     }
  1925     return found;
  1926 #else
  1927     return SDL_FALSE;
  1928 #endif
  1929 }
  1930 
  1931 SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
  1932 {
  1933     /* This list is taken from:
  1934        https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
  1935      */
  1936     static Uint32 joystick_blacklist[] = {
  1937         /* Microsoft Microsoft Wireless Optical Desktop 2.10 */
  1938         /* Microsoft Wireless Desktop - Comfort Edition */
  1939         MAKE_VIDPID(0x045e, 0x009d),
  1940 
  1941         /* Microsoft Microsoft Digital Media Pro Keyboard */
  1942         /* Microsoft Corp. Digital Media Pro Keyboard */
  1943         MAKE_VIDPID(0x045e, 0x00b0),
  1944 
  1945         /* Microsoft Microsoft Digital Media Keyboard */
  1946         /* Microsoft Corp. Digital Media Keyboard 1.0A */
  1947         MAKE_VIDPID(0x045e, 0x00b4),
  1948 
  1949         /* Microsoft Microsoft Digital Media Keyboard 3000 */
  1950         MAKE_VIDPID(0x045e, 0x0730),
  1951 
  1952         /* Microsoft Microsoft 2.4GHz Transceiver v6.0 */
  1953         /* Microsoft Microsoft 2.4GHz Transceiver v8.0 */
  1954         /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
  1955         /* Microsoft Wireless Mobile Mouse 1000 */
  1956         /* Microsoft Wireless Desktop 3000 */
  1957         MAKE_VIDPID(0x045e, 0x0745),
  1958 
  1959         /* Microsoft SideWinder(TM) 2.4GHz Transceiver */
  1960         MAKE_VIDPID(0x045e, 0x0748),
  1961 
  1962         /* Microsoft Corp. Wired Keyboard 600 */
  1963         MAKE_VIDPID(0x045e, 0x0750),
  1964 
  1965         /* Microsoft Corp. Sidewinder X4 keyboard */
  1966         MAKE_VIDPID(0x045e, 0x0768),
  1967 
  1968         /* Microsoft Corp. Arc Touch Mouse Transceiver */
  1969         MAKE_VIDPID(0x045e, 0x0773),
  1970 
  1971         /* Microsoft 2.4GHz Transceiver v9.0 */
  1972         /* Microsoft Nano Transceiver v2.1 */
  1973         /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
  1974         MAKE_VIDPID(0x045e, 0x07a5),
  1975 
  1976         /* Microsoft Nano Transceiver v1.0 */
  1977         /* Microsoft Wireless Keyboard 800 */
  1978         MAKE_VIDPID(0x045e, 0x07b2),
  1979 
  1980         /* Microsoft Nano Transceiver v2.0 */
  1981         MAKE_VIDPID(0x045e, 0x0800),
  1982 
  1983         MAKE_VIDPID(0x046d, 0xc30a),  /* Logitech, Inc. iTouch Composite keboard */
  1984 
  1985         MAKE_VIDPID(0x04d9, 0xa0df),  /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */
  1986 
  1987         /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */
  1988         MAKE_VIDPID(0x056a, 0x0010),  /* Wacom ET-0405 Graphire */
  1989         MAKE_VIDPID(0x056a, 0x0011),  /* Wacom ET-0405A Graphire2 (4x5) */
  1990         MAKE_VIDPID(0x056a, 0x0012),  /* Wacom ET-0507A Graphire2 (5x7) */
  1991         MAKE_VIDPID(0x056a, 0x0013),  /* Wacom CTE-430 Graphire3 (4x5) */
  1992         MAKE_VIDPID(0x056a, 0x0014),  /* Wacom CTE-630 Graphire3 (6x8) */
  1993         MAKE_VIDPID(0x056a, 0x0015),  /* Wacom CTE-440 Graphire4 (4x5) */
  1994         MAKE_VIDPID(0x056a, 0x0016),  /* Wacom CTE-640 Graphire4 (6x8) */
  1995         MAKE_VIDPID(0x056a, 0x0017),  /* Wacom CTE-450 Bamboo Fun (4x5) */
  1996         MAKE_VIDPID(0x056a, 0x0018),  /* Wacom CTE-650 Bamboo Fun 6x8 */
  1997         MAKE_VIDPID(0x056a, 0x0019),  /* Wacom CTE-631 Bamboo One */
  1998         MAKE_VIDPID(0x056a, 0x00d1),  /* Wacom Bamboo Pen and Touch CTH-460 */
  1999         MAKE_VIDPID(0x056a, 0x030e),  /* Wacom Intuos Pen (S) CTL-480 */
  2000 
  2001         MAKE_VIDPID(0x09da, 0x054f),  /* A4 Tech Co., G7 750 mouse */
  2002         MAKE_VIDPID(0x09da, 0x1410),  /* A4 Tech Co., Ltd Bloody AL9 mouse */
  2003         MAKE_VIDPID(0x09da, 0x3043),  /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */
  2004         MAKE_VIDPID(0x09da, 0x31b5),  /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */
  2005         MAKE_VIDPID(0x09da, 0x3997),  /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */
  2006         MAKE_VIDPID(0x09da, 0x3f8b),  /* A4 Tech Co., Ltd Bloody V8 mouse */
  2007         MAKE_VIDPID(0x09da, 0x51f4),  /* Modecom MC-5006 Keyboard */
  2008         MAKE_VIDPID(0x09da, 0x5589),  /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */
  2009         MAKE_VIDPID(0x09da, 0x7b22),  /* A4 Tech Co., Ltd Bloody V5 */
  2010         MAKE_VIDPID(0x09da, 0x7f2d),  /* A4 Tech Co., Ltd Bloody R3 mouse */
  2011         MAKE_VIDPID(0x09da, 0x8090),  /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */
  2012         MAKE_VIDPID(0x09da, 0x9033),  /* A4 Tech Co., X7 X-705K */
  2013         MAKE_VIDPID(0x09da, 0x9066),  /* A4 Tech Co., Sharkoon Fireglider Optical */
  2014         MAKE_VIDPID(0x09da, 0x9090),  /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */
  2015         MAKE_VIDPID(0x09da, 0x90c0),  /* A4 Tech Co., Ltd X7 G800V keyboard */
  2016         MAKE_VIDPID(0x09da, 0xf012),  /* A4 Tech Co., Ltd Bloody V7 mouse */
  2017         MAKE_VIDPID(0x09da, 0xf32a),  /* A4 Tech Co., Ltd Bloody B540 keyboard */
  2018         MAKE_VIDPID(0x09da, 0xf613),  /* A4 Tech Co., Ltd Bloody V2 mouse */
  2019         MAKE_VIDPID(0x09da, 0xf624),  /* A4 Tech Co., Ltd Bloody B120 Keyboard */
  2020 
  2021         MAKE_VIDPID(0x1b1c, 0x1b3c),  /* Corsair Harpoon RGB gaming mouse */
  2022 
  2023         MAKE_VIDPID(0x1d57, 0xad03),  /* [T3] 2.4GHz and IR Air Mouse Remote Control */
  2024 
  2025         MAKE_VIDPID(0x1e7d, 0x2e4a),  /* Roccat Tyon Mouse */
  2026 
  2027         MAKE_VIDPID(0x20a0, 0x422d),  /* Winkeyless.kr Keyboards */
  2028 
  2029         MAKE_VIDPID(0x2516, 0x001f),  /* Cooler Master Storm Mizar Mouse */
  2030         MAKE_VIDPID(0x2516, 0x0028),  /* Cooler Master Storm Alcor Mouse */
  2031     };
  2032 
  2033     unsigned int i;
  2034     Uint32 id;
  2035     Uint16 vendor;
  2036     Uint16 product;
  2037 
  2038     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
  2039 
  2040     /* Check the joystick blacklist */
  2041     id = MAKE_VIDPID(vendor, product);
  2042     for (i = 0; i < SDL_arraysize(joystick_blacklist); ++i) {
  2043         if (id == joystick_blacklist[i]) {
  2044             return SDL_TRUE;
  2045         }
  2046     }
  2047 
  2048     if (SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) {
  2049         return SDL_TRUE;
  2050     }
  2051 
  2052     if (SDL_IsGameControllerNameAndGUID(name, guid) &&
  2053         SDL_ShouldIgnoreGameController(name, guid)) {
  2054         return SDL_TRUE;
  2055     }
  2056 
  2057     return SDL_FALSE;
  2058 }
  2059 
  2060 /* return the guid for this index */
  2061 SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
  2062 {
  2063     SDL_JoystickDriver *driver;
  2064     SDL_JoystickGUID guid;
  2065 
  2066     SDL_LockJoysticks();
  2067     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
  2068         guid = driver->GetDeviceGUID(device_index);
  2069     } else {
  2070         SDL_zero(guid);
  2071     }
  2072     SDL_UnlockJoysticks();
  2073 
  2074     return guid;
  2075 }
  2076 
  2077 Uint16 SDL_JoystickGetDeviceVendor(int device_index)
  2078 {
  2079     Uint16 vendor;
  2080     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  2081 
  2082     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
  2083     return vendor;
  2084 }
  2085 
  2086 Uint16 SDL_JoystickGetDeviceProduct(int device_index)
  2087 {
  2088     Uint16 product;
  2089     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  2090 
  2091     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
  2092     return product;
  2093 }
  2094 
  2095 Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
  2096 {
  2097     Uint16 version;
  2098     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  2099 
  2100     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
  2101     return version;
  2102 }
  2103 
  2104 SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
  2105 {
  2106     SDL_JoystickType type;
  2107     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  2108 
  2109     type = SDL_GetJoystickGUIDType(guid);
  2110     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
  2111         if (SDL_IsGameController(device_index)) {
  2112             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  2113         }
  2114     }
  2115     return type;
  2116 }
  2117 
  2118 SDL_JoystickID SDL_JoystickGetDeviceInstanceID(int device_index)
  2119 {
  2120     SDL_JoystickDriver *driver;
  2121     SDL_JoystickID instance_id = -1;
  2122 
  2123     SDL_LockJoysticks();
  2124     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
  2125         instance_id = driver->GetDeviceInstanceID(device_index);
  2126     }
  2127     SDL_UnlockJoysticks();
  2128 
  2129     return instance_id;
  2130 }
  2131 
  2132 int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
  2133 {
  2134     int i, num_joysticks, device_index = -1;
  2135 
  2136     SDL_LockJoysticks();
  2137     num_joysticks = SDL_NumJoysticks();
  2138     for (i = 0; i < num_joysticks; ++i) {
  2139         if (SDL_JoystickGetDeviceInstanceID(i) == instance_id) {
  2140             device_index = i;
  2141             break;
  2142         }
  2143     }
  2144     SDL_UnlockJoysticks();
  2145 
  2146     return device_index;
  2147 }
  2148 
  2149 SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
  2150 {
  2151     if (!SDL_PrivateJoystickValid(joystick)) {
  2152         SDL_JoystickGUID emptyGUID;
  2153         SDL_zero(emptyGUID);
  2154         return emptyGUID;
  2155     }
  2156     return joystick->guid;
  2157 }
  2158 
  2159 Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick)
  2160 {
  2161     Uint16 vendor;
  2162     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  2163 
  2164     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
  2165     return vendor;
  2166 }
  2167 
  2168 Uint16 SDL_JoystickGetProduct(SDL_Joystick * joystick)
  2169 {
  2170     Uint16 product;
  2171     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  2172 
  2173     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
  2174     return product;
  2175 }
  2176 
  2177 Uint16 SDL_JoystickGetProductVersion(SDL_Joystick * joystick)
  2178 {
  2179     Uint16 version;
  2180     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  2181 
  2182     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
  2183     return version;
  2184 }
  2185 
  2186 SDL_JoystickType SDL_JoystickGetType(SDL_Joystick * joystick)
  2187 {
  2188     SDL_JoystickType type;
  2189     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  2190 
  2191     type = SDL_GetJoystickGUIDType(guid);
  2192     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
  2193         if (joystick && joystick->is_game_controller) {
  2194             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  2195         }
  2196     }
  2197     return type;
  2198 }
  2199 
  2200 /* convert the guid to a printable string */
  2201 void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
  2202 {
  2203     static const char k_rgchHexToASCII[] = "0123456789abcdef";
  2204     int i;
  2205 
  2206     if ((pszGUID == NULL) || (cbGUID <= 0)) {
  2207         return;
  2208     }
  2209 
  2210     for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
  2211         /* each input byte writes 2 ascii chars, and might write a null byte. */
  2212         /* If we don't have room for next input byte, stop */
  2213         unsigned char c = guid.data[i];
  2214 
  2215         *pszGUID++ = k_rgchHexToASCII[c >> 4];
  2216         *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
  2217     }
  2218     *pszGUID = '\0';
  2219 }
  2220 
  2221 /*-----------------------------------------------------------------------------
  2222  * Purpose: Returns the 4 bit nibble for a hex character
  2223  * Input  : c -
  2224  * Output : unsigned char
  2225  *-----------------------------------------------------------------------------*/
  2226 static unsigned char nibble(char c)
  2227 {
  2228     if ((c >= '0') && (c <= '9')) {
  2229         return (unsigned char)(c - '0');
  2230     }
  2231 
  2232     if ((c >= 'A') && (c <= 'F')) {
  2233         return (unsigned char)(c - 'A' + 0x0a);
  2234     }
  2235 
  2236     if ((c >= 'a') && (c <= 'f')) {
  2237         return (unsigned char)(c - 'a' + 0x0a);
  2238     }
  2239 
  2240     /* received an invalid character, and no real way to return an error */
  2241     /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
  2242     return 0;
  2243 }
  2244 
  2245 /* convert the string version of a joystick guid to the struct */
  2246 SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
  2247 {
  2248     SDL_JoystickGUID guid;
  2249     int maxoutputbytes= sizeof(guid);
  2250     size_t len = SDL_strlen(pchGUID);
  2251     Uint8 *p;
  2252     size_t i;
  2253 
  2254     /* Make sure it's even */
  2255     len = (len) & ~0x1;
  2256 
  2257     SDL_memset(&guid, 0x00, sizeof(guid));
  2258 
  2259     p = (Uint8 *)&guid;
  2260     for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
  2261         *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
  2262     }
  2263 
  2264     return guid;
  2265 }
  2266 
  2267 /* update the power level for this joystick */
  2268 void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
  2269 {
  2270     joystick->epowerlevel = ePowerLevel;
  2271 }
  2272 
  2273 /* return its power level */
  2274 SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
  2275 {
  2276     if (!SDL_PrivateJoystickValid(joystick)) {
  2277         return SDL_JOYSTICK_POWER_UNKNOWN;
  2278     }
  2279     return joystick->epowerlevel;
  2280 }
  2281 
  2282 /* vi: set ts=4 sw=4 expandtab: */