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