src/joystick/SDL_joystick.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 10 Aug 2018 14:32:30 -0400
changeset 12104 fc8ab202b5a8
parent 12090 c3209fca27b2
child 12105 997ec56425a8
permissions -rw-r--r--
emscripten: Patched to compile with new joystick interfaces.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 
    37 /* This is included in only one place because it has a large static list of controllers */
    38 #include "controller_type.h"
    39 
    40 #ifdef __WIN32__
    41 /* Needed for checking for input remapping programs */
    42 #include "../core/windows/SDL_windows.h"
    43 
    44 #undef UNICODE          /* We want ASCII functions */
    45 #include <tlhelp32.h>
    46 #endif
    47 
    48 static SDL_JoystickDriver *SDL_joystick_drivers[] = {
    49 #if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
    50     &SDL_WINDOWS_JoystickDriver,
    51 #endif
    52 #ifdef SDL_JOYSTICK_LINUX
    53     &SDL_LINUX_JoystickDriver,
    54 #endif
    55 #ifdef SDL_JOYSTICK_IOKIT
    56     &SDL_DARWIN_JoystickDriver,
    57 #endif
    58 #if defined(__IPHONEOS__) || defined(__TVOS__)
    59     &SDL_IOS_JoystickDriver,
    60 #endif
    61 #ifdef SDL_JOYSTICK_ANDROID
    62     &SDL_ANDROID_JoystickDriver,
    63 #endif
    64 #ifdef SDL_JOYSTICK_EMSCRIPTEN
    65     &SDL_EMSCRIPTEN_JoystickDriver,
    66 #endif
    67 #ifdef SDL_JOYSTICK_HIDAPI
    68     &SDL_HIDAPI_JoystickDriver,
    69 #endif
    70 #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
    71     &SDL_DUMMY_JoystickDriver
    72 #endif
    73 };
    74 static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
    75 static SDL_Joystick *SDL_joysticks = NULL;
    76 static SDL_bool SDL_updating_joystick = SDL_FALSE;
    77 static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
    78 static SDL_atomic_t SDL_next_joystick_instance_id;
    79 
    80 void
    81 SDL_LockJoysticks(void)
    82 {
    83     if (SDL_joystick_lock) {
    84         SDL_LockMutex(SDL_joystick_lock);
    85     }
    86 }
    87 
    88 void
    89 SDL_UnlockJoysticks(void)
    90 {
    91     if (SDL_joystick_lock) {
    92         SDL_UnlockMutex(SDL_joystick_lock);
    93     }
    94 }
    95 
    96 
    97 static void SDLCALL
    98 SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
    99 {
   100     if (hint && *hint == '1') {
   101         SDL_joystick_allows_background_events = SDL_TRUE;
   102     } else {
   103         SDL_joystick_allows_background_events = SDL_FALSE;
   104     }
   105 }
   106 
   107 int
   108 SDL_JoystickInit(void)
   109 {
   110     int i, status;
   111 
   112     SDL_GameControllerInitMappings();
   113 
   114     /* Create the joystick list lock */
   115     if (!SDL_joystick_lock) {
   116         SDL_joystick_lock = SDL_CreateMutex();
   117     }
   118 
   119     /* See if we should allow joystick events while in the background */
   120     SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
   121                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
   122 
   123 #if !SDL_EVENTS_DISABLED
   124     if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
   125         return -1;
   126     }
   127 #endif /* !SDL_EVENTS_DISABLED */
   128 
   129     status = -1;
   130     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   131         if (SDL_joystick_drivers[i]->Init() >= 0) {
   132             status = 0;
   133         }
   134     }
   135     return status;
   136 }
   137 
   138 /*
   139  * Count the number of joysticks attached to the system
   140  */
   141 int
   142 SDL_NumJoysticks(void)
   143 {
   144     int i, total_joysticks = 0;
   145     SDL_LockJoysticks();
   146     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   147         total_joysticks += SDL_joystick_drivers[i]->GetCount();
   148     }
   149     SDL_UnlockJoysticks();
   150     return total_joysticks;
   151 }
   152 
   153 /*
   154  * Return the next available joystick instance ID
   155  * This may be called by drivers from multiple threads, unprotected by any locks
   156  */
   157 SDL_JoystickID SDL_GetNextJoystickInstanceID()
   158 {
   159     return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
   160 }
   161 
   162 /*
   163  * Get the driver and device index for an API device index
   164  * This should be called while the joystick lock is held, to prevent another thread from updating the list
   165  */
   166 SDL_bool
   167 SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index)
   168 {
   169     int i, num_joysticks, total_joysticks = 0;
   170 
   171     if (device_index >= 0) {
   172         for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   173             num_joysticks = SDL_joystick_drivers[i]->GetCount();
   174             if (device_index < num_joysticks) {
   175                 *driver = SDL_joystick_drivers[i];
   176                 *driver_index = device_index;
   177                 return SDL_TRUE;
   178             }
   179             device_index -= num_joysticks;
   180             total_joysticks += num_joysticks;
   181         }
   182     }
   183 
   184     SDL_SetError("There are %d joysticks available", total_joysticks);
   185     return SDL_FALSE;
   186 }
   187 
   188 /*
   189  * Perform any needed fixups for joystick names
   190  */
   191 static const char *
   192 SDL_FixupJoystickName(const char *name)
   193 {
   194     if (name) {
   195         const char *skip_prefix = "NVIDIA Corporation ";
   196 
   197         if (SDL_strncmp(name, skip_prefix, SDL_strlen(skip_prefix)) == 0) {
   198             name += SDL_strlen(skip_prefix);
   199         }
   200     }
   201     return name;
   202 }
   203 
   204 
   205 /*
   206  * Get the implementation dependent name of a joystick
   207  */
   208 const char *
   209 SDL_JoystickNameForIndex(int device_index)
   210 {
   211     SDL_JoystickDriver *driver;
   212     const char *name = NULL;
   213 
   214     SDL_LockJoysticks();
   215     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   216         name = SDL_FixupJoystickName(driver->GetDeviceName(device_index));
   217     }
   218     SDL_UnlockJoysticks();
   219 
   220     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */
   221     return name;
   222 }
   223 
   224 /*
   225  * Return true if this joystick is known to have all axes centered at zero
   226  * This isn't generally needed unless the joystick never generates an initial axis value near zero,
   227  * e.g. it's emulating axes with digital buttons
   228  */
   229 static SDL_bool
   230 SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
   231 {
   232     static Uint32 zero_centered_joysticks[] = {
   233         MAKE_VIDPID(0x0e8f, 0x3013),    /* HuiJia SNES USB adapter */
   234         MAKE_VIDPID(0x05a0, 0x3232),    /* 8Bitdo Zero Gamepad */
   235     };
   236 
   237     int i;
   238     Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick),
   239                             SDL_JoystickGetProduct(joystick));
   240 
   241 /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
   242 
   243     if (joystick->naxes == 2) {
   244         /* Assume D-pad or thumbstick style axes are centered at 0 */
   245         return SDL_TRUE;
   246     }
   247 
   248     for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
   249         if (id == zero_centered_joysticks[i]) {
   250             return SDL_TRUE;
   251         }
   252     }
   253     return SDL_FALSE;
   254 }
   255 
   256 /*
   257  * Open a joystick for use - the index passed as an argument refers to
   258  * the N'th joystick on the system.  This index is the value which will
   259  * identify this joystick in future joystick events.
   260  *
   261  * This function returns a joystick identifier, or NULL if an error occurred.
   262  */
   263 SDL_Joystick *
   264 SDL_JoystickOpen(int device_index)
   265 {
   266     SDL_JoystickDriver *driver;
   267     SDL_JoystickID instance_id;
   268     SDL_Joystick *joystick;
   269     SDL_Joystick *joysticklist;
   270     const char *joystickname = NULL;
   271 
   272     SDL_LockJoysticks();
   273 
   274     if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   275         SDL_UnlockJoysticks();
   276         return NULL;
   277     }
   278 
   279     joysticklist = SDL_joysticks;
   280     /* If the joystick is already open, return it
   281      * it is important that we have a single joystick * for each instance id
   282      */
   283     instance_id = driver->GetDeviceInstanceID(device_index);
   284     while (joysticklist) {
   285         if (instance_id == joysticklist->instance_id) {
   286                 joystick = joysticklist;
   287                 ++joystick->ref_count;
   288                 SDL_UnlockJoysticks();
   289                 return joystick;
   290         }
   291         joysticklist = joysticklist->next;
   292     }
   293 
   294     /* Create and initialize the joystick */
   295     joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
   296     if (joystick == NULL) {
   297         SDL_OutOfMemory();
   298         SDL_UnlockJoysticks();
   299         return NULL;
   300     }
   301     joystick->driver = driver;
   302     joystick->instance_id = instance_id;
   303     joystick->attached = SDL_TRUE;
   304 
   305     if (driver->Open(joystick, device_index) < 0) {
   306         SDL_free(joystick);
   307         SDL_UnlockJoysticks();
   308         return NULL;
   309     }
   310 
   311     joystickname = driver->GetDeviceName(device_index);
   312     if (joystickname) {
   313         joystick->name = SDL_strdup(joystickname);
   314     } else {
   315         joystick->name = NULL;
   316     }
   317 
   318     joystick->guid = driver->GetDeviceGUID(device_index);
   319 
   320     if (joystick->naxes > 0) {
   321         joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
   322     }
   323     if (joystick->nhats > 0) {
   324         joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8));
   325     }
   326     if (joystick->nballs > 0) {
   327         joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls));
   328     }
   329     if (joystick->nbuttons > 0) {
   330         joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8));
   331     }
   332     if (((joystick->naxes > 0) && !joystick->axes)
   333         || ((joystick->nhats > 0) && !joystick->hats)
   334         || ((joystick->nballs > 0) && !joystick->balls)
   335         || ((joystick->nbuttons > 0) && !joystick->buttons)) {
   336         SDL_OutOfMemory();
   337         SDL_JoystickClose(joystick);
   338         SDL_UnlockJoysticks();
   339         return NULL;
   340     }
   341     joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
   342 
   343     /* If this joystick is known to have all zero centered axes, skip the auto-centering code */
   344     if (SDL_JoystickAxesCenteredAtZero(joystick)) {
   345         int i;
   346 
   347         for (i = 0; i < joystick->naxes; ++i) {
   348             joystick->axes[i].has_initial_value = SDL_TRUE;
   349         }
   350     }
   351 
   352     joystick->is_game_controller = SDL_IsGameController(device_index);
   353 
   354     /* Add joystick to list */
   355     ++joystick->ref_count;
   356     /* Link the joystick in the list */
   357     joystick->next = SDL_joysticks;
   358     SDL_joysticks = joystick;
   359 
   360     SDL_UnlockJoysticks();
   361 
   362     driver->Update(joystick);
   363 
   364     return joystick;
   365 }
   366 
   367 
   368 /*
   369  * Checks to make sure the joystick is valid.
   370  */
   371 int
   372 SDL_PrivateJoystickValid(SDL_Joystick * joystick)
   373 {
   374     int valid;
   375 
   376     if (joystick == NULL) {
   377         SDL_SetError("Joystick hasn't been opened yet");
   378         valid = 0;
   379     } else {
   380         valid = 1;
   381     }
   382 
   383     return valid;
   384 }
   385 
   386 /*
   387  * Get the number of multi-dimensional axis controls on a joystick
   388  */
   389 int
   390 SDL_JoystickNumAxes(SDL_Joystick * joystick)
   391 {
   392     if (!SDL_PrivateJoystickValid(joystick)) {
   393         return -1;
   394     }
   395     return joystick->naxes;
   396 }
   397 
   398 /*
   399  * Get the number of hats on a joystick
   400  */
   401 int
   402 SDL_JoystickNumHats(SDL_Joystick * joystick)
   403 {
   404     if (!SDL_PrivateJoystickValid(joystick)) {
   405         return -1;
   406     }
   407     return joystick->nhats;
   408 }
   409 
   410 /*
   411  * Get the number of trackballs on a joystick
   412  */
   413 int
   414 SDL_JoystickNumBalls(SDL_Joystick * joystick)
   415 {
   416     if (!SDL_PrivateJoystickValid(joystick)) {
   417         return -1;
   418     }
   419     return joystick->nballs;
   420 }
   421 
   422 /*
   423  * Get the number of buttons on a joystick
   424  */
   425 int
   426 SDL_JoystickNumButtons(SDL_Joystick * joystick)
   427 {
   428     if (!SDL_PrivateJoystickValid(joystick)) {
   429         return -1;
   430     }
   431     return joystick->nbuttons;
   432 }
   433 
   434 /*
   435  * Get the current state of an axis control on a joystick
   436  */
   437 Sint16
   438 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
   439 {
   440     Sint16 state;
   441 
   442     if (!SDL_PrivateJoystickValid(joystick)) {
   443         return 0;
   444     }
   445     if (axis < joystick->naxes) {
   446         state = joystick->axes[axis].value;
   447     } else {
   448         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   449         state = 0;
   450     }
   451     return state;
   452 }
   453 
   454 /*
   455  * Get the initial state of an axis control on a joystick
   456  */
   457 SDL_bool
   458 SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick, int axis, Sint16 *state)
   459 {
   460     if (!SDL_PrivateJoystickValid(joystick)) {
   461         return SDL_FALSE;
   462     }
   463     if (axis >= joystick->naxes) {
   464         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   465         return SDL_FALSE;
   466     }
   467     if (state) {
   468         *state = joystick->axes[axis].initial_value;
   469     }
   470     return joystick->axes[axis].has_initial_value;
   471 }
   472 
   473 /*
   474  * Get the current state of a hat on a joystick
   475  */
   476 Uint8
   477 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
   478 {
   479     Uint8 state;
   480 
   481     if (!SDL_PrivateJoystickValid(joystick)) {
   482         return 0;
   483     }
   484     if (hat < joystick->nhats) {
   485         state = joystick->hats[hat];
   486     } else {
   487         SDL_SetError("Joystick only has %d hats", joystick->nhats);
   488         state = 0;
   489     }
   490     return state;
   491 }
   492 
   493 /*
   494  * Get the ball axis change since the last poll
   495  */
   496 int
   497 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
   498 {
   499     int retval;
   500 
   501     if (!SDL_PrivateJoystickValid(joystick)) {
   502         return -1;
   503     }
   504 
   505     retval = 0;
   506     if (ball < joystick->nballs) {
   507         if (dx) {
   508             *dx = joystick->balls[ball].dx;
   509         }
   510         if (dy) {
   511             *dy = joystick->balls[ball].dy;
   512         }
   513         joystick->balls[ball].dx = 0;
   514         joystick->balls[ball].dy = 0;
   515     } else {
   516         return SDL_SetError("Joystick only has %d balls", joystick->nballs);
   517     }
   518     return retval;
   519 }
   520 
   521 /*
   522  * Get the current state of a button on a joystick
   523  */
   524 Uint8
   525 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
   526 {
   527     Uint8 state;
   528 
   529     if (!SDL_PrivateJoystickValid(joystick)) {
   530         return 0;
   531     }
   532     if (button < joystick->nbuttons) {
   533         state = joystick->buttons[button];
   534     } else {
   535         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
   536         state = 0;
   537     }
   538     return state;
   539 }
   540 
   541 /*
   542  * Return if the joystick in question is currently attached to the system,
   543  *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
   544  */
   545 SDL_bool
   546 SDL_JoystickGetAttached(SDL_Joystick * joystick)
   547 {
   548     if (!SDL_PrivateJoystickValid(joystick)) {
   549         return SDL_FALSE;
   550     }
   551 
   552     return joystick->attached;
   553 }
   554 
   555 /*
   556  * Get the instance id for this opened joystick
   557  */
   558 SDL_JoystickID
   559 SDL_JoystickInstanceID(SDL_Joystick * joystick)
   560 {
   561     if (!SDL_PrivateJoystickValid(joystick)) {
   562         return -1;
   563     }
   564 
   565     return joystick->instance_id;
   566 }
   567 
   568 /*
   569  * Find the SDL_Joystick that owns this instance id
   570  */
   571 SDL_Joystick *
   572 SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
   573 {
   574     SDL_Joystick *joystick;
   575 
   576     SDL_LockJoysticks();
   577     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   578         if (joystick->instance_id == joyid) {
   579             SDL_UnlockJoysticks();
   580             return joystick;
   581         }
   582     }
   583     SDL_UnlockJoysticks();
   584     return NULL;
   585 }
   586 
   587 /*
   588  * Get the friendly name of this joystick
   589  */
   590 const char *
   591 SDL_JoystickName(SDL_Joystick * joystick)
   592 {
   593     if (!SDL_PrivateJoystickValid(joystick)) {
   594         return NULL;
   595     }
   596 
   597     return SDL_FixupJoystickName(joystick->name);
   598 }
   599 
   600 int
   601 SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   602 {
   603     if (!SDL_PrivateJoystickValid(joystick)) {
   604         return -1;
   605     }
   606     return joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
   607 }
   608 
   609 /*
   610  * Close a joystick previously opened with SDL_JoystickOpen()
   611  */
   612 void
   613 SDL_JoystickClose(SDL_Joystick * joystick)
   614 {
   615     SDL_Joystick *joysticklist;
   616     SDL_Joystick *joysticklistprev;
   617 
   618     if (!SDL_PrivateJoystickValid(joystick)) {
   619         return;
   620     }
   621 
   622     SDL_LockJoysticks();
   623 
   624     /* First decrement ref count */
   625     if (--joystick->ref_count > 0) {
   626         SDL_UnlockJoysticks();
   627         return;
   628     }
   629 
   630     if (SDL_updating_joystick) {
   631         SDL_UnlockJoysticks();
   632         return;
   633     }
   634 
   635     joystick->driver->Close(joystick);
   636     joystick->hwdata = NULL;
   637 
   638     joysticklist = SDL_joysticks;
   639     joysticklistprev = NULL;
   640     while (joysticklist) {
   641         if (joystick == joysticklist) {
   642             if (joysticklistprev) {
   643                 /* unlink this entry */
   644                 joysticklistprev->next = joysticklist->next;
   645             } else {
   646                 SDL_joysticks = joystick->next;
   647             }
   648             break;
   649         }
   650         joysticklistprev = joysticklist;
   651         joysticklist = joysticklist->next;
   652     }
   653 
   654     SDL_free(joystick->name);
   655 
   656     /* Free the data associated with this joystick */
   657     SDL_free(joystick->axes);
   658     SDL_free(joystick->hats);
   659     SDL_free(joystick->balls);
   660     SDL_free(joystick->buttons);
   661     SDL_free(joystick);
   662 
   663     SDL_UnlockJoysticks();
   664 }
   665 
   666 void
   667 SDL_JoystickQuit(void)
   668 {
   669     int i;
   670 
   671     /* Make sure we're not getting called in the middle of updating joysticks */
   672     SDL_assert(!SDL_updating_joystick);
   673 
   674     SDL_LockJoysticks();
   675 
   676     /* Stop the event polling */
   677     while (SDL_joysticks) {
   678         SDL_joysticks->ref_count = 1;
   679         SDL_JoystickClose(SDL_joysticks);
   680     }
   681 
   682     /* Quit the joystick setup */
   683     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
   684        SDL_joystick_drivers[i]->Quit();
   685     }
   686 
   687     SDL_UnlockJoysticks();
   688 
   689 #if !SDL_EVENTS_DISABLED
   690     SDL_QuitSubSystem(SDL_INIT_EVENTS);
   691 #endif
   692 
   693     SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
   694                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
   695 
   696     if (SDL_joystick_lock) {
   697         SDL_DestroyMutex(SDL_joystick_lock);
   698         SDL_joystick_lock = NULL;
   699     }
   700 
   701     SDL_GameControllerQuitMappings();
   702 }
   703 
   704 
   705 static SDL_bool
   706 SDL_PrivateJoystickShouldIgnoreEvent()
   707 {
   708     if (SDL_joystick_allows_background_events) {
   709         return SDL_FALSE;
   710     }
   711 
   712     if (SDL_HasWindows() && SDL_GetKeyboardFocus() == NULL) {
   713         /* We have windows but we don't have focus, ignore the event. */
   714         return SDL_TRUE;
   715     }
   716     return SDL_FALSE;
   717 }
   718 
   719 /* These are global for SDL_sysjoystick.c and SDL_events.c */
   720 
   721 void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
   722 {
   723 #if !SDL_EVENTS_DISABLED
   724     SDL_Event event;
   725     int device_index;
   726 
   727     device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
   728     if (device_index < 0) {
   729         return;
   730     }
   731 
   732     event.type = SDL_JOYDEVICEADDED;
   733 
   734     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   735         event.jdevice.which = device_index;
   736         SDL_PushEvent(&event);
   737     }
   738 #endif /* !SDL_EVENTS_DISABLED */
   739 }
   740 
   741 /*
   742  * If there is an existing add event in the queue, it needs to be modified
   743  * to have the right value for which, because the number of controllers in
   744  * the system is now one less.
   745  */
   746 static void UpdateEventsForDeviceRemoval()
   747 {
   748     int i, num_events;
   749     SDL_Event *events;
   750 
   751     num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
   752     if (num_events <= 0) {
   753         return;
   754     }
   755 
   756     events = SDL_stack_alloc(SDL_Event, num_events);
   757     if (!events) {
   758         return;
   759     }
   760 
   761     num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
   762     for (i = 0; i < num_events; ++i) {
   763         --events[i].jdevice.which;
   764     }
   765     SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
   766 
   767     SDL_stack_free(events);
   768 }
   769 
   770 void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
   771 {
   772     SDL_Joystick *joystick;
   773 
   774 #if !SDL_EVENTS_DISABLED
   775     SDL_Event event;
   776 
   777     event.type = SDL_JOYDEVICEREMOVED;
   778 
   779     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   780         event.jdevice.which = device_instance;
   781         SDL_PushEvent(&event);
   782     }
   783 
   784     UpdateEventsForDeviceRemoval();
   785 #endif /* !SDL_EVENTS_DISABLED */
   786 
   787     /* Mark this joystick as no longer attached */
   788     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   789         if (joystick->instance_id == device_instance) {
   790             joystick->attached = SDL_FALSE;
   791             joystick->force_recentering = SDL_TRUE;
   792             break;
   793         }
   794     }
   795 }
   796 
   797 int
   798 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
   799 {
   800     int posted;
   801 
   802     /* Make sure we're not getting garbage or duplicate events */
   803     if (axis >= joystick->naxes) {
   804         return 0;
   805     }
   806     if (!joystick->axes[axis].has_initial_value) {
   807         joystick->axes[axis].initial_value = value;
   808         joystick->axes[axis].value = value;
   809         joystick->axes[axis].zero = value;
   810         joystick->axes[axis].has_initial_value = SDL_TRUE;
   811     }
   812     if (value == joystick->axes[axis].value) {
   813         return 0;
   814     }
   815     if (!joystick->axes[axis].sent_initial_value) {
   816         /* Make sure we don't send motion until there's real activity on this axis */
   817         const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
   818         if (SDL_abs(value - joystick->axes[axis].value) <= MAX_ALLOWED_JITTER) {
   819             return 0;
   820         }
   821         joystick->axes[axis].sent_initial_value = SDL_TRUE;
   822         joystick->axes[axis].value = value; /* Just so we pass the check above */
   823         SDL_PrivateJoystickAxis(joystick, axis, joystick->axes[axis].initial_value);
   824     }
   825 
   826     /* We ignore events if we don't have keyboard focus, except for centering
   827      * events.
   828      */
   829     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   830         if ((value > joystick->axes[axis].zero && value >= joystick->axes[axis].value) ||
   831             (value < joystick->axes[axis].zero && value <= joystick->axes[axis].value)) {
   832             return 0;
   833         }
   834     }
   835 
   836     /* Update internal joystick state */
   837     joystick->axes[axis].value = value;
   838 
   839     /* Post the event, if desired */
   840     posted = 0;
   841 #if !SDL_EVENTS_DISABLED
   842     if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
   843         SDL_Event event;
   844         event.type = SDL_JOYAXISMOTION;
   845         event.jaxis.which = joystick->instance_id;
   846         event.jaxis.axis = axis;
   847         event.jaxis.value = value;
   848         posted = SDL_PushEvent(&event) == 1;
   849     }
   850 #endif /* !SDL_EVENTS_DISABLED */
   851     return posted;
   852 }
   853 
   854 int
   855 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
   856 {
   857     int posted;
   858 
   859     /* Make sure we're not getting garbage or duplicate events */
   860     if (hat >= joystick->nhats) {
   861         return 0;
   862     }
   863     if (value == joystick->hats[hat]) {
   864         return 0;
   865     }
   866 
   867     /* We ignore events if we don't have keyboard focus, except for centering
   868      * events.
   869      */
   870     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   871         if (value != SDL_HAT_CENTERED) {
   872             return 0;
   873         }
   874     }
   875 
   876     /* Update internal joystick state */
   877     joystick->hats[hat] = value;
   878 
   879     /* Post the event, if desired */
   880     posted = 0;
   881 #if !SDL_EVENTS_DISABLED
   882     if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
   883         SDL_Event event;
   884         event.jhat.type = SDL_JOYHATMOTION;
   885         event.jhat.which = joystick->instance_id;
   886         event.jhat.hat = hat;
   887         event.jhat.value = value;
   888         posted = SDL_PushEvent(&event) == 1;
   889     }
   890 #endif /* !SDL_EVENTS_DISABLED */
   891     return posted;
   892 }
   893 
   894 int
   895 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
   896                         Sint16 xrel, Sint16 yrel)
   897 {
   898     int posted;
   899 
   900     /* Make sure we're not getting garbage events */
   901     if (ball >= joystick->nballs) {
   902         return 0;
   903     }
   904 
   905     /* We ignore events if we don't have keyboard focus. */
   906     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   907         return 0;
   908     }
   909 
   910     /* Update internal mouse state */
   911     joystick->balls[ball].dx += xrel;
   912     joystick->balls[ball].dy += yrel;
   913 
   914     /* Post the event, if desired */
   915     posted = 0;
   916 #if !SDL_EVENTS_DISABLED
   917     if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
   918         SDL_Event event;
   919         event.jball.type = SDL_JOYBALLMOTION;
   920         event.jball.which = joystick->instance_id;
   921         event.jball.ball = ball;
   922         event.jball.xrel = xrel;
   923         event.jball.yrel = yrel;
   924         posted = SDL_PushEvent(&event) == 1;
   925     }
   926 #endif /* !SDL_EVENTS_DISABLED */
   927     return posted;
   928 }
   929 
   930 int
   931 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
   932 {
   933     int posted;
   934 #if !SDL_EVENTS_DISABLED
   935     SDL_Event event;
   936 
   937     switch (state) {
   938     case SDL_PRESSED:
   939         event.type = SDL_JOYBUTTONDOWN;
   940         break;
   941     case SDL_RELEASED:
   942         event.type = SDL_JOYBUTTONUP;
   943         break;
   944     default:
   945         /* Invalid state -- bail */
   946         return 0;
   947     }
   948 #endif /* !SDL_EVENTS_DISABLED */
   949 
   950     /* Make sure we're not getting garbage or duplicate events */
   951     if (button >= joystick->nbuttons) {
   952         return 0;
   953     }
   954     if (state == joystick->buttons[button]) {
   955         return 0;
   956     }
   957 
   958     /* We ignore events if we don't have keyboard focus, except for button
   959      * release. */
   960     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
   961         if (state == SDL_PRESSED) {
   962             return 0;
   963         }
   964     }
   965 
   966     /* Update internal joystick state */
   967     joystick->buttons[button] = state;
   968 
   969     /* Post the event, if desired */
   970     posted = 0;
   971 #if !SDL_EVENTS_DISABLED
   972     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   973         event.jbutton.which = joystick->instance_id;
   974         event.jbutton.button = button;
   975         event.jbutton.state = state;
   976         posted = SDL_PushEvent(&event) == 1;
   977     }
   978 #endif /* !SDL_EVENTS_DISABLED */
   979     return posted;
   980 }
   981 
   982 void
   983 SDL_JoystickUpdate(void)
   984 {
   985     int i;
   986     SDL_Joystick *joystick;
   987 
   988     SDL_LockJoysticks();
   989 
   990     if (SDL_updating_joystick) {
   991         /* The joysticks are already being updated */
   992         SDL_UnlockJoysticks();
   993         return;
   994     }
   995 
   996     SDL_updating_joystick = SDL_TRUE;
   997 
   998     /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
   999     SDL_UnlockJoysticks();
  1000 
  1001     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
  1002         if (joystick->attached) {
  1003             joystick->driver->Update(joystick);
  1004 
  1005             if (joystick->delayed_guide_button) {
  1006                 SDL_GameControllerHandleDelayedGuideButton(joystick);
  1007             }
  1008         }
  1009 
  1010         if (joystick->force_recentering) {
  1011             /* Tell the app that everything is centered/unpressed... */
  1012             for (i = 0; i < joystick->naxes; i++) {
  1013                 if (joystick->axes[i].has_initial_value) {
  1014                     SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
  1015                 }
  1016             }
  1017 
  1018             for (i = 0; i < joystick->nbuttons; i++) {
  1019                 SDL_PrivateJoystickButton(joystick, i, 0);
  1020             }
  1021 
  1022             for (i = 0; i < joystick->nhats; i++) {
  1023                 SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
  1024             }
  1025 
  1026             joystick->force_recentering = SDL_FALSE;
  1027         }
  1028     }
  1029 
  1030     SDL_LockJoysticks();
  1031 
  1032     SDL_updating_joystick = SDL_FALSE;
  1033 
  1034     /* If any joysticks were closed while updating, free them here */
  1035     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
  1036         if (joystick->ref_count <= 0) {
  1037             SDL_JoystickClose(joystick);
  1038         }
  1039     }
  1040 
  1041     /* this needs to happen AFTER walking the joystick list above, so that any
  1042        dangling hardware data from removed devices can be free'd
  1043      */
  1044     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
  1045         SDL_joystick_drivers[i]->Detect();
  1046     }
  1047 
  1048     SDL_UnlockJoysticks();
  1049 }
  1050 
  1051 int
  1052 SDL_JoystickEventState(int state)
  1053 {
  1054 #if SDL_EVENTS_DISABLED
  1055     return SDL_DISABLE;
  1056 #else
  1057     const Uint32 event_list[] = {
  1058         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
  1059         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
  1060     };
  1061     unsigned int i;
  1062 
  1063     switch (state) {
  1064     case SDL_QUERY:
  1065         state = SDL_DISABLE;
  1066         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1067             state = SDL_EventState(event_list[i], SDL_QUERY);
  1068             if (state == SDL_ENABLE) {
  1069                 break;
  1070             }
  1071         }
  1072         break;
  1073     default:
  1074         for (i = 0; i < SDL_arraysize(event_list); ++i) {
  1075             SDL_EventState(event_list[i], state);
  1076         }
  1077         break;
  1078     }
  1079     return state;
  1080 #endif /* SDL_EVENTS_DISABLED */
  1081 }
  1082 
  1083 void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
  1084 {
  1085     Uint16 *guid16 = (Uint16 *)guid.data;
  1086 
  1087     /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
  1088     if (/* guid16[0] is device bus type */
  1089         guid16[1] == 0x0000 &&
  1090         /* guid16[2] is vendor ID */
  1091         guid16[3] == 0x0000 &&
  1092         /* guid16[4] is product ID */
  1093         guid16[5] == 0x0000
  1094         /* guid16[6] is product version */
  1095    ) {
  1096         if (vendor) {
  1097             *vendor = guid16[2];
  1098         }
  1099         if (product) {
  1100             *product = guid16[4];
  1101         }
  1102         if (version) {
  1103             *version = guid16[6];
  1104         }
  1105     } else {
  1106         if (vendor) {
  1107             *vendor = 0;
  1108         }
  1109         if (product) {
  1110             *product = 0;
  1111         }
  1112         if (version) {
  1113             *version = 0;
  1114         }
  1115     }
  1116 }
  1117 
  1118 SDL_bool
  1119 SDL_IsJoystickPS4(Uint16 vendor, Uint16 product)
  1120 {
  1121     return (GuessControllerType(vendor, product) == k_eControllerType_PS4Controller);
  1122 }
  1123 
  1124 SDL_bool
  1125 SDL_IsJoystickNintendoSwitchPro(Uint16 vendor, Uint16 product)
  1126 {
  1127     return (GuessControllerType(vendor, product) == k_eControllerType_SwitchProController);
  1128 }
  1129 
  1130 SDL_bool
  1131 SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product)
  1132 {
  1133     return BIsSteamController(GuessControllerType(vendor, product)) ? SDL_TRUE : SDL_FALSE;
  1134 }
  1135 
  1136 SDL_bool
  1137 SDL_IsJoystickXbox360(Uint16 vendor, Uint16 product)
  1138 {
  1139 	/* Filter out some bogus values here */
  1140 	if (vendor == 0x0000 && product == 0x0000) {
  1141 		return SDL_FALSE;
  1142 	}
  1143 	if (vendor == 0x0001 && product == 0x0001) {
  1144 		return SDL_FALSE;
  1145 	}
  1146     return (GuessControllerType(vendor, product) == k_eControllerType_XBox360Controller);
  1147 }
  1148 
  1149 SDL_bool
  1150 SDL_IsJoystickXboxOne(Uint16 vendor, Uint16 product)
  1151 {
  1152     return (GuessControllerType(vendor, product) == k_eControllerType_XBoxOneController);
  1153 }
  1154 
  1155 static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
  1156 {
  1157     static Uint32 wheel_joysticks[] = {
  1158         MAKE_VIDPID(0x046d, 0xc294),    /* Logitech generic wheel */
  1159         MAKE_VIDPID(0x046d, 0xc295),    /* Logitech Momo Force */
  1160         MAKE_VIDPID(0x046d, 0xc298),    /* Logitech Driving Force Pro */
  1161         MAKE_VIDPID(0x046d, 0xc299),    /* Logitech G25 */
  1162         MAKE_VIDPID(0x046d, 0xc29a),    /* Logitech Driving Force GT */
  1163         MAKE_VIDPID(0x046d, 0xc29b),    /* Logitech G27 */
  1164         MAKE_VIDPID(0x046d, 0xc261),    /* Logitech G920 (initial mode) */
  1165         MAKE_VIDPID(0x046d, 0xc262),    /* Logitech G920 (active mode) */
  1166         MAKE_VIDPID(0x044f, 0xb65d),    /* Thrustmaster Wheel FFB */
  1167         MAKE_VIDPID(0x044f, 0xb66d),    /* Thrustmaster Wheel FFB */
  1168         MAKE_VIDPID(0x044f, 0xb677),    /* Thrustmaster T150 */
  1169         MAKE_VIDPID(0x044f, 0xb664),    /* Thrustmaster TX (initial mode) */
  1170         MAKE_VIDPID(0x044f, 0xb669),    /* Thrustmaster TX (active mode) */
  1171     };
  1172     int i;
  1173 
  1174     for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) {
  1175         if (vidpid == wheel_joysticks[i]) {
  1176             return SDL_TRUE;
  1177         }
  1178     }
  1179     return SDL_FALSE;
  1180 }
  1181 
  1182 static SDL_bool SDL_IsJoystickProductFlightStick(Uint32 vidpid)
  1183 {
  1184     static Uint32 flightstick_joysticks[] = {
  1185         MAKE_VIDPID(0x044f, 0x0402),    /* HOTAS Warthog Joystick */
  1186         MAKE_VIDPID(0x0738, 0x2221),    /* Saitek Pro Flight X-56 Rhino Stick */
  1187     };
  1188     int i;
  1189 
  1190     for (i = 0; i < SDL_arraysize(flightstick_joysticks); ++i) {
  1191         if (vidpid == flightstick_joysticks[i]) {
  1192             return SDL_TRUE;
  1193         }
  1194     }
  1195     return SDL_FALSE;
  1196 }
  1197 
  1198 static SDL_bool SDL_IsJoystickProductThrottle(Uint32 vidpid)
  1199 {
  1200     static Uint32 throttle_joysticks[] = {
  1201         MAKE_VIDPID(0x044f, 0x0404),    /* HOTAS Warthog Throttle */
  1202         MAKE_VIDPID(0x0738, 0xa221),    /* Saitek Pro Flight X-56 Rhino Throttle */
  1203     };
  1204     int i;
  1205 
  1206     for (i = 0; i < SDL_arraysize(throttle_joysticks); ++i) {
  1207         if (vidpid == throttle_joysticks[i]) {
  1208             return SDL_TRUE;
  1209         }
  1210     }
  1211     return SDL_FALSE;
  1212 }
  1213 
  1214 static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
  1215 {
  1216     Uint16 vendor;
  1217     Uint16 product;
  1218     Uint32 vidpid;
  1219 
  1220     if (guid.data[14] == 'x') {
  1221         /* XInput GUID, get the type based on the XInput device subtype */
  1222         switch (guid.data[15]) {
  1223         case 0x01:  /* XINPUT_DEVSUBTYPE_GAMEPAD */
  1224             return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1225         case 0x02:  /* XINPUT_DEVSUBTYPE_WHEEL */
  1226             return SDL_JOYSTICK_TYPE_WHEEL;
  1227         case 0x03:  /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
  1228             return SDL_JOYSTICK_TYPE_ARCADE_STICK;
  1229         case 0x04:  /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
  1230             return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
  1231         case 0x05:  /* XINPUT_DEVSUBTYPE_DANCE_PAD */
  1232             return SDL_JOYSTICK_TYPE_DANCE_PAD;
  1233         case 0x06:  /* XINPUT_DEVSUBTYPE_GUITAR */
  1234         case 0x07:  /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
  1235         case 0x0B:  /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
  1236             return SDL_JOYSTICK_TYPE_GUITAR;
  1237         case 0x08:  /* XINPUT_DEVSUBTYPE_DRUM_KIT */
  1238             return SDL_JOYSTICK_TYPE_DRUM_KIT;
  1239         case 0x13:  /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
  1240             return SDL_JOYSTICK_TYPE_ARCADE_PAD;
  1241         default:
  1242             return SDL_JOYSTICK_TYPE_UNKNOWN;
  1243         }
  1244     }
  1245 
  1246     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
  1247     vidpid = MAKE_VIDPID(vendor, product);
  1248 
  1249     if (SDL_IsJoystickProductWheel(vidpid)) {
  1250         return SDL_JOYSTICK_TYPE_WHEEL;
  1251     }
  1252 
  1253     if (SDL_IsJoystickProductFlightStick(vidpid)) {
  1254         return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
  1255     }
  1256 
  1257     if (SDL_IsJoystickProductThrottle(vidpid)) {
  1258         return SDL_JOYSTICK_TYPE_THROTTLE;
  1259     }
  1260 
  1261     if (GuessControllerType(vendor, product) != k_eControllerType_UnknownNonSteamController) {
  1262         return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1263     }
  1264 
  1265     return SDL_JOYSTICK_TYPE_UNKNOWN;
  1266 }
  1267 
  1268 static SDL_bool SDL_IsPS4RemapperRunning(void)
  1269 {
  1270 #ifdef __WIN32__
  1271     const char *mapper_processes[] = {
  1272         "DS4Windows.exe",
  1273         "InputMapper.exe",
  1274     };
  1275     int i;
  1276     PROCESSENTRY32 pe32;
  1277     SDL_bool found = SDL_FALSE;
  1278 
  1279     /* Take a snapshot of all processes in the system */
  1280     HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1281     if (hProcessSnap != INVALID_HANDLE_VALUE) {
  1282         pe32.dwSize = sizeof(PROCESSENTRY32);
  1283         if (Process32First(hProcessSnap, &pe32)) {
  1284             do
  1285             {
  1286                 for (i = 0; i < SDL_arraysize(mapper_processes); ++i) {
  1287                     if (SDL_strcasecmp(pe32.szExeFile, mapper_processes[i]) == 0) {
  1288                         found = SDL_TRUE;
  1289                     }
  1290                 }
  1291             } while (Process32Next(hProcessSnap, &pe32) && !found);
  1292         }
  1293         CloseHandle(hProcessSnap);
  1294     }
  1295     return found;
  1296 #else
  1297     return SDL_FALSE;
  1298 #endif
  1299 }
  1300 
  1301 SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
  1302 {
  1303     Uint16 vendor;
  1304     Uint16 product;
  1305 
  1306     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
  1307 
  1308     if (SDL_IsJoystickPS4(vendor, product) && SDL_IsPS4RemapperRunning()) {
  1309         return SDL_TRUE;
  1310     }
  1311 
  1312     if (SDL_IsGameControllerNameAndGUID(name, guid) &&
  1313         SDL_ShouldIgnoreGameController(name, guid)) {
  1314         return SDL_TRUE;
  1315     }
  1316 
  1317     return SDL_FALSE;
  1318 }
  1319 
  1320 /* return the guid for this index */
  1321 SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
  1322 {
  1323     SDL_JoystickDriver *driver;
  1324     SDL_JoystickGUID guid;
  1325 
  1326     SDL_LockJoysticks();
  1327     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
  1328         guid = driver->GetDeviceGUID(device_index);
  1329     } else {
  1330         SDL_zero(guid);
  1331     }
  1332     SDL_UnlockJoysticks();
  1333 
  1334     return guid;
  1335 }
  1336 
  1337 Uint16 SDL_JoystickGetDeviceVendor(int device_index)
  1338 {
  1339     Uint16 vendor;
  1340     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  1341 
  1342     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
  1343     return vendor;
  1344 }
  1345 
  1346 Uint16 SDL_JoystickGetDeviceProduct(int device_index)
  1347 {
  1348     Uint16 product;
  1349     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  1350 
  1351     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
  1352     return product;
  1353 }
  1354 
  1355 Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
  1356 {
  1357     Uint16 version;
  1358     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  1359 
  1360     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
  1361     return version;
  1362 }
  1363 
  1364 SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
  1365 {
  1366     SDL_JoystickType type;
  1367     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
  1368 
  1369     type = SDL_GetJoystickGUIDType(guid);
  1370     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
  1371         if (SDL_IsGameController(device_index)) {
  1372             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1373         }
  1374     }
  1375     return type;
  1376 }
  1377 
  1378 SDL_JoystickID SDL_JoystickGetDeviceInstanceID(int device_index)
  1379 {
  1380     SDL_JoystickDriver *driver;
  1381     SDL_JoystickID instance_id = -1;
  1382 
  1383     SDL_LockJoysticks();
  1384     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
  1385         instance_id = driver->GetDeviceInstanceID(device_index);
  1386     }
  1387     SDL_UnlockJoysticks();
  1388 
  1389     return instance_id;
  1390 }
  1391 
  1392 int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
  1393 {
  1394     int i, num_joysticks, device_index = -1;
  1395 
  1396     SDL_LockJoysticks();
  1397     num_joysticks = SDL_NumJoysticks();
  1398     for (i = 0; i < num_joysticks; ++i) {
  1399         if (SDL_JoystickGetDeviceInstanceID(i) == instance_id) {
  1400             device_index = i;
  1401             break;
  1402         }
  1403     }
  1404     SDL_UnlockJoysticks();
  1405 
  1406     return device_index;
  1407 }
  1408 
  1409 SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
  1410 {
  1411     if (!SDL_PrivateJoystickValid(joystick)) {
  1412         SDL_JoystickGUID emptyGUID;
  1413         SDL_zero(emptyGUID);
  1414         return emptyGUID;
  1415     }
  1416     return joystick->guid;
  1417 }
  1418 
  1419 Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick)
  1420 {
  1421     Uint16 vendor;
  1422     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  1423 
  1424     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
  1425     return vendor;
  1426 }
  1427 
  1428 Uint16 SDL_JoystickGetProduct(SDL_Joystick * joystick)
  1429 {
  1430     Uint16 product;
  1431     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  1432 
  1433     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
  1434     return product;
  1435 }
  1436 
  1437 Uint16 SDL_JoystickGetProductVersion(SDL_Joystick * joystick)
  1438 {
  1439     Uint16 version;
  1440     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  1441 
  1442     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
  1443     return version;
  1444 }
  1445 
  1446 SDL_JoystickType SDL_JoystickGetType(SDL_Joystick * joystick)
  1447 {
  1448     SDL_JoystickType type;
  1449     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  1450 
  1451     type = SDL_GetJoystickGUIDType(guid);
  1452     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
  1453         if (joystick && joystick->is_game_controller) {
  1454             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
  1455         }
  1456     }
  1457     return type;
  1458 }
  1459 
  1460 /* convert the guid to a printable string */
  1461 void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
  1462 {
  1463     static const char k_rgchHexToASCII[] = "0123456789abcdef";
  1464     int i;
  1465 
  1466     if ((pszGUID == NULL) || (cbGUID <= 0)) {
  1467         return;
  1468     }
  1469 
  1470     for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
  1471         /* each input byte writes 2 ascii chars, and might write a null byte. */
  1472         /* If we don't have room for next input byte, stop */
  1473         unsigned char c = guid.data[i];
  1474 
  1475         *pszGUID++ = k_rgchHexToASCII[c >> 4];
  1476         *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
  1477     }
  1478     *pszGUID = '\0';
  1479 }
  1480 
  1481 /*-----------------------------------------------------------------------------
  1482  * Purpose: Returns the 4 bit nibble for a hex character
  1483  * Input  : c -
  1484  * Output : unsigned char
  1485  *-----------------------------------------------------------------------------*/
  1486 static unsigned char nibble(char c)
  1487 {
  1488     if ((c >= '0') && (c <= '9')) {
  1489         return (unsigned char)(c - '0');
  1490     }
  1491 
  1492     if ((c >= 'A') && (c <= 'F')) {
  1493         return (unsigned char)(c - 'A' + 0x0a);
  1494     }
  1495 
  1496     if ((c >= 'a') && (c <= 'f')) {
  1497         return (unsigned char)(c - 'a' + 0x0a);
  1498     }
  1499 
  1500     /* received an invalid character, and no real way to return an error */
  1501     /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
  1502     return 0;
  1503 }
  1504 
  1505 /* convert the string version of a joystick guid to the struct */
  1506 SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
  1507 {
  1508     SDL_JoystickGUID guid;
  1509     int maxoutputbytes= sizeof(guid);
  1510     size_t len = SDL_strlen(pchGUID);
  1511     Uint8 *p;
  1512     size_t i;
  1513 
  1514     /* Make sure it's even */
  1515     len = (len) & ~0x1;
  1516 
  1517     SDL_memset(&guid, 0x00, sizeof(guid));
  1518 
  1519     p = (Uint8 *)&guid;
  1520     for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
  1521         *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
  1522     }
  1523 
  1524     return guid;
  1525 }
  1526 
  1527 /* update the power level for this joystick */
  1528 void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
  1529 {
  1530     joystick->epowerlevel = ePowerLevel;
  1531 }
  1532 
  1533 /* return its power level */
  1534 SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
  1535 {
  1536     if (!SDL_PrivateJoystickValid(joystick)) {
  1537         return SDL_JOYSTICK_POWER_UNKNOWN;
  1538     }
  1539     return joystick->epowerlevel;
  1540 }
  1541 
  1542 /* vi: set ts=4 sw=4 expandtab: */