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