1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2021 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_hints.h"
30 
31 #if !SDL_EVENTS_DISABLED
32 #include "../events/SDL_events_c.h"
33 #endif
34 #include "../video/SDL_sysvideo.h"
35 #include "hidapi/SDL_hidapijoystick_c.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 #if SDL_JOYSTICK_VIRTUAL
49 #include "./virtual/SDL_virtualjoystick_c.h"
50 #endif
51 
52 static SDL_JoystickDriver *SDL_joystick_drivers[] = {
53 #ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
54     &SDL_HIDAPI_JoystickDriver,
55 #endif
56 #ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
57     &SDL_RAWINPUT_JoystickDriver,
58 #endif
59 #if defined(SDL_JOYSTICK_WGI)
60     &SDL_WGI_JoystickDriver,
61 #endif
62 #if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
63     &SDL_WINDOWS_JoystickDriver,
64 #endif
65 #if defined(SDL_JOYSTICK_WINMM)
66     &SDL_WINMM_JoystickDriver,
67 #endif
68 #ifdef SDL_JOYSTICK_LINUX
69     &SDL_LINUX_JoystickDriver,
70 #endif
71 #ifdef SDL_JOYSTICK_IOKIT
72     &SDL_DARWIN_JoystickDriver,
73 #endif
74 #if (defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)) && !defined(SDL_JOYSTICK_DISABLED)
75     &SDL_IOS_JoystickDriver,
76 #endif
77 #ifdef SDL_JOYSTICK_ANDROID
78     &SDL_ANDROID_JoystickDriver,
79 #endif
80 #ifdef SDL_JOYSTICK_EMSCRIPTEN
81     &SDL_EMSCRIPTEN_JoystickDriver,
82 #endif
83 #ifdef SDL_JOYSTICK_HAIKU
84     &SDL_HAIKU_JoystickDriver,
85 #endif
86 #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. */
87     &SDL_BSD_JoystickDriver,
88 #endif
89 #ifdef SDL_JOYSTICK_OS2
90     &SDL_OS2_JoystickDriver,
91 #endif
92 #ifdef SDL_JOYSTICK_PSP
93     &SDL_PSP_JoystickDriver,
94 #endif
95 #ifdef SDL_JOYSTICK_VIRTUAL
96     &SDL_VIRTUAL_JoystickDriver,
97 #endif
98 #ifdef SDL_JOYSTICK_VITA
99     &SDL_VITA_JoystickDriver,
100 #endif
101 #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
102     &SDL_DUMMY_JoystickDriver
103 #endif
104 };
105 static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
106 static SDL_Joystick *SDL_joysticks = NULL;
107 static SDL_bool SDL_updating_joystick = SDL_FALSE;
108 static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
109 static SDL_atomic_t SDL_next_joystick_instance_id;
110 static int SDL_joystick_player_count = 0;
111 static SDL_JoystickID *SDL_joystick_players = NULL;
112 
113 void
SDL_LockJoysticks(void)114 SDL_LockJoysticks(void)
115 {
116     if (SDL_joystick_lock) {
117         SDL_LockMutex(SDL_joystick_lock);
118     }
119 }
120 
121 void
SDL_UnlockJoysticks(void)122 SDL_UnlockJoysticks(void)
123 {
124     if (SDL_joystick_lock) {
125         SDL_UnlockMutex(SDL_joystick_lock);
126     }
127 }
128 
129 static int
SDL_FindFreePlayerIndex()130 SDL_FindFreePlayerIndex()
131 {
132     int player_index;
133 
134     for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
135         if (SDL_joystick_players[player_index] == -1) {
136             return player_index;
137         }
138     }
139     return player_index;
140 }
141 
142 static int
SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)143 SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)
144 {
145     int player_index;
146 
147     for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
148         if (instance_id == SDL_joystick_players[player_index]) {
149             break;
150         }
151     }
152     if (player_index == SDL_joystick_player_count) {
153         player_index = -1;
154     }
155     return player_index;
156 }
157 
158 static SDL_JoystickID
SDL_GetJoystickIDForPlayerIndex(int player_index)159 SDL_GetJoystickIDForPlayerIndex(int player_index)
160 {
161     if (player_index < 0 || player_index >= SDL_joystick_player_count) {
162         return -1;
163     }
164     return SDL_joystick_players[player_index];
165 }
166 
167 static SDL_bool
SDL_SetJoystickIDForPlayerIndex(int player_index,SDL_JoystickID instance_id)168 SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
169 {
170     SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
171     SDL_JoystickDriver *driver;
172     int device_index;
173     int existing_player_index;
174 
175     if (player_index >= SDL_joystick_player_count) {
176         SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players));
177         if (!new_players) {
178             SDL_OutOfMemory();
179             return SDL_FALSE;
180         }
181 
182         SDL_joystick_players = new_players;
183         SDL_memset(&SDL_joystick_players[SDL_joystick_player_count], 0xFF, (player_index - SDL_joystick_player_count + 1) * sizeof(SDL_joystick_players[0]));
184         SDL_joystick_player_count = player_index + 1;
185     } else if (SDL_joystick_players[player_index] == instance_id) {
186         /* Joystick is already assigned the requested player index */
187         return SDL_TRUE;
188     }
189 
190     /* Clear the old player index */
191     existing_player_index = SDL_GetPlayerIndexForJoystickID(instance_id);
192     if (existing_player_index >= 0) {
193         SDL_joystick_players[existing_player_index] = -1;
194     }
195 
196     if (player_index >= 0) {
197         SDL_joystick_players[player_index] = instance_id;
198     }
199 
200     /* Update the driver with the new index */
201     device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
202     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
203         driver->SetDevicePlayerIndex(device_index, player_index);
204     }
205 
206     /* Move any existing joystick to another slot */
207     if (existing_instance >= 0) {
208         SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance);
209     }
210     return SDL_TRUE;
211 }
212 
213 static void SDLCALL
SDL_JoystickAllowBackgroundEventsChanged(void * userdata,const char * name,const char * oldValue,const char * hint)214 SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
215 {
216     if (hint && *hint == '1') {
217         SDL_joystick_allows_background_events = SDL_TRUE;
218     } else {
219         SDL_joystick_allows_background_events = SDL_FALSE;
220     }
221 }
222 
223 int
SDL_JoystickInit(void)224 SDL_JoystickInit(void)
225 {
226     int i, status;
227 
228     SDL_GameControllerInitMappings();
229 
230     /* Create the joystick list lock */
231     if (!SDL_joystick_lock) {
232         SDL_joystick_lock = SDL_CreateMutex();
233     }
234 
235     /* See if we should allow joystick events while in the background */
236     SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
237                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
238 
239 #if !SDL_EVENTS_DISABLED
240     if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
241         return -1;
242     }
243 #endif /* !SDL_EVENTS_DISABLED */
244 
245     status = -1;
246     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
247         if (SDL_joystick_drivers[i]->Init() >= 0) {
248             status = 0;
249         }
250     }
251     return status;
252 }
253 
254 /*
255  * Count the number of joysticks attached to the system
256  */
257 int
SDL_NumJoysticks(void)258 SDL_NumJoysticks(void)
259 {
260     int i, total_joysticks = 0;
261     SDL_LockJoysticks();
262     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
263         total_joysticks += SDL_joystick_drivers[i]->GetCount();
264     }
265     SDL_UnlockJoysticks();
266     return total_joysticks;
267 }
268 
269 /*
270  * Return the next available joystick instance ID
271  * This may be called by drivers from multiple threads, unprotected by any locks
272  */
SDL_GetNextJoystickInstanceID()273 SDL_JoystickID SDL_GetNextJoystickInstanceID()
274 {
275     return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
276 }
277 
278 /*
279  * Get the driver and device index for an API device index
280  * This should be called while the joystick lock is held, to prevent another thread from updating the list
281  */
282 SDL_bool
SDL_GetDriverAndJoystickIndex(int device_index,SDL_JoystickDriver ** driver,int * driver_index)283 SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index)
284 {
285     int i, num_joysticks, total_joysticks = 0;
286 
287     if (device_index >= 0) {
288         for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
289             num_joysticks = SDL_joystick_drivers[i]->GetCount();
290             if (device_index < num_joysticks) {
291                 *driver = SDL_joystick_drivers[i];
292                 *driver_index = device_index;
293                 return SDL_TRUE;
294             }
295             device_index -= num_joysticks;
296             total_joysticks += num_joysticks;
297         }
298     }
299 
300     SDL_SetError("There are %d joysticks available", total_joysticks);
301     return SDL_FALSE;
302 }
303 
304 /*
305  * Get the implementation dependent name of a joystick
306  */
307 const char *
SDL_JoystickNameForIndex(int device_index)308 SDL_JoystickNameForIndex(int device_index)
309 {
310     SDL_JoystickDriver *driver;
311     const char *name = NULL;
312 
313     SDL_LockJoysticks();
314     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
315         name = driver->GetDeviceName(device_index);
316     }
317     SDL_UnlockJoysticks();
318 
319     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */
320     return name;
321 }
322 
323 /*
324  *  Get the player index of a joystick, or -1 if it's not available
325  */
326 int
SDL_JoystickGetDevicePlayerIndex(int device_index)327 SDL_JoystickGetDevicePlayerIndex(int device_index)
328 {
329     int player_index;
330 
331     SDL_LockJoysticks();
332     player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index));
333     SDL_UnlockJoysticks();
334 
335     return player_index;
336 }
337 
338 /*
339  * Return true if this joystick is known to have all axes centered at zero
340  * This isn't generally needed unless the joystick never generates an initial axis value near zero,
341  * e.g. it's emulating axes with digital buttons
342  */
343 static SDL_bool
SDL_JoystickAxesCenteredAtZero(SDL_Joystick * joystick)344 SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
345 {
346 #ifdef __WINRT__
347     return SDL_TRUE;
348 #else
349     static Uint32 zero_centered_joysticks[] = {
350         MAKE_VIDPID(0x0e8f, 0x3013),    /* HuiJia SNES USB adapter */
351         MAKE_VIDPID(0x05a0, 0x3232),    /* 8Bitdo Zero Gamepad */
352     };
353 
354     int i;
355     Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick),
356                             SDL_JoystickGetProduct(joystick));
357 
358     /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
359 
360     if (joystick->naxes == 2) {
361         /* Assume D-pad or thumbstick style axes are centered at 0 */
362         return SDL_TRUE;
363     }
364 
365     for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
366         if (id == zero_centered_joysticks[i]) {
367             return SDL_TRUE;
368         }
369     }
370     return SDL_FALSE;
371 #endif /* __WINRT__ */
372 }
373 
374 /*
375  * Open a joystick for use - the index passed as an argument refers to
376  * the N'th joystick on the system.  This index is the value which will
377  * identify this joystick in future joystick events.
378  *
379  * This function returns a joystick identifier, or NULL if an error occurred.
380  */
381 SDL_Joystick *
SDL_JoystickOpen(int device_index)382 SDL_JoystickOpen(int device_index)
383 {
384     SDL_JoystickDriver *driver;
385     SDL_JoystickID instance_id;
386     SDL_Joystick *joystick;
387     SDL_Joystick *joysticklist;
388     const char *joystickname = NULL;
389 
390     SDL_LockJoysticks();
391 
392     if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
393         SDL_UnlockJoysticks();
394         return NULL;
395     }
396 
397     joysticklist = SDL_joysticks;
398     /* If the joystick is already open, return it
399      * it is important that we have a single joystick * for each instance id
400      */
401     instance_id = driver->GetDeviceInstanceID(device_index);
402     while (joysticklist) {
403         if (instance_id == joysticklist->instance_id) {
404                 joystick = joysticklist;
405                 ++joystick->ref_count;
406                 SDL_UnlockJoysticks();
407                 return joystick;
408         }
409         joysticklist = joysticklist->next;
410     }
411 
412     /* Create and initialize the joystick */
413     joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
414     if (joystick == NULL) {
415         SDL_OutOfMemory();
416         SDL_UnlockJoysticks();
417         return NULL;
418     }
419     joystick->driver = driver;
420     joystick->instance_id = instance_id;
421     joystick->attached = SDL_TRUE;
422     joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
423     joystick->led_expiration = SDL_GetTicks();
424 
425     if (driver->Open(joystick, device_index) < 0) {
426         SDL_free(joystick);
427         SDL_UnlockJoysticks();
428         return NULL;
429     }
430 
431     joystickname = driver->GetDeviceName(device_index);
432     if (joystickname) {
433         joystick->name = SDL_strdup(joystickname);
434     } else {
435         joystick->name = NULL;
436     }
437 
438     joystick->guid = driver->GetDeviceGUID(device_index);
439 
440     if (joystick->naxes > 0) {
441         joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
442     }
443     if (joystick->nhats > 0) {
444         joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8));
445     }
446     if (joystick->nballs > 0) {
447         joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls));
448     }
449     if (joystick->nbuttons > 0) {
450         joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8));
451     }
452     if (((joystick->naxes > 0) && !joystick->axes)
453         || ((joystick->nhats > 0) && !joystick->hats)
454         || ((joystick->nballs > 0) && !joystick->balls)
455         || ((joystick->nbuttons > 0) && !joystick->buttons)) {
456         SDL_OutOfMemory();
457         SDL_JoystickClose(joystick);
458         SDL_UnlockJoysticks();
459         return NULL;
460     }
461 
462     /* If this joystick is known to have all zero centered axes, skip the auto-centering code */
463     if (SDL_JoystickAxesCenteredAtZero(joystick)) {
464         int i;
465 
466         for (i = 0; i < joystick->naxes; ++i) {
467             joystick->axes[i].has_initial_value = SDL_TRUE;
468         }
469     }
470 
471     joystick->is_game_controller = SDL_IsGameController(device_index);
472 
473     /* Add joystick to list */
474     ++joystick->ref_count;
475     /* Link the joystick in the list */
476     joystick->next = SDL_joysticks;
477     SDL_joysticks = joystick;
478 
479     SDL_UnlockJoysticks();
480 
481     driver->Update(joystick);
482 
483     return joystick;
484 }
485 
486 int
SDL_JoystickAttachVirtual(SDL_JoystickType type,int naxes,int nbuttons,int nhats)487 SDL_JoystickAttachVirtual(SDL_JoystickType type,
488                           int naxes, int nbuttons, int nhats)
489 {
490 #if SDL_JOYSTICK_VIRTUAL
491     return SDL_JoystickAttachVirtualInner(type, naxes, nbuttons, nhats);
492 #else
493     return SDL_SetError("SDL not built with virtual-joystick support");
494 #endif
495 }
496 
497 int
SDL_JoystickDetachVirtual(int device_index)498 SDL_JoystickDetachVirtual(int device_index)
499 {
500 #if SDL_JOYSTICK_VIRTUAL
501     SDL_JoystickDriver *driver;
502 
503     SDL_LockJoysticks();
504     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
505         if (driver == &SDL_VIRTUAL_JoystickDriver) {
506             const int result = SDL_JoystickDetachVirtualInner(device_index);
507             SDL_UnlockJoysticks();
508             return result;
509         }
510     }
511     SDL_UnlockJoysticks();
512 
513     return SDL_SetError("Virtual joystick not found at provided index");
514 #else
515     return SDL_SetError("SDL not built with virtual-joystick support");
516 #endif
517 }
518 
519 SDL_bool
SDL_JoystickIsVirtual(int device_index)520 SDL_JoystickIsVirtual(int device_index)
521 {
522 #if SDL_JOYSTICK_VIRTUAL
523     SDL_JoystickDriver *driver;
524     int driver_device_index;
525     SDL_bool is_virtual = SDL_FALSE;
526 
527     SDL_LockJoysticks();
528     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
529         if (driver == &SDL_VIRTUAL_JoystickDriver) {
530             is_virtual = SDL_TRUE;
531         }
532     }
533     SDL_UnlockJoysticks();
534 
535     return is_virtual;
536 #else
537     return SDL_FALSE;
538 #endif
539 }
540 
541 int
SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick,int axis,Sint16 value)542 SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value)
543 {
544 #if SDL_JOYSTICK_VIRTUAL
545     return SDL_JoystickSetVirtualAxisInner(joystick, axis, value);
546 #else
547     return SDL_SetError("SDL not built with virtual-joystick support");
548 #endif
549 }
550 
551 int
SDL_JoystickSetVirtualButton(SDL_Joystick * joystick,int button,Uint8 value)552 SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value)
553 {
554 #if SDL_JOYSTICK_VIRTUAL
555     return SDL_JoystickSetVirtualButtonInner(joystick, button, value);
556 #else
557     return SDL_SetError("SDL not built with virtual-joystick support");
558 #endif
559 }
560 
561 int
SDL_JoystickSetVirtualHat(SDL_Joystick * joystick,int hat,Uint8 value)562 SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value)
563 {
564 #if SDL_JOYSTICK_VIRTUAL
565     return SDL_JoystickSetVirtualHatInner(joystick, hat, value);
566 #else
567     return SDL_SetError("SDL not built with virtual-joystick support");
568 #endif
569 }
570 
571 /*
572  * Checks to make sure the joystick is valid.
573  */
574 SDL_bool
SDL_PrivateJoystickValid(SDL_Joystick * joystick)575 SDL_PrivateJoystickValid(SDL_Joystick *joystick)
576 {
577     SDL_bool valid;
578 
579     if (joystick == NULL) {
580         SDL_SetError("Joystick hasn't been opened yet");
581         valid = SDL_FALSE;
582     } else {
583         valid = SDL_TRUE;
584     }
585 
586     return valid;
587 }
588 
589 SDL_bool
SDL_PrivateJoystickGetAutoGamepadMapping(int device_index,SDL_GamepadMapping * out)590 SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping * out)
591 {
592     SDL_JoystickDriver *driver;
593     SDL_bool is_ok = SDL_FALSE;
594 
595     SDL_LockJoysticks();
596     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
597         is_ok = driver->GetGamepadMapping(device_index, out);
598     }
599     SDL_UnlockJoysticks();
600 
601     return is_ok;
602 }
603 
604 /*
605  * Get the number of multi-dimensional axis controls on a joystick
606  */
607 int
SDL_JoystickNumAxes(SDL_Joystick * joystick)608 SDL_JoystickNumAxes(SDL_Joystick *joystick)
609 {
610     if (!SDL_PrivateJoystickValid(joystick)) {
611         return -1;
612     }
613     return joystick->naxes;
614 }
615 
616 /*
617  * Get the number of hats on a joystick
618  */
619 int
SDL_JoystickNumHats(SDL_Joystick * joystick)620 SDL_JoystickNumHats(SDL_Joystick *joystick)
621 {
622     if (!SDL_PrivateJoystickValid(joystick)) {
623         return -1;
624     }
625     return joystick->nhats;
626 }
627 
628 /*
629  * Get the number of trackballs on a joystick
630  */
631 int
SDL_JoystickNumBalls(SDL_Joystick * joystick)632 SDL_JoystickNumBalls(SDL_Joystick *joystick)
633 {
634     if (!SDL_PrivateJoystickValid(joystick)) {
635         return -1;
636     }
637     return joystick->nballs;
638 }
639 
640 /*
641  * Get the number of buttons on a joystick
642  */
643 int
SDL_JoystickNumButtons(SDL_Joystick * joystick)644 SDL_JoystickNumButtons(SDL_Joystick *joystick)
645 {
646     if (!SDL_PrivateJoystickValid(joystick)) {
647         return -1;
648     }
649     return joystick->nbuttons;
650 }
651 
652 /*
653  * Get the current state of an axis control on a joystick
654  */
655 Sint16
SDL_JoystickGetAxis(SDL_Joystick * joystick,int axis)656 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis)
657 {
658     Sint16 state;
659 
660     if (!SDL_PrivateJoystickValid(joystick)) {
661         return 0;
662     }
663     if (axis < joystick->naxes) {
664         state = joystick->axes[axis].value;
665     } else {
666         SDL_SetError("Joystick only has %d axes", joystick->naxes);
667         state = 0;
668     }
669     return state;
670 }
671 
672 /*
673  * Get the initial state of an axis control on a joystick
674  */
675 SDL_bool
SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick,int axis,Sint16 * state)676 SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state)
677 {
678     if (!SDL_PrivateJoystickValid(joystick)) {
679         return SDL_FALSE;
680     }
681     if (axis >= joystick->naxes) {
682         SDL_SetError("Joystick only has %d axes", joystick->naxes);
683         return SDL_FALSE;
684     }
685     if (state) {
686         *state = joystick->axes[axis].initial_value;
687     }
688     return joystick->axes[axis].has_initial_value;
689 }
690 
691 /*
692  * Get the current state of a hat on a joystick
693  */
694 Uint8
SDL_JoystickGetHat(SDL_Joystick * joystick,int hat)695 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat)
696 {
697     Uint8 state;
698 
699     if (!SDL_PrivateJoystickValid(joystick)) {
700         return 0;
701     }
702     if (hat < joystick->nhats) {
703         state = joystick->hats[hat];
704     } else {
705         SDL_SetError("Joystick only has %d hats", joystick->nhats);
706         state = 0;
707     }
708     return state;
709 }
710 
711 /*
712  * Get the ball axis change since the last poll
713  */
714 int
SDL_JoystickGetBall(SDL_Joystick * joystick,int ball,int * dx,int * dy)715 SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy)
716 {
717     int retval;
718 
719     if (!SDL_PrivateJoystickValid(joystick)) {
720         return -1;
721     }
722 
723     retval = 0;
724     if (ball < joystick->nballs) {
725         if (dx) {
726             *dx = joystick->balls[ball].dx;
727         }
728         if (dy) {
729             *dy = joystick->balls[ball].dy;
730         }
731         joystick->balls[ball].dx = 0;
732         joystick->balls[ball].dy = 0;
733     } else {
734         return SDL_SetError("Joystick only has %d balls", joystick->nballs);
735     }
736     return retval;
737 }
738 
739 /*
740  * Get the current state of a button on a joystick
741  */
742 Uint8
SDL_JoystickGetButton(SDL_Joystick * joystick,int button)743 SDL_JoystickGetButton(SDL_Joystick *joystick, int button)
744 {
745     Uint8 state;
746 
747     if (!SDL_PrivateJoystickValid(joystick)) {
748         return 0;
749     }
750     if (button < joystick->nbuttons) {
751         state = joystick->buttons[button];
752     } else {
753         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
754         state = 0;
755     }
756     return state;
757 }
758 
759 /*
760  * Return if the joystick in question is currently attached to the system,
761  *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
762  */
763 SDL_bool
SDL_JoystickGetAttached(SDL_Joystick * joystick)764 SDL_JoystickGetAttached(SDL_Joystick *joystick)
765 {
766     if (!joystick) {
767         return SDL_FALSE;
768     }
769 
770     return joystick->attached;
771 }
772 
773 /*
774  * Get the instance id for this opened joystick
775  */
776 SDL_JoystickID
SDL_JoystickInstanceID(SDL_Joystick * joystick)777 SDL_JoystickInstanceID(SDL_Joystick *joystick)
778 {
779     if (!SDL_PrivateJoystickValid(joystick)) {
780         return -1;
781     }
782 
783     return joystick->instance_id;
784 }
785 
786 /*
787  * Return the SDL_Joystick associated with an instance id.
788  */
789 SDL_Joystick *
SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)790 SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)
791 {
792     SDL_Joystick *joystick;
793 
794     SDL_LockJoysticks();
795     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
796         if (joystick->instance_id == instance_id) {
797             break;
798         }
799     }
800     SDL_UnlockJoysticks();
801     return joystick;
802 }
803 
804 /**
805  * Return the SDL_Joystick associated with a player index.
806  */
807 SDL_Joystick *
SDL_JoystickFromPlayerIndex(int player_index)808 SDL_JoystickFromPlayerIndex(int player_index)
809 {
810     SDL_JoystickID instance_id;
811     SDL_Joystick *joystick;
812 
813     SDL_LockJoysticks();
814     instance_id = SDL_GetJoystickIDForPlayerIndex(player_index);
815     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
816         if (joystick->instance_id == instance_id) {
817             break;
818         }
819     }
820     SDL_UnlockJoysticks();
821     return joystick;
822 }
823 
824 /*
825  * Get the friendly name of this joystick
826  */
827 const char *
SDL_JoystickName(SDL_Joystick * joystick)828 SDL_JoystickName(SDL_Joystick *joystick)
829 {
830     if (!SDL_PrivateJoystickValid(joystick)) {
831         return NULL;
832     }
833 
834     return joystick->name;
835 }
836 
837 /**
838  *  Get the player index of an opened joystick, or -1 if it's not available
839  */
840 int
SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)841 SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick)
842 {
843     int player_index;
844 
845     if (!SDL_PrivateJoystickValid(joystick)) {
846         return -1;
847     }
848 
849     SDL_LockJoysticks();
850     player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id);
851     SDL_UnlockJoysticks();
852 
853     return player_index;
854 }
855 
856 /**
857  *  Set the player index of an opened joystick
858  */
859 void
SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick,int player_index)860 SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index)
861 {
862     if (!SDL_PrivateJoystickValid(joystick)) {
863         return;
864     }
865 
866     SDL_LockJoysticks();
867     SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id);
868     SDL_UnlockJoysticks();
869 }
870 
871 int
SDL_JoystickRumble(SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble,Uint32 duration_ms)872 SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
873 {
874     int result;
875 
876     if (!SDL_PrivateJoystickValid(joystick)) {
877         return -1;
878     }
879 
880     SDL_LockJoysticks();
881     if (low_frequency_rumble == joystick->low_frequency_rumble &&
882         high_frequency_rumble == joystick->high_frequency_rumble) {
883         /* Just update the expiration */
884         result = 0;
885     } else {
886         result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
887     }
888 
889     /* Save the rumble value regardless of success, so we don't spam the driver */
890     joystick->low_frequency_rumble = low_frequency_rumble;
891     joystick->high_frequency_rumble = high_frequency_rumble;
892 
893     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
894         joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
895         if (!joystick->rumble_expiration) {
896             joystick->rumble_expiration = 1;
897         }
898     } else {
899         joystick->rumble_expiration = 0;
900     }
901     SDL_UnlockJoysticks();
902 
903     return result;
904 }
905 
906 int
SDL_JoystickRumbleTriggers(SDL_Joystick * joystick,Uint16 left_rumble,Uint16 right_rumble,Uint32 duration_ms)907 SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms)
908 {
909     int result;
910 
911     if (!SDL_PrivateJoystickValid(joystick)) {
912         return -1;
913     }
914 
915     SDL_LockJoysticks();
916     if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) {
917         /* Just update the expiration */
918         result = 0;
919     } else {
920         result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
921     }
922 
923     /* Save the rumble value regardless of success, so we don't spam the driver */
924     joystick->left_trigger_rumble = left_rumble;
925     joystick->right_trigger_rumble = right_rumble;
926 
927     if ((left_rumble || right_rumble) && duration_ms) {
928         joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
929         if (!joystick->trigger_rumble_expiration) {
930             joystick->trigger_rumble_expiration = 1;
931         }
932     } else {
933         joystick->trigger_rumble_expiration = 0;
934     }
935     SDL_UnlockJoysticks();
936 
937     return result;
938 }
939 
940 SDL_bool
SDL_JoystickHasLED(SDL_Joystick * joystick)941 SDL_JoystickHasLED(SDL_Joystick *joystick)
942 {
943     SDL_bool result;
944 
945     if (!SDL_PrivateJoystickValid(joystick)) {
946         return SDL_FALSE;
947     }
948 
949     SDL_LockJoysticks();
950 
951     result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0;
952 
953     SDL_UnlockJoysticks();
954 
955     return result;
956 }
957 
958 SDL_bool
SDL_JoystickHasRumble(SDL_Joystick * joystick)959 SDL_JoystickHasRumble(SDL_Joystick *joystick)
960 {
961     SDL_bool result;
962 
963     if (!SDL_PrivateJoystickValid(joystick)) {
964         return SDL_FALSE;
965     }
966 
967     SDL_LockJoysticks();
968 
969     result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0;
970 
971     SDL_UnlockJoysticks();
972 
973     return result;
974 }
975 
976 SDL_bool
SDL_JoystickHasRumbleTriggers(SDL_Joystick * joystick)977 SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick)
978 {
979     SDL_bool result;
980 
981     if (!SDL_PrivateJoystickValid(joystick)) {
982         return SDL_FALSE;
983     }
984 
985     SDL_LockJoysticks();
986 
987     result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0;
988 
989     SDL_UnlockJoysticks();
990 
991     return result;
992 }
993 
994 int
SDL_JoystickSetLED(SDL_Joystick * joystick,Uint8 red,Uint8 green,Uint8 blue)995 SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
996 {
997     int result;
998     SDL_bool isfreshvalue;
999 
1000     if (!SDL_PrivateJoystickValid(joystick)) {
1001         return -1;
1002     }
1003 
1004     SDL_LockJoysticks();
1005 
1006     isfreshvalue = red != joystick->led_red ||
1007         green != joystick->led_green ||
1008         blue != joystick->led_blue;
1009 
1010     if ( isfreshvalue || SDL_TICKS_PASSED( SDL_GetTicks(), joystick->led_expiration ) ) {
1011         result = joystick->driver->SetLED(joystick, red, green, blue);
1012         joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS;
1013     }
1014     else {
1015         /* Avoid spamming the driver */
1016         result = 0;
1017     }
1018 
1019     /* Save the LED value regardless of success, so we don't spam the driver */
1020     joystick->led_red = red;
1021     joystick->led_green = green;
1022     joystick->led_blue = blue;
1023 
1024     SDL_UnlockJoysticks();
1025 
1026     return result;
1027 }
1028 
1029 int
SDL_JoystickSendEffect(SDL_Joystick * joystick,const void * data,int size)1030 SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
1031 {
1032     int result;
1033 
1034     if (!SDL_PrivateJoystickValid(joystick)) {
1035         return -1;
1036     }
1037 
1038     SDL_LockJoysticks();
1039 
1040     result = joystick->driver->SendEffect(joystick, data, size);
1041 
1042     SDL_UnlockJoysticks();
1043 
1044     return result;
1045 }
1046 
1047 /*
1048  * Close a joystick previously opened with SDL_JoystickOpen()
1049  */
1050 void
SDL_JoystickClose(SDL_Joystick * joystick)1051 SDL_JoystickClose(SDL_Joystick *joystick)
1052 {
1053     SDL_Joystick *joysticklist;
1054     SDL_Joystick *joysticklistprev;
1055     int i;
1056 
1057     if (!SDL_PrivateJoystickValid(joystick)) {
1058         return;
1059     }
1060 
1061     SDL_LockJoysticks();
1062 
1063     /* First decrement ref count */
1064     if (--joystick->ref_count > 0) {
1065         SDL_UnlockJoysticks();
1066         return;
1067     }
1068 
1069     if (SDL_updating_joystick) {
1070         SDL_UnlockJoysticks();
1071         return;
1072     }
1073 
1074     if (joystick->rumble_expiration) {
1075         SDL_JoystickRumble(joystick, 0, 0, 0);
1076     }
1077     if (joystick->trigger_rumble_expiration) {
1078         SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
1079     }
1080 
1081     joystick->driver->Close(joystick);
1082     joystick->hwdata = NULL;
1083 
1084     joysticklist = SDL_joysticks;
1085     joysticklistprev = NULL;
1086     while (joysticklist) {
1087         if (joystick == joysticklist) {
1088             if (joysticklistprev) {
1089                 /* unlink this entry */
1090                 joysticklistprev->next = joysticklist->next;
1091             } else {
1092                 SDL_joysticks = joystick->next;
1093             }
1094             break;
1095         }
1096         joysticklistprev = joysticklist;
1097         joysticklist = joysticklist->next;
1098     }
1099 
1100     SDL_free(joystick->name);
1101     SDL_free(joystick->serial);
1102 
1103     /* Free the data associated with this joystick */
1104     SDL_free(joystick->axes);
1105     SDL_free(joystick->hats);
1106     SDL_free(joystick->balls);
1107     SDL_free(joystick->buttons);
1108     for (i = 0; i < joystick->ntouchpads; i++) {
1109         SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i];
1110         SDL_free(touchpad->fingers);
1111     }
1112     SDL_free(joystick->touchpads);
1113     SDL_free(joystick->sensors);
1114     SDL_free(joystick);
1115 
1116     SDL_UnlockJoysticks();
1117 }
1118 
1119 void
SDL_JoystickQuit(void)1120 SDL_JoystickQuit(void)
1121 {
1122     int i;
1123 
1124     /* Make sure we're not getting called in the middle of updating joysticks */
1125     SDL_LockJoysticks();
1126     while (SDL_updating_joystick) {
1127         SDL_UnlockJoysticks();
1128         SDL_Delay(1);
1129         SDL_LockJoysticks();
1130     }
1131 
1132     /* Stop the event polling */
1133     while (SDL_joysticks) {
1134         SDL_joysticks->ref_count = 1;
1135         SDL_JoystickClose(SDL_joysticks);
1136     }
1137 
1138     /* Quit drivers in reverse order to avoid breaking dependencies between drivers */
1139     for (i = SDL_arraysize(SDL_joystick_drivers) - 1; i >= 0; --i) {
1140        SDL_joystick_drivers[i]->Quit();
1141     }
1142 
1143     if (SDL_joystick_players) {
1144         SDL_free(SDL_joystick_players);
1145         SDL_joystick_players = NULL;
1146         SDL_joystick_player_count = 0;
1147     }
1148     SDL_UnlockJoysticks();
1149 
1150 #if !SDL_EVENTS_DISABLED
1151     SDL_QuitSubSystem(SDL_INIT_EVENTS);
1152 #endif
1153 
1154     SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
1155                         SDL_JoystickAllowBackgroundEventsChanged, NULL);
1156 
1157     if (SDL_joystick_lock) {
1158         SDL_mutex *mutex = SDL_joystick_lock;
1159         SDL_joystick_lock = NULL;
1160         SDL_DestroyMutex(mutex);
1161     }
1162 
1163     SDL_GameControllerQuitMappings();
1164 }
1165 
1166 
1167 static SDL_bool
SDL_PrivateJoystickShouldIgnoreEvent()1168 SDL_PrivateJoystickShouldIgnoreEvent()
1169 {
1170     if (SDL_joystick_allows_background_events) {
1171         return SDL_FALSE;
1172     }
1173 
1174     if (SDL_HasWindows() && SDL_GetKeyboardFocus() == NULL) {
1175         /* We have windows but we don't have focus, ignore the event. */
1176         return SDL_TRUE;
1177     }
1178     return SDL_FALSE;
1179 }
1180 
1181 /* These are global for SDL_sysjoystick.c and SDL_events.c */
1182 
SDL_PrivateJoystickAddTouchpad(SDL_Joystick * joystick,int nfingers)1183 void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
1184 {
1185     int ntouchpads = joystick->ntouchpads + 1;
1186     SDL_JoystickTouchpadInfo *touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo)));
1187     if (touchpads) {
1188         SDL_JoystickTouchpadInfo *touchpad = &touchpads[ntouchpads - 1];
1189         SDL_JoystickTouchpadFingerInfo *fingers = (SDL_JoystickTouchpadFingerInfo *)SDL_calloc(nfingers, sizeof(SDL_JoystickTouchpadFingerInfo));
1190 
1191         if (fingers) {
1192             touchpad->nfingers = nfingers;
1193             touchpad->fingers = fingers;
1194         } else {
1195             /* Out of memory, this touchpad won't be active */
1196             touchpad->nfingers = 0;
1197             touchpad->fingers = NULL;
1198         }
1199 
1200         joystick->ntouchpads = ntouchpads;
1201         joystick->touchpads = touchpads;
1202     }
1203 }
1204 
SDL_PrivateJoystickAddSensor(SDL_Joystick * joystick,SDL_SensorType type,float rate)1205 void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, float rate)
1206 {
1207     int nsensors = joystick->nsensors + 1;
1208     SDL_JoystickSensorInfo *sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo)));
1209     if (sensors) {
1210         SDL_JoystickSensorInfo *sensor = &sensors[nsensors - 1];
1211 
1212         SDL_zerop(sensor);
1213         sensor->type = type;
1214         sensor->rate = rate;
1215 
1216         joystick->nsensors = nsensors;
1217         joystick->sensors = sensors;
1218     }
1219 }
1220 
SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)1221 void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
1222 {
1223     SDL_JoystickDriver *driver;
1224     int driver_device_index;
1225     int player_index = -1;
1226     int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
1227     if (device_index < 0) {
1228         return;
1229     }
1230 
1231     SDL_LockJoysticks();
1232     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
1233         player_index = driver->GetDevicePlayerIndex(driver_device_index);
1234     }
1235     if (player_index < 0 && SDL_IsGameController(device_index)) {
1236         player_index = SDL_FindFreePlayerIndex();
1237     }
1238     if (player_index >= 0) {
1239         SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
1240     }
1241     SDL_UnlockJoysticks();
1242 
1243 #if !SDL_EVENTS_DISABLED
1244     {
1245         SDL_Event event;
1246 
1247         event.type = SDL_JOYDEVICEADDED;
1248 
1249         if (SDL_GetEventState(event.type) == SDL_ENABLE) {
1250             event.jdevice.which = device_index;
1251             SDL_PushEvent(&event);
1252         }
1253     }
1254 #endif /* !SDL_EVENTS_DISABLED */
1255 }
1256 
1257 /*
1258  * If there is an existing add event in the queue, it needs to be modified
1259  * to have the right value for which, because the number of controllers in
1260  * the system is now one less.
1261  */
UpdateEventsForDeviceRemoval(int device_index)1262 static void UpdateEventsForDeviceRemoval(int device_index)
1263 {
1264     int i, num_events;
1265     SDL_Event *events;
1266     SDL_bool isstack;
1267 
1268     num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
1269     if (num_events <= 0) {
1270         return;
1271     }
1272 
1273     events = SDL_small_alloc(SDL_Event, num_events, &isstack);
1274     if (!events) {
1275         return;
1276     }
1277 
1278     num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
1279     for (i = 0; i < num_events; ++i) {
1280         if (events[i].cdevice.which < device_index) {
1281             /* No change for index values lower than the removed device */
1282         }
1283         else if (events[i].cdevice.which == device_index) {
1284             /* Drop this event entirely */
1285             SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
1286             --num_events;
1287             --i;
1288         }
1289         else {
1290             /* Fix up the device index if greater than the removed device */
1291             --events[i].cdevice.which;
1292         }
1293     }
1294     SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
1295 
1296     SDL_small_free(events, isstack);
1297 }
1298 
1299 static void
SDL_PrivateJoystickForceRecentering(SDL_Joystick * joystick)1300 SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
1301 {
1302     int i, j;
1303 
1304     /* Tell the app that everything is centered/unpressed... */
1305     for (i = 0; i < joystick->naxes; i++) {
1306         if (joystick->axes[i].has_initial_value) {
1307             SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
1308         }
1309     }
1310 
1311     for (i = 0; i < joystick->nbuttons; i++) {
1312         SDL_PrivateJoystickButton(joystick, i, SDL_RELEASED);
1313     }
1314 
1315     for (i = 0; i < joystick->nhats; i++) {
1316         SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
1317     }
1318 
1319     for (i = 0; i < joystick->ntouchpads; i++) {
1320         SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i];
1321 
1322         for (j = 0; j < touchpad->nfingers; ++j) {
1323             SDL_PrivateJoystickTouchpad(joystick, i, j, SDL_RELEASED, 0.0f, 0.0f, 0.0f);
1324         }
1325     }
1326 }
1327 
SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)1328 void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
1329 {
1330     SDL_Joystick *joystick = NULL;
1331     int player_index;
1332     int device_index;
1333 #if !SDL_EVENTS_DISABLED
1334     SDL_Event event;
1335 #endif
1336 
1337     /* Find this joystick... */
1338     device_index = 0;
1339     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
1340         if (joystick->instance_id == device_instance) {
1341             SDL_PrivateJoystickForceRecentering(joystick);
1342             joystick->attached = SDL_FALSE;
1343             break;
1344         }
1345 
1346         ++device_index;
1347     }
1348 
1349 #if !SDL_EVENTS_DISABLED
1350     SDL_zero(event);
1351     event.type = SDL_JOYDEVICEREMOVED;
1352 
1353     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
1354         event.jdevice.which = device_instance;
1355         SDL_PushEvent(&event);
1356     }
1357 
1358     UpdateEventsForDeviceRemoval(device_index);
1359 #endif /* !SDL_EVENTS_DISABLED */
1360 
1361     SDL_LockJoysticks();
1362     player_index = SDL_GetPlayerIndexForJoystickID(device_instance);
1363     if (player_index >= 0) {
1364         SDL_joystick_players[player_index] = -1;
1365     }
1366     SDL_UnlockJoysticks();
1367 }
1368 
1369 int
SDL_PrivateJoystickAxis(SDL_Joystick * joystick,Uint8 axis,Sint16 value)1370 SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
1371 {
1372     int posted;
1373     SDL_JoystickAxisInfo *info;
1374 
1375     /* Make sure we're not getting garbage or duplicate events */
1376     if (axis >= joystick->naxes) {
1377         return 0;
1378     }
1379 
1380     info = &joystick->axes[axis];
1381     if (!info->has_initial_value ||
1382         (!info->has_second_value && (info->initial_value <= -32767 || info->initial_value == 32767) && SDL_abs(value) < (SDL_JOYSTICK_AXIS_MAX / 4))) {
1383         info->initial_value = value;
1384         info->value = value;
1385         info->zero = value;
1386         info->has_initial_value = SDL_TRUE;
1387     } else if (value == info->value && !info->sending_initial_value) {
1388         return 0;
1389     } else {
1390         info->has_second_value = SDL_TRUE;
1391     }
1392     if (!info->sent_initial_value) {
1393         /* Make sure we don't send motion until there's real activity on this axis */
1394         const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
1395         if (SDL_abs(value - info->value) <= MAX_ALLOWED_JITTER) {
1396             return 0;
1397         }
1398         info->sent_initial_value = SDL_TRUE;
1399         info->sending_initial_value = SDL_TRUE;
1400         SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
1401         info->sending_initial_value = SDL_FALSE;
1402     }
1403 
1404     /* We ignore events if we don't have keyboard focus, except for centering
1405      * events.
1406      */
1407     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
1408         if (info->sending_initial_value ||
1409             (value > info->zero && value >= info->value) ||
1410             (value < info->zero && value <= info->value)) {
1411             return 0;
1412         }
1413     }
1414 
1415     /* Update internal joystick state */
1416     info->value = value;
1417 
1418     /* Post the event, if desired */
1419     posted = 0;
1420 #if !SDL_EVENTS_DISABLED
1421     if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
1422         SDL_Event event;
1423         event.type = SDL_JOYAXISMOTION;
1424         event.jaxis.which = joystick->instance_id;
1425         event.jaxis.axis = axis;
1426         event.jaxis.value = value;
1427         posted = SDL_PushEvent(&event) == 1;
1428     }
1429 #endif /* !SDL_EVENTS_DISABLED */
1430     return posted;
1431 }
1432 
1433 int
SDL_PrivateJoystickHat(SDL_Joystick * joystick,Uint8 hat,Uint8 value)1434 SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
1435 {
1436     int posted;
1437 
1438     /* Make sure we're not getting garbage or duplicate events */
1439     if (hat >= joystick->nhats) {
1440         return 0;
1441     }
1442     if (value == joystick->hats[hat]) {
1443         return 0;
1444     }
1445 
1446     /* We ignore events if we don't have keyboard focus, except for centering
1447      * events.
1448      */
1449     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
1450         if (value != SDL_HAT_CENTERED) {
1451             return 0;
1452         }
1453     }
1454 
1455     /* Update internal joystick state */
1456     joystick->hats[hat] = value;
1457 
1458     /* Post the event, if desired */
1459     posted = 0;
1460 #if !SDL_EVENTS_DISABLED
1461     if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
1462         SDL_Event event;
1463         event.jhat.type = SDL_JOYHATMOTION;
1464         event.jhat.which = joystick->instance_id;
1465         event.jhat.hat = hat;
1466         event.jhat.value = value;
1467         posted = SDL_PushEvent(&event) == 1;
1468     }
1469 #endif /* !SDL_EVENTS_DISABLED */
1470     return posted;
1471 }
1472 
1473 int
SDL_PrivateJoystickBall(SDL_Joystick * joystick,Uint8 ball,Sint16 xrel,Sint16 yrel)1474 SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball,
1475                         Sint16 xrel, Sint16 yrel)
1476 {
1477     int posted;
1478 
1479     /* Make sure we're not getting garbage events */
1480     if (ball >= joystick->nballs) {
1481         return 0;
1482     }
1483 
1484     /* We ignore events if we don't have keyboard focus. */
1485     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
1486         return 0;
1487     }
1488 
1489     /* Update internal mouse state */
1490     joystick->balls[ball].dx += xrel;
1491     joystick->balls[ball].dy += yrel;
1492 
1493     /* Post the event, if desired */
1494     posted = 0;
1495 #if !SDL_EVENTS_DISABLED
1496     if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
1497         SDL_Event event;
1498         event.jball.type = SDL_JOYBALLMOTION;
1499         event.jball.which = joystick->instance_id;
1500         event.jball.ball = ball;
1501         event.jball.xrel = xrel;
1502         event.jball.yrel = yrel;
1503         posted = SDL_PushEvent(&event) == 1;
1504     }
1505 #endif /* !SDL_EVENTS_DISABLED */
1506     return posted;
1507 }
1508 
1509 int
SDL_PrivateJoystickButton(SDL_Joystick * joystick,Uint8 button,Uint8 state)1510 SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
1511 {
1512     int posted;
1513 #if !SDL_EVENTS_DISABLED
1514     SDL_Event event;
1515 
1516     switch (state) {
1517     case SDL_PRESSED:
1518         event.type = SDL_JOYBUTTONDOWN;
1519         break;
1520     case SDL_RELEASED:
1521         event.type = SDL_JOYBUTTONUP;
1522         break;
1523     default:
1524         /* Invalid state -- bail */
1525         return 0;
1526     }
1527 #endif /* !SDL_EVENTS_DISABLED */
1528 
1529     /* Make sure we're not getting garbage or duplicate events */
1530     if (button >= joystick->nbuttons) {
1531         return 0;
1532     }
1533     if (state == joystick->buttons[button]) {
1534         return 0;
1535     }
1536 
1537     /* We ignore events if we don't have keyboard focus, except for button
1538      * release. */
1539     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
1540         if (state == SDL_PRESSED) {
1541             return 0;
1542         }
1543     }
1544 
1545     /* Update internal joystick state */
1546     joystick->buttons[button] = state;
1547 
1548     /* Post the event, if desired */
1549     posted = 0;
1550 #if !SDL_EVENTS_DISABLED
1551     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
1552         event.jbutton.which = joystick->instance_id;
1553         event.jbutton.button = button;
1554         event.jbutton.state = state;
1555         posted = SDL_PushEvent(&event) == 1;
1556     }
1557 #endif /* !SDL_EVENTS_DISABLED */
1558     return posted;
1559 }
1560 
1561 void
SDL_JoystickUpdate(void)1562 SDL_JoystickUpdate(void)
1563 {
1564     int i;
1565     SDL_Joystick *joystick, *next;
1566 
1567     if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
1568         return;
1569     }
1570 
1571     SDL_LockJoysticks();
1572 
1573     if (SDL_updating_joystick) {
1574         /* The joysticks are already being updated */
1575         SDL_UnlockJoysticks();
1576         return;
1577     }
1578 
1579     SDL_updating_joystick = SDL_TRUE;
1580 
1581     /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
1582     SDL_UnlockJoysticks();
1583 
1584 #ifdef SDL_JOYSTICK_HIDAPI
1585     /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
1586     HIDAPI_UpdateDevices();
1587 #endif /* SDL_JOYSTICK_HIDAPI */
1588 
1589     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
1590         if (joystick->attached) {
1591             /* This should always be true, but seeing a crash in the wild...? */
1592             if (joystick->driver) {
1593                 joystick->driver->Update(joystick);
1594             }
1595 
1596             if (joystick->delayed_guide_button) {
1597                 SDL_GameControllerHandleDelayedGuideButton(joystick);
1598             }
1599         }
1600 
1601         if (joystick->rumble_expiration) {
1602             SDL_LockJoysticks();
1603             /* Double check now that the lock is held */
1604             if (joystick->rumble_expiration &&
1605                 SDL_TICKS_PASSED(SDL_GetTicks(), joystick->rumble_expiration)) {
1606                 SDL_JoystickRumble(joystick, 0, 0, 0);
1607             }
1608             SDL_UnlockJoysticks();
1609         }
1610 
1611         if (joystick->trigger_rumble_expiration) {
1612             SDL_LockJoysticks();
1613             /* Double check now that the lock is held */
1614             if (joystick->trigger_rumble_expiration &&
1615                 SDL_TICKS_PASSED(SDL_GetTicks(), joystick->trigger_rumble_expiration)) {
1616                 SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
1617             }
1618             SDL_UnlockJoysticks();
1619         }
1620     }
1621 
1622     SDL_LockJoysticks();
1623 
1624     SDL_updating_joystick = SDL_FALSE;
1625 
1626     /* If any joysticks were closed while updating, free them here */
1627     for (joystick = SDL_joysticks; joystick; joystick = next) {
1628         next = joystick->next;
1629         if (joystick->ref_count <= 0) {
1630             SDL_JoystickClose(joystick);
1631         }
1632     }
1633 
1634     /* this needs to happen AFTER walking the joystick list above, so that any
1635        dangling hardware data from removed devices can be free'd
1636      */
1637     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
1638         SDL_joystick_drivers[i]->Detect();
1639     }
1640 
1641     SDL_UnlockJoysticks();
1642 }
1643 
1644 int
SDL_JoystickEventState(int state)1645 SDL_JoystickEventState(int state)
1646 {
1647 #if SDL_EVENTS_DISABLED
1648     return SDL_DISABLE;
1649 #else
1650     const Uint32 event_list[] = {
1651         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
1652         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
1653     };
1654     unsigned int i;
1655 
1656     switch (state) {
1657     case SDL_QUERY:
1658         state = SDL_DISABLE;
1659         for (i = 0; i < SDL_arraysize(event_list); ++i) {
1660             state = SDL_EventState(event_list[i], SDL_QUERY);
1661             if (state == SDL_ENABLE) {
1662                 break;
1663             }
1664         }
1665         break;
1666     default:
1667         for (i = 0; i < SDL_arraysize(event_list); ++i) {
1668             SDL_EventState(event_list[i], state);
1669         }
1670         break;
1671     }
1672     return state;
1673 #endif /* SDL_EVENTS_DISABLED */
1674 }
1675 
SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid,Uint16 * vendor,Uint16 * product,Uint16 * version)1676 void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
1677 {
1678     Uint16 *guid16 = (Uint16 *)guid.data;
1679 
1680     /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
1681     if (/* guid16[0] is device bus type */
1682         guid16[1] == 0x0000 &&
1683         /* guid16[2] is vendor ID */
1684         guid16[3] == 0x0000 &&
1685         /* guid16[4] is product ID */
1686         guid16[5] == 0x0000
1687         /* guid16[6] is product version */
1688    ) {
1689         if (vendor) {
1690             *vendor = guid16[2];
1691         }
1692         if (product) {
1693             *product = guid16[4];
1694         }
1695         if (version) {
1696             *version = guid16[6];
1697         }
1698     } else {
1699         if (vendor) {
1700             *vendor = 0;
1701         }
1702         if (product) {
1703             *product = 0;
1704         }
1705         if (version) {
1706             *version = 0;
1707         }
1708     }
1709 }
1710 
1711 static int
PrefixMatch(const char * a,const char * b)1712 PrefixMatch(const char *a, const char *b)
1713 {
1714     int matchlen = 0;
1715     while (*a && *b) {
1716         if (SDL_tolower(*a++) == SDL_tolower(*b++)) {
1717             ++matchlen;
1718         } else {
1719             break;
1720         }
1721     }
1722     return matchlen;
1723 }
1724 
1725 char *
SDL_CreateJoystickName(Uint16 vendor,Uint16 product,const char * vendor_name,const char * product_name)1726 SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name)
1727 {
1728     static struct {
1729         const char *prefix;
1730         const char *replacement;
1731     } replacements[] = {
1732         { "NVIDIA Corporation ", "" },
1733         { "Performance Designed Products", "PDP" },
1734         { "HORI CO.,LTD.", "HORI" },
1735         { "HORI CO.,LTD", "HORI" },
1736         { "Unknown ", "" },
1737     };
1738     const char *custom_name;
1739     char *name;
1740     size_t i, len;
1741 
1742     custom_name = GuessControllerName(vendor, product);
1743     if (custom_name) {
1744         return SDL_strdup(custom_name);
1745     }
1746 
1747     if (!vendor_name) {
1748         vendor_name = "";
1749     }
1750     if (!product_name) {
1751         product_name = "";
1752     }
1753 
1754     while (*vendor_name == ' ') {
1755         ++vendor_name;
1756     }
1757     while (*product_name == ' ') {
1758         ++product_name;
1759     }
1760 
1761     if (*vendor_name && *product_name) {
1762         len = (SDL_strlen(vendor_name) + 1 + SDL_strlen(product_name) + 1);
1763         name = (char *)SDL_malloc(len);
1764         if (!name) {
1765             return NULL;
1766         }
1767         SDL_snprintf(name, len, "%s %s", vendor_name, product_name);
1768     } else if (*product_name) {
1769         name = SDL_strdup(product_name);
1770     } else if (vendor || product) {
1771         len = (6 + 1 + 6 + 1);
1772         name = (char *)SDL_malloc(len);
1773         if (!name) {
1774             return NULL;
1775         }
1776         SDL_snprintf(name, len, "0x%.4x/0x%.4x", vendor, product);
1777     } else {
1778         name = SDL_strdup("Controller");
1779     }
1780 
1781     /* Trim trailing whitespace */
1782     for (len = SDL_strlen(name); (len > 0 && name[len - 1] == ' '); --len) {
1783         /* continue */
1784     }
1785     name[len] = '\0';
1786 
1787     /* Compress duplicate spaces */
1788     for (i = 0; i < (len - 1); ) {
1789         if (name[i] == ' ' && name[i+1] == ' ') {
1790             SDL_memmove(&name[i], &name[i+1], (len - i));
1791             --len;
1792         } else {
1793             ++i;
1794         }
1795     }
1796 
1797     /* Perform any manufacturer replacements */
1798     for (i = 0; i < SDL_arraysize(replacements); ++i) {
1799         size_t prefixlen = SDL_strlen(replacements[i].prefix);
1800         if (SDL_strncasecmp(name, replacements[i].prefix, prefixlen) == 0) {
1801             size_t replacementlen = SDL_strlen(replacements[i].replacement);
1802             if (replacementlen <= prefixlen) {
1803                 SDL_memcpy(name, replacements[i].replacement, replacementlen);
1804                 SDL_memmove(name+replacementlen, name+prefixlen, (len-prefixlen)+1);
1805                 len -= (prefixlen - replacementlen);
1806             } else {
1807                 /* FIXME: Need to handle the expand case by reallocating the string */
1808             }
1809             break;
1810         }
1811     }
1812 
1813     /* Remove duplicate manufacturer or product in the name */
1814     for (i = 1; i < (len - 1); ++i) {
1815         int matchlen = PrefixMatch(name, &name[i]);
1816         if (matchlen > 0 && name[matchlen-1] == ' ') {
1817             SDL_memmove(name, name+matchlen, len-matchlen+1);
1818             break;
1819         } else if (matchlen > 0 && name[matchlen] == ' ') {
1820             SDL_memmove(name, name+matchlen+1, len-matchlen);
1821             break;
1822         }
1823     }
1824 
1825     return name;
1826 }
1827 
1828 SDL_GameControllerType
SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor,Uint16 product)1829 SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product)
1830 {
1831     return SDL_GetJoystickGameControllerType(NULL, vendor, product, -1, 0, 0, 0);
1832 }
1833 
1834 SDL_GameControllerType
SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid,const char * name)1835 SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name)
1836 {
1837     SDL_GameControllerType type;
1838     Uint16 vendor, product;
1839 
1840     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
1841     type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
1842     if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
1843         if (SDL_IsJoystickXInput(guid)) {
1844             /* This is probably an Xbox One controller */
1845             return SDL_CONTROLLER_TYPE_XBOXONE;
1846         }
1847     }
1848     return type;
1849 }
1850 
1851 SDL_GameControllerType
SDL_GetJoystickGameControllerType(const char * name,Uint16 vendor,Uint16 product,int interface_number,int interface_class,int interface_subclass,int interface_protocol)1852 SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
1853 {
1854     static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
1855     static const int XB360_IFACE_SUBCLASS = 93;
1856     static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
1857     static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
1858     static const int XBONE_IFACE_SUBCLASS = 71;
1859     static const int XBONE_IFACE_PROTOCOL = 208;
1860 
1861     SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
1862 
1863     /* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
1864     if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
1865         interface_subclass == XB360_IFACE_SUBCLASS &&
1866         (interface_protocol == XB360_IFACE_PROTOCOL ||
1867          interface_protocol == XB360W_IFACE_PROTOCOL)) {
1868 
1869         static const int SUPPORTED_VENDORS[] = {
1870             0x0079, /* GPD Win 2 */
1871             0x044f, /* Thrustmaster */
1872             0x045e, /* Microsoft */
1873             0x046d, /* Logitech */
1874             0x056e, /* Elecom */
1875             0x06a3, /* Saitek */
1876             0x0738, /* Mad Catz */
1877             0x07ff, /* Mad Catz */
1878             0x0e6f, /* PDP */
1879             0x0f0d, /* Hori */
1880             0x1038, /* SteelSeries */
1881             0x11c9, /* Nacon */
1882             0x12ab, /* Unknown */
1883             0x1430, /* RedOctane */
1884             0x146b, /* BigBen */
1885             0x1532, /* Razer Sabertooth */
1886             0x15e4, /* Numark */
1887             0x162e, /* Joytech */
1888             0x1689, /* Razer Onza */
1889             0x1949, /* Lab126, Inc. */
1890             0x1bad, /* Harmonix */
1891             0x20d6, /* PowerA */
1892             0x24c6, /* PowerA */
1893         };
1894 
1895         int i;
1896         for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
1897             if (vendor == SUPPORTED_VENDORS[i]) {
1898                 type = SDL_CONTROLLER_TYPE_XBOX360;
1899                 break;
1900             }
1901         }
1902     }
1903 
1904     if (interface_number == 0 &&
1905         interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
1906         interface_subclass == XBONE_IFACE_SUBCLASS &&
1907         interface_protocol == XBONE_IFACE_PROTOCOL) {
1908 
1909         static const int SUPPORTED_VENDORS[] = {
1910             0x045e, /* Microsoft */
1911             0x0738, /* Mad Catz */
1912             0x0e6f, /* PDP */
1913             0x0f0d, /* Hori */
1914             0x1532, /* Razer Wildcat */
1915             0x20d6, /* PowerA */
1916             0x24c6, /* PowerA */
1917             0x2e24, /* Hyperkin */
1918         };
1919 
1920         int i;
1921         for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
1922             if (vendor == SUPPORTED_VENDORS[i]) {
1923                 type = SDL_CONTROLLER_TYPE_XBOXONE;
1924                 break;
1925             }
1926         }
1927     }
1928 
1929     if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
1930         if (vendor == 0x0000 && product == 0x0000) {
1931             /* Some devices are only identifiable by their name */
1932             if (name &&
1933                 (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
1934                  SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
1935                  SDL_strcmp(name, "Wireless Gamepad") == 0)) {
1936                 /* HORI or PowerA Switch Pro Controller clone */
1937                 type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
1938             } else if (name && SDL_strcmp(name, "Virtual Joystick") == 0) {
1939                 type = SDL_CONTROLLER_TYPE_VIRTUAL;
1940             } else {
1941                 type = SDL_CONTROLLER_TYPE_UNKNOWN;
1942             }
1943 
1944         } else if (vendor == 0x0001 && product == 0x0001) {
1945             type = SDL_CONTROLLER_TYPE_UNKNOWN;
1946 
1947         } else if ((vendor == USB_VENDOR_AMAZON && product == USB_PRODUCT_AMAZON_LUNA_CONTROLLER) ||
1948                    (vendor == BLUETOOTH_VENDOR_AMAZON && product == BLUETOOTH_PRODUCT_LUNA_CONTROLLER)) {
1949             type = SDL_CONTROLLER_TYPE_AMAZON_LUNA;
1950 
1951         } else if (vendor == USB_VENDOR_GOOGLE && product == USB_PRODUCT_GOOGLE_STADIA_CONTROLLER) {
1952             type = SDL_CONTROLLER_TYPE_GOOGLE_STADIA;
1953 
1954         } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
1955                 type = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, SDL_FALSE) ? SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO : SDL_CONTROLLER_TYPE_UNKNOWN;
1956 
1957         } else {
1958             switch (GuessControllerType(vendor, product)) {
1959             case k_eControllerType_XBox360Controller:
1960                 type = SDL_CONTROLLER_TYPE_XBOX360;
1961                 break;
1962             case k_eControllerType_XBoxOneController:
1963                 type = SDL_CONTROLLER_TYPE_XBOXONE;
1964                 break;
1965             case k_eControllerType_PS3Controller:
1966                 type = SDL_CONTROLLER_TYPE_PS3;
1967                 break;
1968             case k_eControllerType_PS4Controller:
1969                 type = SDL_CONTROLLER_TYPE_PS4;
1970                 break;
1971             case k_eControllerType_PS5Controller:
1972                 type = SDL_CONTROLLER_TYPE_PS5;
1973                 break;
1974             case k_eControllerType_SwitchProController:
1975             case k_eControllerType_SwitchInputOnlyController:
1976                 type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
1977                 break;
1978             case k_eControllerType_SwitchJoyConLeft:
1979             case k_eControllerType_SwitchJoyConRight:
1980                 type = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, SDL_FALSE) ? SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO : SDL_CONTROLLER_TYPE_UNKNOWN;
1981                 break;
1982             default:
1983                 type = SDL_CONTROLLER_TYPE_UNKNOWN;
1984                 break;
1985             }
1986         }
1987     }
1988     return type;
1989 }
1990 
1991 SDL_bool
SDL_IsJoystickXboxOneElite(Uint16 vendor_id,Uint16 product_id)1992 SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
1993 {
1994     if (vendor_id == USB_VENDOR_MICROSOFT) {
1995         if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
1996             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 ||
1997             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
1998             return SDL_TRUE;
1999         }
2000     }
2001     return SDL_FALSE;
2002 }
2003 
2004 SDL_bool
SDL_IsJoystickXboxSeriesX(Uint16 vendor_id,Uint16 product_id)2005 SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
2006 {
2007     if (vendor_id == USB_VENDOR_MICROSOFT) {
2008         if (product_id == USB_PRODUCT_XBOX_SERIES_X ||
2009             product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
2010             return SDL_TRUE;
2011         }
2012     }
2013     if (vendor_id == USB_VENDOR_PDP) {
2014         if (product_id == USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT ||
2015             product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE ||
2016             product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW) {
2017             return SDL_TRUE;
2018         }
2019     }
2020     if (vendor_id == USB_VENDOR_POWERA_ALT) {
2021         if ((product_id >= 0x2001 && product_id <= 0x201a) ||
2022             product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 ||
2023             product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA) {
2024             return SDL_TRUE;
2025         }
2026     }
2027     return SDL_FALSE;
2028 }
2029 
2030 SDL_bool
SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id,Uint16 product_id)2031 SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id)
2032 {
2033     if (vendor_id == USB_VENDOR_MICROSOFT) {
2034         if (product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH ||
2035             product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE ||
2036             product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
2037             product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
2038             product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLE ||
2039             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
2040             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLE ||
2041             product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
2042             return SDL_TRUE;
2043         }
2044     }
2045     return SDL_FALSE;
2046 }
2047 
2048 SDL_bool
SDL_IsJoystickPS4(Uint16 vendor_id,Uint16 product_id)2049 SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id)
2050 {
2051     EControllerType eType = GuessControllerType(vendor_id, product_id);
2052     return (eType == k_eControllerType_PS4Controller);
2053 }
2054 
2055 SDL_bool
SDL_IsJoystickPS5(Uint16 vendor_id,Uint16 product_id)2056 SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id)
2057 {
2058     EControllerType eType = GuessControllerType(vendor_id, product_id);
2059     return (eType == k_eControllerType_PS5Controller);
2060 }
2061 
2062 SDL_bool
SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id,Uint16 product_id)2063 SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id)
2064 {
2065     EControllerType eType = GuessControllerType(vendor_id, product_id);
2066     return (eType == k_eControllerType_SwitchProController ||
2067             eType == k_eControllerType_SwitchInputOnlyController ||
2068             (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP));
2069 }
2070 
2071 SDL_bool
SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id,Uint16 product_id)2072 SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id)
2073 {
2074     EControllerType eType = GuessControllerType(vendor_id, product_id);
2075     return (eType == k_eControllerType_SwitchInputOnlyController);
2076 }
2077 
2078 SDL_bool
SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id,Uint16 product_id)2079 SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id, Uint16 product_id)
2080 {
2081     EControllerType eType = GuessControllerType(vendor_id, product_id);
2082     return (eType == k_eControllerType_SwitchJoyConLeft ||
2083             eType == k_eControllerType_SwitchJoyConRight);
2084 }
2085 
2086 SDL_bool
SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id,Uint16 product_id)2087 SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id, Uint16 product_id)
2088 {
2089     EControllerType eType = GuessControllerType(vendor_id, product_id);
2090     return (eType == k_eControllerType_SwitchJoyConLeft);
2091 }
2092 
2093 SDL_bool
SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id,Uint16 product_id)2094 SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id)
2095 {
2096     EControllerType eType = GuessControllerType(vendor_id, product_id);
2097     return (eType == k_eControllerType_SwitchJoyConRight);
2098 }
2099 
2100 SDL_bool
SDL_IsJoystickSteamController(Uint16 vendor_id,Uint16 product_id)2101 SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id)
2102 {
2103     EControllerType eType = GuessControllerType(vendor_id, product_id);
2104     return (eType == k_eControllerType_SteamController ||
2105             eType == k_eControllerType_SteamControllerV2);
2106 }
2107 
2108 SDL_bool
SDL_IsJoystickXInput(SDL_JoystickGUID guid)2109 SDL_IsJoystickXInput(SDL_JoystickGUID guid)
2110 {
2111     return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
2112 }
2113 
2114 SDL_bool
SDL_IsJoystickWGI(SDL_JoystickGUID guid)2115 SDL_IsJoystickWGI(SDL_JoystickGUID guid)
2116 {
2117     return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE;
2118 }
2119 
2120 SDL_bool
SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)2121 SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
2122 {
2123     return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
2124 }
2125 
2126 SDL_bool
SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid)2127 SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid)
2128 {
2129     return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE;
2130 }
2131 
2132 SDL_bool
SDL_IsJoystickVirtual(SDL_JoystickGUID guid)2133 SDL_IsJoystickVirtual(SDL_JoystickGUID guid)
2134 {
2135     return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE;
2136 }
2137 
SDL_IsJoystickProductWheel(Uint32 vidpid)2138 static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
2139 {
2140     static Uint32 wheel_joysticks[] = {
2141         MAKE_VIDPID(0x046d, 0xc294),    /* Logitech generic wheel */
2142         MAKE_VIDPID(0x046d, 0xc295),    /* Logitech Momo Force */
2143         MAKE_VIDPID(0x046d, 0xc298),    /* Logitech Driving Force Pro */
2144         MAKE_VIDPID(0x046d, 0xc299),    /* Logitech G25 */
2145         MAKE_VIDPID(0x046d, 0xc29a),    /* Logitech Driving Force GT */
2146         MAKE_VIDPID(0x046d, 0xc29b),    /* Logitech G27 */
2147         MAKE_VIDPID(0x046d, 0xc24f),    /* Logitech G29 (PS3) */
2148         MAKE_VIDPID(0x046d, 0xc260),    /* Logitech G29 (PS4) */
2149         MAKE_VIDPID(0x046d, 0xc261),    /* Logitech G920 (initial mode) */
2150         MAKE_VIDPID(0x046d, 0xc262),    /* Logitech G920 (active mode) */
2151         MAKE_VIDPID(0x046d, 0xc26e),    /* Logitech G923 */
2152         MAKE_VIDPID(0x044f, 0xb65d),    /* Thrustmaster Wheel FFB */
2153         MAKE_VIDPID(0x044f, 0xb66d),    /* Thrustmaster Wheel FFB */
2154         MAKE_VIDPID(0x044f, 0xb677),    /* Thrustmaster T150 */
2155         MAKE_VIDPID(0x044f, 0xb66e),    /* Thrustmaster T300RS */
2156         MAKE_VIDPID(0x044f, 0xb65e),    /* Thrustmaster T500RS */
2157         MAKE_VIDPID(0x044f, 0xb664),    /* Thrustmaster TX (initial mode) */
2158         MAKE_VIDPID(0x044f, 0xb669),    /* Thrustmaster TX (active mode) */
2159     };
2160     int i;
2161 
2162     for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) {
2163         if (vidpid == wheel_joysticks[i]) {
2164             return SDL_TRUE;
2165         }
2166     }
2167     return SDL_FALSE;
2168 }
2169 
SDL_IsJoystickProductArcadeStick(Uint32 vidpid)2170 static SDL_bool SDL_IsJoystickProductArcadeStick(Uint32 vidpid)
2171 {
2172     static Uint32 arcadestick_joysticks[] = {
2173         MAKE_VIDPID(0x0079, 0x181a),    /* Venom Arcade Stick */
2174         MAKE_VIDPID(0x0f0d, 0x006a),    /* Real Arcade Pro 4 */
2175         MAKE_VIDPID(0x0079, 0x181b),    /* Venom Arcade Stick */
2176         MAKE_VIDPID(0x0c12, 0x0ef6),    /* Hitbox Arcade Stick */
2177         MAKE_VIDPID(0x0f0d, 0x008a),    /* HORI Real Arcade Pro 4 */
2178         MAKE_VIDPID(0x0f0d, 0x0016),    /* Hori Real Arcade Pro.EX */
2179         MAKE_VIDPID(0x0f0d, 0x001b),    /* Hori Real Arcade Pro VX */
2180         MAKE_VIDPID(0x0f0d, 0x008c),    /* Hori Real Arcade Pro 4 */
2181         MAKE_VIDPID(0x1bad, 0xf03d),    /* Street Fighter IV Arcade Stick TE - Chun Li */
2182         MAKE_VIDPID(0x1bad, 0xf502),    /* Hori Real Arcade Pro.VX SA */
2183         MAKE_VIDPID(0x1bad, 0xf504),    /* Hori Real Arcade Pro. EX */
2184         MAKE_VIDPID(0x1bad, 0xf506),    /* Hori Real Arcade Pro.EX Premium VLX */
2185         MAKE_VIDPID(0x24c6, 0x5000),    /* Razer Atrox Arcade Stick */
2186         MAKE_VIDPID(0x24c6, 0x5501),    /* Hori Real Arcade Pro VX-SA */
2187         MAKE_VIDPID(0x24c6, 0x550e),    /* Hori Real Arcade Pro V Kai 360 */
2188         MAKE_VIDPID(0x0f0d, 0x0063),    /* Hori Real Arcade Pro Hayabusa (USA) Xbox One */
2189         MAKE_VIDPID(0x0f0d, 0x0078),    /* Hori Real Arcade Pro V Kai Xbox One */
2190         MAKE_VIDPID(0x1532, 0x0a00),    /* Razer Atrox Arcade Stick */
2191         MAKE_VIDPID(0x0f0d, 0x00aa),    /* HORI Real Arcade Pro V Hayabusa in Switch Mode */
2192         MAKE_VIDPID(0x20d6, 0xa715),    /* PowerA Nintendo Switch Fusion Arcade Stick */
2193     };
2194     int i;
2195 
2196     for (i = 0; i < SDL_arraysize(arcadestick_joysticks); ++i) {
2197         if (vidpid == arcadestick_joysticks[i]) {
2198             return SDL_TRUE;
2199         }
2200     }
2201     return SDL_FALSE;
2202 }
2203 
SDL_IsJoystickProductFlightStick(Uint32 vidpid)2204 static SDL_bool SDL_IsJoystickProductFlightStick(Uint32 vidpid)
2205 {
2206     static Uint32 flightstick_joysticks[] = {
2207         MAKE_VIDPID(0x044f, 0x0402),    /* HOTAS Warthog Joystick */
2208         MAKE_VIDPID(0x0738, 0x2221),    /* Saitek Pro Flight X-56 Rhino Stick */
2209         MAKE_VIDPID(0x044f, 0xb10a),    /* ThrustMaster, Inc. T.16000M Joystick */
2210     };
2211     int i;
2212 
2213     for (i = 0; i < SDL_arraysize(flightstick_joysticks); ++i) {
2214         if (vidpid == flightstick_joysticks[i]) {
2215             return SDL_TRUE;
2216         }
2217     }
2218     return SDL_FALSE;
2219 }
2220 
SDL_IsJoystickProductThrottle(Uint32 vidpid)2221 static SDL_bool SDL_IsJoystickProductThrottle(Uint32 vidpid)
2222 {
2223     static Uint32 throttle_joysticks[] = {
2224         MAKE_VIDPID(0x044f, 0x0404),    /* HOTAS Warthog Throttle */
2225         MAKE_VIDPID(0x0738, 0xa221),    /* Saitek Pro Flight X-56 Rhino Throttle */
2226     };
2227     int i;
2228 
2229     for (i = 0; i < SDL_arraysize(throttle_joysticks); ++i) {
2230         if (vidpid == throttle_joysticks[i]) {
2231             return SDL_TRUE;
2232         }
2233     }
2234     return SDL_FALSE;
2235 }
2236 
SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)2237 static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
2238 {
2239     Uint16 vendor;
2240     Uint16 product;
2241     Uint32 vidpid;
2242 
2243     if (SDL_IsJoystickXInput(guid)) {
2244         /* XInput GUID, get the type based on the XInput device subtype */
2245         switch (guid.data[15]) {
2246         case 0x01:  /* XINPUT_DEVSUBTYPE_GAMEPAD */
2247             return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
2248         case 0x02:  /* XINPUT_DEVSUBTYPE_WHEEL */
2249             return SDL_JOYSTICK_TYPE_WHEEL;
2250         case 0x03:  /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
2251             return SDL_JOYSTICK_TYPE_ARCADE_STICK;
2252         case 0x04:  /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
2253             return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
2254         case 0x05:  /* XINPUT_DEVSUBTYPE_DANCE_PAD */
2255             return SDL_JOYSTICK_TYPE_DANCE_PAD;
2256         case 0x06:  /* XINPUT_DEVSUBTYPE_GUITAR */
2257         case 0x07:  /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
2258         case 0x0B:  /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
2259             return SDL_JOYSTICK_TYPE_GUITAR;
2260         case 0x08:  /* XINPUT_DEVSUBTYPE_DRUM_KIT */
2261             return SDL_JOYSTICK_TYPE_DRUM_KIT;
2262         case 0x13:  /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
2263             return SDL_JOYSTICK_TYPE_ARCADE_PAD;
2264         default:
2265             return SDL_JOYSTICK_TYPE_UNKNOWN;
2266         }
2267     }
2268 
2269     if (SDL_IsJoystickWGI(guid)) {
2270         return (SDL_JoystickType)guid.data[15];
2271     }
2272 
2273     if (SDL_IsJoystickVirtual(guid)) {
2274         return (SDL_JoystickType)guid.data[15];
2275     }
2276 
2277     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
2278     vidpid = MAKE_VIDPID(vendor, product);
2279 
2280     if (SDL_IsJoystickProductWheel(vidpid)) {
2281         return SDL_JOYSTICK_TYPE_WHEEL;
2282     }
2283 
2284     if (SDL_IsJoystickProductArcadeStick(vidpid)) {
2285         return SDL_JOYSTICK_TYPE_ARCADE_STICK;
2286     }
2287 
2288     if (SDL_IsJoystickProductFlightStick(vidpid)) {
2289         return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
2290     }
2291 
2292     if (SDL_IsJoystickProductThrottle(vidpid)) {
2293         return SDL_JOYSTICK_TYPE_THROTTLE;
2294     }
2295 
2296     if (GuessControllerType(vendor, product) != k_eControllerType_UnknownNonSteamController) {
2297         return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
2298     }
2299 
2300     return SDL_JOYSTICK_TYPE_UNKNOWN;
2301 }
2302 
SDL_IsPS4RemapperRunning(void)2303 static SDL_bool SDL_IsPS4RemapperRunning(void)
2304 {
2305 #ifdef __WIN32__
2306     const char *mapper_processes[] = {
2307         "DS4Windows.exe",
2308         "InputMapper.exe",
2309     };
2310     int i;
2311     PROCESSENTRY32 pe32;
2312     SDL_bool found = SDL_FALSE;
2313 
2314     /* Take a snapshot of all processes in the system */
2315     HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
2316     if (hProcessSnap != INVALID_HANDLE_VALUE) {
2317         pe32.dwSize = sizeof(PROCESSENTRY32);
2318         if (Process32First(hProcessSnap, &pe32)) {
2319             do
2320             {
2321                 for (i = 0; i < SDL_arraysize(mapper_processes); ++i) {
2322                     if (SDL_strcasecmp(pe32.szExeFile, mapper_processes[i]) == 0) {
2323                         found = SDL_TRUE;
2324                     }
2325                 }
2326             } while (Process32Next(hProcessSnap, &pe32) && !found);
2327         }
2328         CloseHandle(hProcessSnap);
2329     }
2330     return found;
2331 #else
2332     return SDL_FALSE;
2333 #endif
2334 }
2335 
SDL_ShouldIgnoreJoystick(const char * name,SDL_JoystickGUID guid)2336 SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
2337 {
2338     /* This list is taken from:
2339        https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
2340      */
2341     static Uint32 joystick_blacklist[] = {
2342         /* Microsoft Microsoft Wireless Optical Desktop 2.10 */
2343         /* Microsoft Wireless Desktop - Comfort Edition */
2344         MAKE_VIDPID(0x045e, 0x009d),
2345 
2346         /* Microsoft Microsoft Digital Media Pro Keyboard */
2347         /* Microsoft Corp. Digital Media Pro Keyboard */
2348         MAKE_VIDPID(0x045e, 0x00b0),
2349 
2350         /* Microsoft Microsoft Digital Media Keyboard */
2351         /* Microsoft Corp. Digital Media Keyboard 1.0A */
2352         MAKE_VIDPID(0x045e, 0x00b4),
2353 
2354         /* Microsoft Microsoft Digital Media Keyboard 3000 */
2355         MAKE_VIDPID(0x045e, 0x0730),
2356 
2357         /* Microsoft Microsoft 2.4GHz Transceiver v6.0 */
2358         /* Microsoft Microsoft 2.4GHz Transceiver v8.0 */
2359         /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
2360         /* Microsoft Wireless Mobile Mouse 1000 */
2361         /* Microsoft Wireless Desktop 3000 */
2362         MAKE_VIDPID(0x045e, 0x0745),
2363 
2364         /* Microsoft SideWinder(TM) 2.4GHz Transceiver */
2365         MAKE_VIDPID(0x045e, 0x0748),
2366 
2367         /* Microsoft Corp. Wired Keyboard 600 */
2368         MAKE_VIDPID(0x045e, 0x0750),
2369 
2370         /* Microsoft Corp. Sidewinder X4 keyboard */
2371         MAKE_VIDPID(0x045e, 0x0768),
2372 
2373         /* Microsoft Corp. Arc Touch Mouse Transceiver */
2374         MAKE_VIDPID(0x045e, 0x0773),
2375 
2376         /* Microsoft 2.4GHz Transceiver v9.0 */
2377         /* Microsoft Nano Transceiver v2.1 */
2378         /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
2379         MAKE_VIDPID(0x045e, 0x07a5),
2380 
2381         /* Microsoft Nano Transceiver v1.0 */
2382         /* Microsoft Wireless Keyboard 800 */
2383         MAKE_VIDPID(0x045e, 0x07b2),
2384 
2385         /* Microsoft Nano Transceiver v2.0 */
2386         MAKE_VIDPID(0x045e, 0x0800),
2387 
2388         MAKE_VIDPID(0x046d, 0xc30a),  /* Logitech, Inc. iTouch Composite keboard */
2389 
2390         MAKE_VIDPID(0x04d9, 0xa0df),  /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */
2391 
2392         /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */
2393         MAKE_VIDPID(0x056a, 0x0010),  /* Wacom ET-0405 Graphire */
2394         MAKE_VIDPID(0x056a, 0x0011),  /* Wacom ET-0405A Graphire2 (4x5) */
2395         MAKE_VIDPID(0x056a, 0x0012),  /* Wacom ET-0507A Graphire2 (5x7) */
2396         MAKE_VIDPID(0x056a, 0x0013),  /* Wacom CTE-430 Graphire3 (4x5) */
2397         MAKE_VIDPID(0x056a, 0x0014),  /* Wacom CTE-630 Graphire3 (6x8) */
2398         MAKE_VIDPID(0x056a, 0x0015),  /* Wacom CTE-440 Graphire4 (4x5) */
2399         MAKE_VIDPID(0x056a, 0x0016),  /* Wacom CTE-640 Graphire4 (6x8) */
2400         MAKE_VIDPID(0x056a, 0x0017),  /* Wacom CTE-450 Bamboo Fun (4x5) */
2401         MAKE_VIDPID(0x056a, 0x0018),  /* Wacom CTE-650 Bamboo Fun 6x8 */
2402         MAKE_VIDPID(0x056a, 0x0019),  /* Wacom CTE-631 Bamboo One */
2403         MAKE_VIDPID(0x056a, 0x00d1),  /* Wacom Bamboo Pen and Touch CTH-460 */
2404         MAKE_VIDPID(0x056a, 0x030e),  /* Wacom Intuos Pen (S) CTL-480 */
2405 
2406         MAKE_VIDPID(0x09da, 0x054f),  /* A4 Tech Co., G7 750 mouse */
2407         MAKE_VIDPID(0x09da, 0x1410),  /* A4 Tech Co., Ltd Bloody AL9 mouse */
2408         MAKE_VIDPID(0x09da, 0x3043),  /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */
2409         MAKE_VIDPID(0x09da, 0x31b5),  /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */
2410         MAKE_VIDPID(0x09da, 0x3997),  /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */
2411         MAKE_VIDPID(0x09da, 0x3f8b),  /* A4 Tech Co., Ltd Bloody V8 mouse */
2412         MAKE_VIDPID(0x09da, 0x51f4),  /* Modecom MC-5006 Keyboard */
2413         MAKE_VIDPID(0x09da, 0x5589),  /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */
2414         MAKE_VIDPID(0x09da, 0x7b22),  /* A4 Tech Co., Ltd Bloody V5 */
2415         MAKE_VIDPID(0x09da, 0x7f2d),  /* A4 Tech Co., Ltd Bloody R3 mouse */
2416         MAKE_VIDPID(0x09da, 0x8090),  /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */
2417         MAKE_VIDPID(0x09da, 0x9033),  /* A4 Tech Co., X7 X-705K */
2418         MAKE_VIDPID(0x09da, 0x9066),  /* A4 Tech Co., Sharkoon Fireglider Optical */
2419         MAKE_VIDPID(0x09da, 0x9090),  /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */
2420         MAKE_VIDPID(0x09da, 0x90c0),  /* A4 Tech Co., Ltd X7 G800V keyboard */
2421         MAKE_VIDPID(0x09da, 0xf012),  /* A4 Tech Co., Ltd Bloody V7 mouse */
2422         MAKE_VIDPID(0x09da, 0xf32a),  /* A4 Tech Co., Ltd Bloody B540 keyboard */
2423         MAKE_VIDPID(0x09da, 0xf613),  /* A4 Tech Co., Ltd Bloody V2 mouse */
2424         MAKE_VIDPID(0x09da, 0xf624),  /* A4 Tech Co., Ltd Bloody B120 Keyboard */
2425 
2426         MAKE_VIDPID(0x1b1c, 0x1b3c),  /* Corsair Harpoon RGB gaming mouse */
2427 
2428         MAKE_VIDPID(0x1d57, 0xad03),  /* [T3] 2.4GHz and IR Air Mouse Remote Control */
2429 
2430         MAKE_VIDPID(0x1e7d, 0x2e4a),  /* Roccat Tyon Mouse */
2431 
2432         MAKE_VIDPID(0x20a0, 0x422d),  /* Winkeyless.kr Keyboards */
2433 
2434         MAKE_VIDPID(0x2516, 0x001f),  /* Cooler Master Storm Mizar Mouse */
2435         MAKE_VIDPID(0x2516, 0x0028),  /* Cooler Master Storm Alcor Mouse */
2436 
2437         /*****************************************************************/
2438         /* Additional entries                                            */
2439         /*****************************************************************/
2440 
2441         MAKE_VIDPID(0x04d9, 0x8009),  /* OBINLB USB-HID Keyboard */
2442         MAKE_VIDPID(0x0b05, 0x1958),  /* ROG Chakram Mouse */
2443         MAKE_VIDPID(0x26ce, 0x01a2),  /* ASRock LED Controller */
2444     };
2445 
2446     unsigned int i;
2447     Uint32 id;
2448     Uint16 vendor;
2449     Uint16 product;
2450     SDL_GameControllerType type;
2451 
2452     SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
2453 
2454     /* Check the joystick blacklist */
2455     id = MAKE_VIDPID(vendor, product);
2456     for (i = 0; i < SDL_arraysize(joystick_blacklist); ++i) {
2457         if (id == joystick_blacklist[i]) {
2458             return SDL_TRUE;
2459         }
2460     }
2461 
2462     type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
2463     if ((type == SDL_CONTROLLER_TYPE_PS4 || type == SDL_CONTROLLER_TYPE_PS5) && SDL_IsPS4RemapperRunning()) {
2464         return SDL_TRUE;
2465     }
2466 
2467     if (SDL_IsGameControllerNameAndGUID(name, guid) &&
2468         SDL_ShouldIgnoreGameController(name, guid)) {
2469         return SDL_TRUE;
2470     }
2471 
2472     return SDL_FALSE;
2473 }
2474 
2475 /* return the guid for this index */
SDL_JoystickGetDeviceGUID(int device_index)2476 SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
2477 {
2478     SDL_JoystickDriver *driver;
2479     SDL_JoystickGUID guid;
2480 
2481     SDL_LockJoysticks();
2482     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
2483         guid = driver->GetDeviceGUID(device_index);
2484     } else {
2485         SDL_zero(guid);
2486     }
2487     SDL_UnlockJoysticks();
2488 
2489     return guid;
2490 }
2491 
SDL_JoystickGetDeviceVendor(int device_index)2492 Uint16 SDL_JoystickGetDeviceVendor(int device_index)
2493 {
2494     Uint16 vendor;
2495     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
2496 
2497     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
2498     return vendor;
2499 }
2500 
SDL_JoystickGetDeviceProduct(int device_index)2501 Uint16 SDL_JoystickGetDeviceProduct(int device_index)
2502 {
2503     Uint16 product;
2504     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
2505 
2506     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
2507     return product;
2508 }
2509 
SDL_JoystickGetDeviceProductVersion(int device_index)2510 Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
2511 {
2512     Uint16 version;
2513     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
2514 
2515     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
2516     return version;
2517 }
2518 
SDL_JoystickGetDeviceType(int device_index)2519 SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
2520 {
2521     SDL_JoystickType type;
2522     SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
2523 
2524     type = SDL_GetJoystickGUIDType(guid);
2525     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
2526         if (SDL_IsGameController(device_index)) {
2527             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
2528         }
2529     }
2530     return type;
2531 }
2532 
SDL_JoystickGetDeviceInstanceID(int device_index)2533 SDL_JoystickID SDL_JoystickGetDeviceInstanceID(int device_index)
2534 {
2535     SDL_JoystickDriver *driver;
2536     SDL_JoystickID instance_id = -1;
2537 
2538     SDL_LockJoysticks();
2539     if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
2540         instance_id = driver->GetDeviceInstanceID(device_index);
2541     }
2542     SDL_UnlockJoysticks();
2543 
2544     return instance_id;
2545 }
2546 
SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)2547 int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
2548 {
2549     int i, num_joysticks, device_index = -1;
2550 
2551     SDL_LockJoysticks();
2552     num_joysticks = SDL_NumJoysticks();
2553     for (i = 0; i < num_joysticks; ++i) {
2554         if (SDL_JoystickGetDeviceInstanceID(i) == instance_id) {
2555             device_index = i;
2556             break;
2557         }
2558     }
2559     SDL_UnlockJoysticks();
2560 
2561     return device_index;
2562 }
2563 
SDL_JoystickGetGUID(SDL_Joystick * joystick)2564 SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick)
2565 {
2566     if (!SDL_PrivateJoystickValid(joystick)) {
2567         SDL_JoystickGUID emptyGUID;
2568         SDL_zero(emptyGUID);
2569         return emptyGUID;
2570     }
2571     return joystick->guid;
2572 }
2573 
SDL_JoystickGetVendor(SDL_Joystick * joystick)2574 Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick)
2575 {
2576     Uint16 vendor;
2577     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
2578 
2579     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
2580     return vendor;
2581 }
2582 
SDL_JoystickGetProduct(SDL_Joystick * joystick)2583 Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick)
2584 {
2585     Uint16 product;
2586     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
2587 
2588     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
2589     return product;
2590 }
2591 
SDL_JoystickGetProductVersion(SDL_Joystick * joystick)2592 Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick)
2593 {
2594     Uint16 version;
2595     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
2596 
2597     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
2598     return version;
2599 }
2600 
SDL_JoystickGetSerial(SDL_Joystick * joystick)2601 const char *SDL_JoystickGetSerial(SDL_Joystick *joystick)
2602 {
2603     if (!SDL_PrivateJoystickValid(joystick)) {
2604         return NULL;
2605     }
2606     return joystick->serial;
2607 }
2608 
SDL_JoystickGetType(SDL_Joystick * joystick)2609 SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick)
2610 {
2611     SDL_JoystickType type;
2612     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
2613 
2614     type = SDL_GetJoystickGUIDType(guid);
2615     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
2616         if (joystick && joystick->is_game_controller) {
2617             type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
2618         }
2619     }
2620     return type;
2621 }
2622 
2623 /* convert the guid to a printable string */
SDL_JoystickGetGUIDString(SDL_JoystickGUID guid,char * pszGUID,int cbGUID)2624 void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
2625 {
2626     static const char k_rgchHexToASCII[] = "0123456789abcdef";
2627     int i;
2628 
2629     if ((pszGUID == NULL) || (cbGUID <= 0)) {
2630         return;
2631     }
2632 
2633     for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
2634         /* each input byte writes 2 ascii chars, and might write a null byte. */
2635         /* If we don't have room for next input byte, stop */
2636         unsigned char c = guid.data[i];
2637 
2638         *pszGUID++ = k_rgchHexToASCII[c >> 4];
2639         *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
2640     }
2641     *pszGUID = '\0';
2642 }
2643 
2644 /*-----------------------------------------------------------------------------
2645  * Purpose: Returns the 4 bit nibble for a hex character
2646  * Input  : c -
2647  * Output : unsigned char
2648  *-----------------------------------------------------------------------------*/
nibble(char c)2649 static unsigned char nibble(char c)
2650 {
2651     if ((c >= '0') && (c <= '9')) {
2652         return (unsigned char)(c - '0');
2653     }
2654 
2655     if ((c >= 'A') && (c <= 'F')) {
2656         return (unsigned char)(c - 'A' + 0x0a);
2657     }
2658 
2659     if ((c >= 'a') && (c <= 'f')) {
2660         return (unsigned char)(c - 'a' + 0x0a);
2661     }
2662 
2663     /* received an invalid character, and no real way to return an error */
2664     /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
2665     return 0;
2666 }
2667 
2668 /* convert the string version of a joystick guid to the struct */
SDL_JoystickGetGUIDFromString(const char * pchGUID)2669 SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
2670 {
2671     SDL_JoystickGUID guid;
2672     int maxoutputbytes= sizeof(guid);
2673     size_t len = SDL_strlen(pchGUID);
2674     Uint8 *p;
2675     size_t i;
2676 
2677     /* Make sure it's even */
2678     len = (len) & ~0x1;
2679 
2680     SDL_memset(&guid, 0x00, sizeof(guid));
2681 
2682     p = (Uint8 *)&guid;
2683     for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
2684         *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
2685     }
2686 
2687     return guid;
2688 }
2689 
2690 /* update the power level for this joystick */
SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick,SDL_JoystickPowerLevel ePowerLevel)2691 void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
2692 {
2693     joystick->epowerlevel = ePowerLevel;
2694 }
2695 
2696 /* return its power level */
SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)2697 SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick)
2698 {
2699     if (!SDL_PrivateJoystickValid(joystick)) {
2700         return SDL_JOYSTICK_POWER_UNKNOWN;
2701     }
2702     return joystick->epowerlevel;
2703 }
2704 
SDL_PrivateJoystickTouchpad(SDL_Joystick * joystick,int touchpad,int finger,Uint8 state,float x,float y,float pressure)2705 int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure)
2706 {
2707     SDL_JoystickTouchpadInfo *touchpad_info;
2708     SDL_JoystickTouchpadFingerInfo *finger_info;
2709     int posted;
2710 #if !SDL_EVENTS_DISABLED
2711     Uint32 event_type;
2712 #endif
2713 
2714     if (touchpad < 0 || touchpad >= joystick->ntouchpads) {
2715         return 0;
2716     }
2717 
2718     touchpad_info = &joystick->touchpads[touchpad];
2719     if (finger < 0 || finger >= touchpad_info->nfingers) {
2720         return 0;
2721     }
2722 
2723     finger_info = &touchpad_info->fingers[finger];
2724 
2725     if (!state) {
2726         if (x == 0.0f && y == 0.0f) {
2727             x = finger_info->x;
2728             y = finger_info->y;
2729         }
2730         pressure = 0.0f;
2731     }
2732 
2733     if (x < 0.0f) {
2734         x = 0.0f;
2735     } else if (x > 1.0f) {
2736         x = 1.0f;
2737     }
2738     if (y < 0.0f) {
2739         y = 0.0f;
2740     } else if (y > 1.0f) {
2741         y = 1.0f;
2742     }
2743     if (pressure < 0.0f) {
2744         pressure = 0.0f;
2745     } else if (pressure > 1.0f) {
2746         pressure = 1.0f;
2747     }
2748 
2749     if (state == finger_info->state) {
2750         if (!state ||
2751             (x == finger_info->x && y == finger_info->y && pressure == finger_info->pressure)) {
2752             return 0;
2753         }
2754     }
2755 
2756 #if !SDL_EVENTS_DISABLED
2757     if (state == finger_info->state) {
2758         event_type = SDL_CONTROLLERTOUCHPADMOTION;
2759     } else if (state) {
2760         event_type = SDL_CONTROLLERTOUCHPADDOWN;
2761     } else {
2762         event_type = SDL_CONTROLLERTOUCHPADUP;
2763     }
2764 #endif
2765 
2766     /* We ignore events if we don't have keyboard focus, except for touch release */
2767     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
2768         if (event_type != SDL_CONTROLLERTOUCHPADUP) {
2769             return 0;
2770         }
2771     }
2772 
2773     /* Update internal joystick state */
2774     finger_info->state = state;
2775     finger_info->x = x;
2776     finger_info->y = y;
2777     finger_info->pressure = pressure;
2778 
2779     /* Post the event, if desired */
2780     posted = 0;
2781 #if !SDL_EVENTS_DISABLED
2782     if (SDL_GetEventState(event_type) == SDL_ENABLE) {
2783         SDL_Event event;
2784         event.type = event_type;
2785         event.ctouchpad.which = joystick->instance_id;
2786         event.ctouchpad.touchpad = touchpad;
2787         event.ctouchpad.finger = finger;
2788         event.ctouchpad.x = x;
2789         event.ctouchpad.y = y;
2790         event.ctouchpad.pressure = pressure;
2791         posted = SDL_PushEvent(&event) == 1;
2792     }
2793 #endif /* !SDL_EVENTS_DISABLED */
2794     return posted;
2795 }
2796 
SDL_PrivateJoystickSensor(SDL_Joystick * joystick,SDL_SensorType type,const float * data,int num_values)2797 int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values)
2798 {
2799     int i;
2800     int posted = 0;
2801 
2802     /* We ignore events if we don't have keyboard focus */
2803     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
2804         return 0;
2805     }
2806 
2807     for (i = 0; i < joystick->nsensors; ++i) {
2808         SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
2809 
2810         if (sensor->type == type) {
2811             if (sensor->enabled) {
2812                 num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
2813 
2814                 /* Update internal sensor state */
2815                 SDL_memcpy(sensor->data, data, num_values*sizeof(*data));
2816 
2817                 /* Post the event, if desired */
2818 #if !SDL_EVENTS_DISABLED
2819                 if (SDL_GetEventState(SDL_CONTROLLERSENSORUPDATE) == SDL_ENABLE) {
2820                     SDL_Event event;
2821                     event.type = SDL_CONTROLLERSENSORUPDATE;
2822                     event.csensor.which = joystick->instance_id;
2823                     event.csensor.sensor = type;
2824                     num_values = SDL_min(num_values, SDL_arraysize(event.csensor.data));
2825                     SDL_memset(event.csensor.data, 0, sizeof(event.csensor.data));
2826                     SDL_memcpy(event.csensor.data, data, num_values*sizeof(*data));
2827                     posted = SDL_PushEvent(&event) == 1;
2828                 }
2829 #endif /* !SDL_EVENTS_DISABLED */
2830             }
2831             break;
2832         }
2833     }
2834     return posted;
2835 }
2836 
2837 /* vi: set ts=4 sw=4 expandtab: */
2838