src/joystick/SDL_joystick.c
author Ozkan Sezer <sezeroz@gmail.com>
Mon, 21 Oct 2019 22:22:28 +0300
changeset 13155 faed1bb24abb
parent 13135 fbae11263ac5
permissions -rw-r--r--
SDL_endian.h: Use endian.h for OpenBSD.

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