src/joystick/SDL_joystick.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 10 Aug 2018 14:42:40 -0400
changeset 12105 997ec56425a8
parent 12104 fc8ab202b5a8
child 12107 7c7cee9f2bc4
permissions -rw-r--r--
bsd: Update joystick code for new interfaces.

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