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