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 #ifdef SDL_JOYSTICK_LINUX
24 
25 #ifndef SDL_INPUT_LINUXEV
26 #error SDL now requires a Linux 2.4+ kernel with /dev/input/event support.
27 #endif
28 
29 /* This is the Linux implementation of the SDL joystick API */
30 
31 #include <sys/stat.h>
32 #include <errno.h>              /* errno, strerror */
33 #include <fcntl.h>
34 #include <limits.h>             /* For the definition of PATH_MAX */
35 #ifdef HAVE_INOTIFY
36 #include <sys/inotify.h>
37 #endif
38 #include <sys/ioctl.h>
39 #include <unistd.h>
40 #include <dirent.h>
41 #include <linux/joystick.h>
42 
43 #include "SDL_hints.h"
44 #include "SDL_joystick.h"
45 #include "SDL_log.h"
46 #include "SDL_endian.h"
47 #include "SDL_timer.h"
48 #include "../../events/SDL_events_c.h"
49 #include "../SDL_sysjoystick.h"
50 #include "../SDL_joystick_c.h"
51 #include "../steam/SDL_steamcontroller.h"
52 #include "SDL_sysjoystick_c.h"
53 #include "../hidapi/SDL_hidapijoystick_c.h"
54 
55 /* This isn't defined in older Linux kernel headers */
56 #ifndef SYN_DROPPED
57 #define SYN_DROPPED 3
58 #endif
59 #ifndef BTN_NORTH
60 #define BTN_NORTH       0x133
61 #endif
62 #ifndef BTN_WEST
63 #define BTN_WEST        0x134
64 #endif
65 #ifndef BTN_DPAD_UP
66 #define BTN_DPAD_UP     0x220
67 #endif
68 #ifndef BTN_DPAD_DOWN
69 #define BTN_DPAD_DOWN   0x221
70 #endif
71 #ifndef BTN_DPAD_LEFT
72 #define BTN_DPAD_LEFT   0x222
73 #endif
74 #ifndef BTN_DPAD_RIGHT
75 #define BTN_DPAD_RIGHT  0x223
76 #endif
77 
78 #include "../../core/linux/SDL_evdev_capabilities.h"
79 #include "../../core/linux/SDL_udev.h"
80 
81 #if 0
82 #define DEBUG_INPUT_EVENTS 1
83 #endif
84 
85 typedef enum
86 {
87     ENUMERATION_UNSET,
88     ENUMERATION_LIBUDEV,
89     ENUMERATION_FALLBACK
90 } EnumerationMethod;
91 
92 static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
93 
94 static SDL_bool IsJoystickJSNode(const char *node);
95 static int MaybeAddDevice(const char *path);
96 static int MaybeRemoveDevice(const char *path);
97 
98 /* A linked list of available joysticks */
99 typedef struct SDL_joylist_item
100 {
101     int device_instance;
102     char *path;   /* "/dev/input/event2" or whatever */
103     char *name;   /* "SideWinder 3D Pro" or whatever */
104     SDL_JoystickGUID guid;
105     dev_t devnum;
106     struct joystick_hwdata *hwdata;
107     struct SDL_joylist_item *next;
108 
109     /* Steam Controller support */
110     SDL_bool m_bSteamController;
111 
112     SDL_GamepadMapping *mapping;
113 } SDL_joylist_item;
114 
115 static SDL_bool SDL_classic_joysticks = SDL_FALSE;
116 static SDL_joylist_item *SDL_joylist = NULL;
117 static SDL_joylist_item *SDL_joylist_tail = NULL;
118 static int numjoysticks = 0;
119 static int inotify_fd = -1;
120 
121 static Uint32 last_joy_detect_time;
122 static time_t last_input_dir_mtime;
123 
124 static void
FixupDeviceInfoForMapping(int fd,struct input_id * inpid)125 FixupDeviceInfoForMapping(int fd, struct input_id *inpid)
126 {
127     if (inpid->vendor == 0x045e && inpid->product == 0x0b05 && inpid->version == 0x0903) {
128         /* This is a Microsoft Xbox One Elite Series 2 controller */
129         unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
130 
131         /* The first version of the firmware duplicated all the inputs */
132         if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
133             test_bit(0x2c0, keybit)) {
134             /* Change the version to 0x0902, so we can map it differently */
135             inpid->version = 0x0902;
136         }
137     }
138 
139     /* For Atari vcs modern and classic controllers have the version reflecting
140      * firmware version, but the mapping stays stable so ignore
141      * version information */
142     if (inpid->vendor == 0x3250
143             && (inpid->product == 0x1001 || inpid->product == 0x1002)) {
144         inpid->version = 0;
145     }
146 }
147 
148 #ifdef SDL_JOYSTICK_HIDAPI
149 static SDL_bool
IsVirtualJoystick(Uint16 vendor,Uint16 product,Uint16 version,const char * name)150 IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, const char *name)
151 {
152     if (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX_ONE_S && version == 0 &&
153         SDL_strcmp(name, "Xbox One S Controller") == 0) {
154         /* This is the virtual device created by the xow driver */
155         return SDL_TRUE;
156     }
157     return SDL_FALSE;
158 }
159 #endif /* SDL_JOYSTICK_HIDAPI */
160 
161 static int
GuessIsJoystick(int fd)162 GuessIsJoystick(int fd)
163 {
164     unsigned long evbit[NBITS(EV_MAX)] = { 0 };
165     unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
166     unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
167     unsigned long relbit[NBITS(REL_MAX)] = { 0 };
168     int devclass;
169 
170     if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
171         (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
172         (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) < 0) ||
173         (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
174         return (0);
175     }
176 
177     devclass = SDL_EVDEV_GuessDeviceClass(evbit, absbit, keybit, relbit);
178 
179     if (devclass & SDL_UDEV_DEVICE_JOYSTICK) {
180         return 1;
181     }
182 
183     return 0;
184 }
185 
186 static int
IsJoystick(const char * path,int fd,char ** name_return,SDL_JoystickGUID * guid)187 IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
188 {
189     struct input_id inpid;
190     Uint16 *guid16 = (Uint16 *)guid->data;
191     char *name;
192     char product_string[128];
193 
194     if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) {
195         SDL_zero(inpid);
196 #if SDL_USE_LIBUDEV
197         SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version);
198 #endif
199     } else {
200         /* When udev is enabled we only get joystick devices here, so there's no need to test them */
201         if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) {
202             return 0;
203         }
204 
205         if (ioctl(fd, EVIOCGID, &inpid) < 0) {
206             return 0;
207         }
208 
209         if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
210             return 0;
211         }
212     }
213 
214     name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string);
215     if (!name) {
216         return 0;
217     }
218 
219 #ifdef SDL_JOYSTICK_HIDAPI
220     if (!IsVirtualJoystick(inpid.vendor, inpid.product, inpid.version, name) &&
221         HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, name)) {
222         /* The HIDAPI driver is taking care of this device */
223         SDL_free(name);
224         return 0;
225     }
226 #endif
227 
228     FixupDeviceInfoForMapping(fd, &inpid);
229 
230 #ifdef DEBUG_JOYSTICK
231     SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
232 #endif
233 
234     SDL_memset(guid->data, 0, sizeof(guid->data));
235 
236     /* We only need 16 bits for each of these; space them out to fill 128. */
237     /* Byteswap so devices get same GUID on little/big endian platforms. */
238     *guid16++ = SDL_SwapLE16(inpid.bustype);
239     *guid16++ = 0;
240 
241     if (inpid.vendor && inpid.product) {
242         *guid16++ = SDL_SwapLE16(inpid.vendor);
243         *guid16++ = 0;
244         *guid16++ = SDL_SwapLE16(inpid.product);
245         *guid16++ = 0;
246         *guid16++ = SDL_SwapLE16(inpid.version);
247         *guid16++ = 0;
248     } else {
249         SDL_strlcpy((char*)guid16, name, sizeof(guid->data) - 4);
250     }
251 
252     if (SDL_ShouldIgnoreJoystick(name, *guid)) {
253         SDL_free(name);
254         return 0;
255     }
256     *name_return = name;
257     return 1;
258 }
259 
260 #if SDL_USE_LIBUDEV
joystick_udev_callback(SDL_UDEV_deviceevent udev_type,int udev_class,const char * devpath)261 static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
262 {
263     if (devpath == NULL) {
264         return;
265     }
266 
267     switch (udev_type) {
268         case SDL_UDEV_DEVICEADDED:
269             if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
270                 return;
271             }
272             if (SDL_classic_joysticks) {
273                 if (!IsJoystickJSNode(devpath)) {
274                     return;
275                 }
276             } else {
277                 if (IsJoystickJSNode(devpath)) {
278                     return;
279                 }
280             }
281             MaybeAddDevice(devpath);
282             break;
283 
284         case SDL_UDEV_DEVICEREMOVED:
285             MaybeRemoveDevice(devpath);
286             break;
287 
288         default:
289             break;
290     }
291 
292 }
293 #endif /* SDL_USE_LIBUDEV */
294 
295 static void
FreeJoylistItem(SDL_joylist_item * item)296 FreeJoylistItem(SDL_joylist_item *item)
297 {
298     SDL_free(item->mapping);
299     SDL_free(item->path);
300     SDL_free(item->name);
301     SDL_free(item);
302 }
303 
304 static int
MaybeAddDevice(const char * path)305 MaybeAddDevice(const char *path)
306 {
307     struct stat sb;
308     int fd = -1;
309     int isstick = 0;
310     char *name = NULL;
311     SDL_JoystickGUID guid;
312     SDL_joylist_item *item;
313 
314     if (path == NULL) {
315         return -1;
316     }
317 
318     if (stat(path, &sb) == -1) {
319         return -1;
320     }
321 
322     /* Check to make sure it's not already in list. */
323     for (item = SDL_joylist; item != NULL; item = item->next) {
324         if (sb.st_rdev == item->devnum) {
325             return -1;  /* already have this one */
326         }
327     }
328 
329     fd = open(path, O_RDONLY | O_CLOEXEC, 0);
330     if (fd < 0) {
331         return -1;
332     }
333 
334 #ifdef DEBUG_INPUT_EVENTS
335     SDL_Log("Checking %s\n", path);
336 #endif
337 
338     isstick = IsJoystick(path, fd, &name, &guid);
339     close(fd);
340     if (!isstick) {
341         return -1;
342     }
343 
344     item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
345     if (item == NULL) {
346         return -1;
347     }
348 
349     item->devnum = sb.st_rdev;
350     item->path = SDL_strdup(path);
351     item->name = name;
352     item->guid = guid;
353 
354     if ((item->path == NULL) || (item->name == NULL)) {
355          FreeJoylistItem(item);
356          return -1;
357     }
358 
359     item->device_instance = SDL_GetNextJoystickInstanceID();
360     if (SDL_joylist_tail == NULL) {
361         SDL_joylist = SDL_joylist_tail = item;
362     } else {
363         SDL_joylist_tail->next = item;
364         SDL_joylist_tail = item;
365     }
366 
367     /* Need to increment the joystick count before we post the event */
368     ++numjoysticks;
369 
370     SDL_PrivateJoystickAdded(item->device_instance);
371 
372     return numjoysticks;
373 }
374 
375 static void
RemoveJoylistItem(SDL_joylist_item * item,SDL_joylist_item * prev)376 RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev)
377 {
378     if (item->hwdata) {
379         item->hwdata->item = NULL;
380     }
381 
382     if (prev != NULL) {
383         prev->next = item->next;
384     } else {
385         SDL_assert(SDL_joylist == item);
386         SDL_joylist = item->next;
387     }
388 
389     if (item == SDL_joylist_tail) {
390         SDL_joylist_tail = prev;
391     }
392 
393     /* Need to decrement the joystick count before we post the event */
394     --numjoysticks;
395 
396     SDL_PrivateJoystickRemoved(item->device_instance);
397     FreeJoylistItem(item);
398 }
399 
400 static int
MaybeRemoveDevice(const char * path)401 MaybeRemoveDevice(const char *path)
402 {
403     SDL_joylist_item *item;
404     SDL_joylist_item *prev = NULL;
405 
406     if (path == NULL) {
407         return -1;
408     }
409 
410     for (item = SDL_joylist; item != NULL; item = item->next) {
411         /* found it, remove it. */
412         if (SDL_strcmp(path, item->path) == 0) {
413             const int retval = item->device_instance;
414             RemoveJoylistItem(item, prev);
415             return retval;
416         }
417         prev = item;
418     }
419 
420     return -1;
421 }
422 
423 static void
HandlePendingRemovals(void)424 HandlePendingRemovals(void)
425 {
426     SDL_joylist_item *prev = NULL;
427     SDL_joylist_item *item = SDL_joylist;
428 
429     while (item != NULL) {
430         if (item->hwdata && item->hwdata->gone) {
431             RemoveJoylistItem(item, prev);
432 
433             if (prev != NULL) {
434                 item = prev->next;
435             } else {
436                 item = SDL_joylist;
437             }
438         } else {
439             prev = item;
440             item = item->next;
441         }
442     }
443 }
444 
SteamControllerConnectedCallback(const char * name,SDL_JoystickGUID guid,int * device_instance)445 static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
446 {
447     SDL_joylist_item *item;
448 
449     item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
450     if (item == NULL) {
451         return SDL_FALSE;
452     }
453 
454     item->path = SDL_strdup("");
455     item->name = SDL_strdup(name);
456     item->guid = guid;
457     item->m_bSteamController = SDL_TRUE;
458 
459     if ((item->path == NULL) || (item->name == NULL)) {
460          FreeJoylistItem(item);
461          return SDL_FALSE;
462     }
463 
464     *device_instance = item->device_instance = SDL_GetNextJoystickInstanceID();
465     if (SDL_joylist_tail == NULL) {
466         SDL_joylist = SDL_joylist_tail = item;
467     } else {
468         SDL_joylist_tail->next = item;
469         SDL_joylist_tail = item;
470     }
471 
472     /* Need to increment the joystick count before we post the event */
473     ++numjoysticks;
474 
475     SDL_PrivateJoystickAdded(item->device_instance);
476 
477     return SDL_TRUE;
478 }
479 
SteamControllerDisconnectedCallback(int device_instance)480 static void SteamControllerDisconnectedCallback(int device_instance)
481 {
482     SDL_joylist_item *item;
483     SDL_joylist_item *prev = NULL;
484 
485     for (item = SDL_joylist; item != NULL; item = item->next) {
486         /* found it, remove it. */
487         if (item->device_instance == device_instance) {
488             RemoveJoylistItem(item, prev);
489             return;
490         }
491         prev = item;
492     }
493 }
494 
495 #ifdef HAVE_INOTIFY
496 #ifdef HAVE_INOTIFY_INIT1
SDL_inotify_init1(void)497 static int SDL_inotify_init1(void) {
498     return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
499 }
500 #else
SDL_inotify_init1(void)501 static int SDL_inotify_init1(void) {
502     int fd = inotify_init();
503     if (fd  < 0) return -1;
504     fcntl(fd, F_SETFL, O_NONBLOCK);
505     fcntl(fd, F_SETFD, FD_CLOEXEC);
506     return fd;
507 }
508 #endif
509 #endif
510 
511 static int
StrHasPrefix(const char * string,const char * prefix)512 StrHasPrefix(const char *string, const char *prefix)
513 {
514     return (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0);
515 }
516 
517 static int
StrIsInteger(const char * string)518 StrIsInteger(const char *string)
519 {
520     const char *p;
521 
522     if (*string == '\0') {
523         return 0;
524     }
525 
526     for (p = string; *p != '\0'; p++) {
527         if (*p < '0' || *p > '9') {
528             return 0;
529         }
530     }
531 
532     return 1;
533 }
534 
535 static SDL_bool
IsJoystickJSNode(const char * node)536 IsJoystickJSNode(const char *node)
537 {
538     const char *last_slash = SDL_strrchr(node, '/');
539     if (last_slash) {
540         node = last_slash + 1;
541     }
542     return (StrHasPrefix(node, "js") && StrIsInteger(node + 2));
543 }
544 
545 static SDL_bool
IsJoystickEventNode(const char * node)546 IsJoystickEventNode(const char *node)
547 {
548     const char *last_slash = SDL_strrchr(node, '/');
549     if (last_slash) {
550         node = last_slash + 1;
551     }
552     return (StrHasPrefix(node, "event") && StrIsInteger(node + 5));
553 }
554 
555 static SDL_bool
IsJoystickDeviceNode(const char * node)556 IsJoystickDeviceNode(const char *node)
557 {
558     if (SDL_classic_joysticks) {
559         return IsJoystickJSNode(node);
560     } else {
561         return IsJoystickEventNode(node);
562     }
563 }
564 
565 #ifdef HAVE_INOTIFY
566 static void
LINUX_InotifyJoystickDetect(void)567 LINUX_InotifyJoystickDetect(void)
568 {
569     union
570     {
571         struct inotify_event event;
572         char storage[4096];
573         char enough_for_inotify[sizeof (struct inotify_event) + NAME_MAX + 1];
574     } buf;
575     ssize_t bytes;
576     size_t remain = 0;
577     size_t len;
578     char path[PATH_MAX];
579 
580     bytes = read(inotify_fd, &buf, sizeof (buf));
581 
582     if (bytes > 0) {
583         remain = (size_t) bytes;
584     }
585 
586     while (remain > 0) {
587         if (buf.event.len > 0) {
588             if (IsJoystickDeviceNode(buf.event.name)) {
589                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name);
590 
591                 if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) {
592                     MaybeAddDevice(path);
593                 }
594                 else if (buf.event.mask & (IN_DELETE | IN_MOVED_FROM)) {
595                     MaybeRemoveDevice(path);
596                 }
597             }
598         }
599 
600         len = sizeof (struct inotify_event) + buf.event.len;
601         remain -= len;
602 
603         if (remain != 0) {
604             SDL_memmove (&buf.storage[0], &buf.storage[len], remain);
605         }
606     }
607 }
608 #endif /* HAVE_INOTIFY */
609 
610 /* Detect devices by reading /dev/input. In the inotify code path we
611  * have to do this the first time, to detect devices that already existed
612  * before we started; in the non-inotify code path we do this repeatedly
613  * (polling). */
614 static int
filter_entries(const struct dirent * entry)615 filter_entries(const struct dirent *entry)
616 {
617     return IsJoystickDeviceNode(entry->d_name);
618 }
619 static int
sort_entries(const struct dirent ** a,const struct dirent ** b)620 sort_entries(const struct dirent **a, const struct dirent **b)
621 {
622     int numA = SDL_atoi((*a)->d_name+5);
623     int numB = SDL_atoi((*b)->d_name+5);
624     return (numA - numB);
625 }
626 static void
LINUX_FallbackJoystickDetect(void)627 LINUX_FallbackJoystickDetect(void)
628 {
629     const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000;  /* Update every 3 seconds */
630     Uint32 now = SDL_GetTicks();
631 
632     if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
633         struct stat sb;
634 
635         /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
636         if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
637             int i, count;
638             struct dirent **entries;
639             char path[PATH_MAX];
640 
641             count = scandir("/dev/input", &entries, filter_entries, sort_entries);
642             for (i = 0; i < count; ++i) {
643                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
644                 MaybeAddDevice(path);
645 
646                 free(entries[i]); /* This should NOT be SDL_free() */
647             }
648             free(entries); /* This should NOT be SDL_free() */
649 
650             last_input_dir_mtime = sb.st_mtime;
651         }
652 
653         last_joy_detect_time = now;
654     }
655 }
656 
657 static void
LINUX_JoystickDetect(void)658 LINUX_JoystickDetect(void)
659 {
660 #if SDL_USE_LIBUDEV
661     if (enumeration_method == ENUMERATION_LIBUDEV) {
662         SDL_UDEV_Poll();
663     }
664     else
665 #endif
666 #ifdef HAVE_INOTIFY
667     if (inotify_fd >= 0 && last_joy_detect_time != 0) {
668         LINUX_InotifyJoystickDetect();
669     }
670     else
671 #endif
672     {
673         LINUX_FallbackJoystickDetect();
674     }
675 
676     HandlePendingRemovals();
677 
678     SDL_UpdateSteamControllers();
679 }
680 
681 static int
LINUX_JoystickInit(void)682 LINUX_JoystickInit(void)
683 {
684     const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE);
685 
686     SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE);
687 
688 #if SDL_USE_LIBUDEV
689     if (enumeration_method == ENUMERATION_UNSET) {
690         if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
691             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
692                          "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
693             enumeration_method = ENUMERATION_FALLBACK;
694 
695         } else if (access("/.flatpak-info", F_OK) == 0
696                  || access("/run/host/container-manager", F_OK) == 0) {
697             /* Explicitly check `/.flatpak-info` because, for old versions of
698              * Flatpak, this was the only available way to tell if we were in
699              * a Flatpak container. */
700             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
701                          "Container detected, disabling udev integration");
702             enumeration_method = ENUMERATION_FALLBACK;
703 
704         } else {
705             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
706                          "Using udev for joystick device discovery");
707             enumeration_method = ENUMERATION_LIBUDEV;
708         }
709     }
710 #endif
711 
712     /* First see if the user specified one or more joysticks to use */
713     if (devices != NULL) {
714         char *envcopy, *envpath, *delim;
715         envcopy = SDL_strdup(devices);
716         envpath = envcopy;
717         while (envpath != NULL) {
718             delim = SDL_strchr(envpath, ':');
719             if (delim != NULL) {
720                 *delim++ = '\0';
721             }
722             MaybeAddDevice(envpath);
723             envpath = delim;
724         }
725         SDL_free(envcopy);
726     }
727 
728     SDL_InitSteamControllers(SteamControllerConnectedCallback,
729                              SteamControllerDisconnectedCallback);
730 
731     /* Force immediate joystick detection if using fallback */
732     last_joy_detect_time = 0;
733     last_input_dir_mtime = 0;
734 
735     /* Manually scan first, since we sort by device number and udev doesn't */
736     LINUX_JoystickDetect();
737 
738 #if SDL_USE_LIBUDEV
739     if (enumeration_method == ENUMERATION_LIBUDEV) {
740         if (SDL_UDEV_Init() < 0) {
741             return SDL_SetError("Could not initialize UDEV");
742         }
743 
744         /* Set up the udev callback */
745         if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
746             SDL_UDEV_Quit();
747             return SDL_SetError("Could not set up joystick <-> udev callback");
748         }
749 
750         /* Force a scan to build the initial device list */
751         SDL_UDEV_Scan();
752     }
753     else
754 #endif
755     {
756 #if defined(HAVE_INOTIFY)
757         inotify_fd = SDL_inotify_init1();
758 
759         if (inotify_fd < 0) {
760             SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
761                         "Unable to initialize inotify, falling back to polling: %s",
762                         strerror (errno));
763         } else {
764             /* We need to watch for attribute changes in addition to
765              * creation, because when a device is first created, it has
766              * permissions that we can't read. When udev chmods it to
767              * something that we maybe *can* read, we'll get an
768              * IN_ATTRIB event to tell us. */
769             if (inotify_add_watch(inotify_fd, "/dev/input",
770                                   IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
771                 close(inotify_fd);
772                 inotify_fd = -1;
773                 SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
774                             "Unable to add inotify watch, falling back to polling: %s",
775                             strerror (errno));
776             }
777         }
778 #endif /* HAVE_INOTIFY */
779     }
780 
781     return 0;
782 }
783 
784 static int
LINUX_JoystickGetCount(void)785 LINUX_JoystickGetCount(void)
786 {
787     return numjoysticks;
788 }
789 
790 static SDL_joylist_item *
JoystickByDevIndex(int device_index)791 JoystickByDevIndex(int device_index)
792 {
793     SDL_joylist_item *item = SDL_joylist;
794 
795     if ((device_index < 0) || (device_index >= numjoysticks)) {
796         return NULL;
797     }
798 
799     while (device_index > 0) {
800         SDL_assert(item != NULL);
801         device_index--;
802         item = item->next;
803     }
804 
805     return item;
806 }
807 
808 /* Function to get the device-dependent name of a joystick */
809 static const char *
LINUX_JoystickGetDeviceName(int device_index)810 LINUX_JoystickGetDeviceName(int device_index)
811 {
812     return JoystickByDevIndex(device_index)->name;
813 }
814 
815 static int
LINUX_JoystickGetDevicePlayerIndex(int device_index)816 LINUX_JoystickGetDevicePlayerIndex(int device_index)
817 {
818     return -1;
819 }
820 
821 static void
LINUX_JoystickSetDevicePlayerIndex(int device_index,int player_index)822 LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
823 {
824 }
825 
826 static SDL_JoystickGUID
LINUX_JoystickGetDeviceGUID(int device_index)827 LINUX_JoystickGetDeviceGUID( int device_index )
828 {
829     return JoystickByDevIndex(device_index)->guid;
830 }
831 
832 /* Function to perform the mapping from device index to the instance id for this index */
833 static SDL_JoystickID
LINUX_JoystickGetDeviceInstanceID(int device_index)834 LINUX_JoystickGetDeviceInstanceID(int device_index)
835 {
836     return JoystickByDevIndex(device_index)->device_instance;
837 }
838 
839 static int
allocate_hatdata(SDL_Joystick * joystick)840 allocate_hatdata(SDL_Joystick *joystick)
841 {
842     int i;
843 
844     joystick->hwdata->hats =
845         (struct hwdata_hat *) SDL_malloc(joystick->nhats *
846                                          sizeof(struct hwdata_hat));
847     if (joystick->hwdata->hats == NULL) {
848         return (-1);
849     }
850     for (i = 0; i < joystick->nhats; ++i) {
851         joystick->hwdata->hats[i].axis[0] = 1;
852         joystick->hwdata->hats[i].axis[1] = 1;
853     }
854     return (0);
855 }
856 
857 static int
allocate_balldata(SDL_Joystick * joystick)858 allocate_balldata(SDL_Joystick *joystick)
859 {
860     int i;
861 
862     joystick->hwdata->balls =
863         (struct hwdata_ball *) SDL_malloc(joystick->nballs *
864                                           sizeof(struct hwdata_ball));
865     if (joystick->hwdata->balls == NULL) {
866         return (-1);
867     }
868     for (i = 0; i < joystick->nballs; ++i) {
869         joystick->hwdata->balls[i].axis[0] = 0;
870         joystick->hwdata->balls[i].axis[1] = 0;
871     }
872     return (0);
873 }
874 
875 static void
ConfigJoystick(SDL_Joystick * joystick,int fd)876 ConfigJoystick(SDL_Joystick *joystick, int fd)
877 {
878     int i, t;
879     unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
880     unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
881     unsigned long relbit[NBITS(REL_MAX)] = { 0 };
882     unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
883     Uint8 key_pam_size, abs_pam_size;
884     SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE);
885 
886     /* See if this device uses the new unified event API */
887     if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
888         (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
889         (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
890 
891         /* Get the number of buttons, axes, and other thingamajigs */
892         for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
893             if (test_bit(i, keybit)) {
894 #ifdef DEBUG_INPUT_EVENTS
895                 SDL_Log("Joystick has button: 0x%x\n", i);
896 #endif
897                 joystick->hwdata->key_map[i] = joystick->nbuttons;
898                 joystick->hwdata->has_key[i] = SDL_TRUE;
899                 ++joystick->nbuttons;
900             }
901         }
902         for (i = 0; i < BTN_JOYSTICK; ++i) {
903             if (test_bit(i, keybit)) {
904 #ifdef DEBUG_INPUT_EVENTS
905                 SDL_Log("Joystick has button: 0x%x\n", i);
906 #endif
907                 joystick->hwdata->key_map[i] = joystick->nbuttons;
908                 joystick->hwdata->has_key[i] = SDL_TRUE;
909                 ++joystick->nbuttons;
910             }
911         }
912         for (i = 0; i < ABS_MAX; ++i) {
913             /* Skip hats */
914             if (i == ABS_HAT0X) {
915                 i = ABS_HAT3Y;
916                 continue;
917             }
918             if (test_bit(i, absbit)) {
919                 struct input_absinfo absinfo;
920                 struct axis_correct *correct = &joystick->hwdata->abs_correct[i];
921 
922                 if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
923                     continue;
924                 }
925 #ifdef DEBUG_INPUT_EVENTS
926                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
927                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
928                         absinfo.value, absinfo.minimum, absinfo.maximum,
929                         absinfo.fuzz, absinfo.flat);
930 #endif /* DEBUG_INPUT_EVENTS */
931                 joystick->hwdata->abs_map[i] = joystick->naxes;
932                 joystick->hwdata->has_abs[i] = SDL_TRUE;
933 
934                 correct->minimum = absinfo.minimum;
935                 correct->maximum = absinfo.maximum;
936                 if (correct->minimum != correct->maximum) {
937                     if (use_deadzones) {
938                         correct->use_deadzones = SDL_TRUE;
939                         correct->coef[0] = (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
940                         correct->coef[1] = (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
941                         t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
942                         if (t != 0) {
943                             correct->coef[2] = (1 << 28) / t;
944                         } else {
945                             correct->coef[2] = 0;
946                         }
947                     } else {
948                         float value_range = (correct->maximum - correct->minimum);
949                         float output_range = (SDL_JOYSTICK_AXIS_MAX - SDL_JOYSTICK_AXIS_MIN);
950 
951                         correct->scale = (output_range / value_range);
952                     }
953                 }
954                 ++joystick->naxes;
955             }
956         }
957         for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
958             if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
959                 struct input_absinfo absinfo;
960                 int hat_index = (i - ABS_HAT0X) / 2;
961 
962                 if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
963                     continue;
964                 }
965 #ifdef DEBUG_INPUT_EVENTS
966                 SDL_Log("Joystick has hat %d\n", hat_index);
967                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
968                         absinfo.value, absinfo.minimum, absinfo.maximum,
969                         absinfo.fuzz, absinfo.flat);
970 #endif /* DEBUG_INPUT_EVENTS */
971                 joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
972                 joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
973             }
974         }
975         if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
976             ++joystick->nballs;
977         }
978 
979     } else if ((ioctl(fd, JSIOCGBUTTONS, &key_pam_size, sizeof(key_pam_size)) >= 0) &&
980                (ioctl(fd, JSIOCGAXES, &abs_pam_size, sizeof(abs_pam_size)) >= 0)) {
981         size_t len;
982 
983         joystick->hwdata->classic = SDL_TRUE;
984 
985         len = (KEY_MAX - BTN_MISC + 1) * sizeof(*joystick->hwdata->key_pam);
986         joystick->hwdata->key_pam = (Uint16 *)SDL_calloc(1, len);
987         if (joystick->hwdata->key_pam) {
988             if (ioctl(fd, JSIOCGBTNMAP, joystick->hwdata->key_pam, len) < 0) {
989                 SDL_free(joystick->hwdata->key_pam);
990                 joystick->hwdata->key_pam = NULL;
991                 key_pam_size = 0;
992             }
993         } else {
994             key_pam_size = 0;
995         }
996         for (i = 0; i < key_pam_size; ++i) {
997             Uint16 code = joystick->hwdata->key_pam[i];
998 #ifdef DEBUG_INPUT_EVENTS
999             SDL_Log("Joystick has button: 0x%x\n", code);
1000 #endif
1001             joystick->hwdata->key_map[code] = joystick->nbuttons;
1002             joystick->hwdata->has_key[code] = SDL_TRUE;
1003             ++joystick->nbuttons;
1004         }
1005 
1006         len = ABS_CNT * sizeof(*joystick->hwdata->abs_pam);
1007         joystick->hwdata->abs_pam = (Uint8 *)SDL_calloc(1, len);
1008         if (joystick->hwdata->abs_pam) {
1009             if (ioctl(fd, JSIOCGAXMAP, joystick->hwdata->abs_pam, len) < 0) {
1010                 SDL_free(joystick->hwdata->abs_pam);
1011                 joystick->hwdata->abs_pam = NULL;
1012                 abs_pam_size = 0;
1013             }
1014         } else {
1015             abs_pam_size = 0;
1016         }
1017         for (i = 0; i < abs_pam_size; ++i) {
1018             Uint8 code = joystick->hwdata->abs_pam[i];
1019 
1020             if (code >= ABS_HAT0X && code <= ABS_HAT3Y) {
1021                 int hat_index = (code - ABS_HAT0X) / 2;
1022                 if (!joystick->hwdata->has_hat[hat_index]) {
1023 #ifdef DEBUG_INPUT_EVENTS
1024                     SDL_Log("Joystick has hat %d\n", hat_index);
1025 #endif
1026                     joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
1027                     joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
1028                 }
1029             } else {
1030 #ifdef DEBUG_INPUT_EVENTS
1031                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", code);
1032 #endif
1033                 joystick->hwdata->abs_map[code] = joystick->naxes;
1034                 joystick->hwdata->has_abs[code] = SDL_TRUE;
1035                 ++joystick->naxes;
1036             }
1037         }
1038     }
1039 
1040     /* Allocate data to keep track of these thingamajigs */
1041     if (joystick->nhats > 0) {
1042         if (allocate_hatdata(joystick) < 0) {
1043             joystick->nhats = 0;
1044         }
1045     }
1046     if (joystick->nballs > 0) {
1047         if (allocate_balldata(joystick) < 0) {
1048             joystick->nballs = 0;
1049         }
1050     }
1051 
1052     if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) {
1053         if (test_bit(FF_RUMBLE, ffbit)) {
1054             joystick->hwdata->ff_rumble = SDL_TRUE;
1055         }
1056         if (test_bit(FF_SINE, ffbit)) {
1057             joystick->hwdata->ff_sine = SDL_TRUE;
1058         }
1059     }
1060 }
1061 
1062 
1063 /* This is used to do the heavy lifting for LINUX_JoystickOpen and
1064    also LINUX_JoystickGetGamepadMapping, so we can query the hardware
1065    without adding an opened SDL_Joystick object to the system.
1066    This expects `joystick->hwdata` to be allocated and will not free it
1067    on error. Returns -1 on error, 0 on success. */
1068 static int
PrepareJoystickHwdata(SDL_Joystick * joystick,SDL_joylist_item * item)1069 PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item)
1070 {
1071     joystick->hwdata->item = item;
1072     joystick->hwdata->guid = item->guid;
1073     joystick->hwdata->effect.id = -1;
1074     joystick->hwdata->m_bSteamController = item->m_bSteamController;
1075     SDL_memset(joystick->hwdata->key_map, 0xFF, sizeof(joystick->hwdata->key_map));
1076     SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
1077 
1078     if (item->m_bSteamController) {
1079         joystick->hwdata->fd = -1;
1080         SDL_GetSteamControllerInputs(&joystick->nbuttons,
1081                                      &joystick->naxes,
1082                                      &joystick->nhats);
1083     } else {
1084         /* Try read-write first, so we can do rumble */
1085         int fd = open(item->path, O_RDWR | O_CLOEXEC, 0);
1086         if (fd < 0) {
1087             /* Try read-only again, at least we'll get events in this case */
1088             fd = open(item->path, O_RDONLY | O_CLOEXEC, 0);
1089         }
1090         if (fd < 0) {
1091             return SDL_SetError("Unable to open %s", item->path);
1092         }
1093 
1094         joystick->hwdata->fd = fd;
1095         joystick->hwdata->fname = SDL_strdup(item->path);
1096         if (joystick->hwdata->fname == NULL) {
1097             close(fd);
1098             return SDL_OutOfMemory();
1099         }
1100 
1101         /* Set the joystick to non-blocking read mode */
1102         fcntl(fd, F_SETFL, O_NONBLOCK);
1103 
1104         /* Get the number of buttons and axes on the joystick */
1105         ConfigJoystick(joystick, fd);
1106     }
1107     return 0;
1108 }
1109 
1110 
1111 /* Function to open a joystick for use.
1112    The joystick to open is specified by the device index.
1113    This should fill the nbuttons and naxes fields of the joystick structure.
1114    It returns 0, or -1 if there is an error.
1115  */
1116 static int
LINUX_JoystickOpen(SDL_Joystick * joystick,int device_index)1117 LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index)
1118 {
1119     SDL_joylist_item *item = JoystickByDevIndex(device_index);
1120 
1121     if (item == NULL) {
1122         return SDL_SetError("No such device");
1123     }
1124 
1125     joystick->instance_id = item->device_instance;
1126     joystick->hwdata = (struct joystick_hwdata *)
1127         SDL_calloc(1, sizeof(*joystick->hwdata));
1128     if (joystick->hwdata == NULL) {
1129         return SDL_OutOfMemory();
1130     }
1131 
1132     if (PrepareJoystickHwdata(joystick, item) == -1) {
1133         SDL_free(joystick->hwdata);
1134         joystick->hwdata = NULL;
1135         return -1;  /* SDL_SetError will already have been called */
1136     }
1137 
1138     SDL_assert(item->hwdata == NULL);
1139     item->hwdata = joystick->hwdata;
1140 
1141     /* mark joystick as fresh and ready */
1142     joystick->hwdata->fresh = SDL_TRUE;
1143 
1144     return 0;
1145 }
1146 
1147 static int
LINUX_JoystickRumble(SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)1148 LINUX_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1149 {
1150     struct input_event event;
1151 
1152     if (joystick->hwdata->ff_rumble) {
1153         struct ff_effect *effect = &joystick->hwdata->effect;
1154 
1155         effect->type = FF_RUMBLE;
1156         effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
1157         effect->u.rumble.strong_magnitude = low_frequency_rumble;
1158         effect->u.rumble.weak_magnitude = high_frequency_rumble;
1159     } else if (joystick->hwdata->ff_sine) {
1160         /* Scale and average the two rumble strengths */
1161         Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
1162         struct ff_effect *effect = &joystick->hwdata->effect;
1163 
1164         effect->type = FF_PERIODIC;
1165         effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
1166         effect->u.periodic.waveform = FF_SINE;
1167         effect->u.periodic.magnitude = magnitude;
1168     } else {
1169         return SDL_Unsupported();
1170     }
1171 
1172     if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
1173         /* The kernel may have lost this effect, try to allocate a new one */
1174         joystick->hwdata->effect.id = -1;
1175         if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
1176             return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
1177         }
1178     }
1179 
1180     event.type = EV_FF;
1181     event.code = joystick->hwdata->effect.id;
1182     event.value = 1;
1183     if (write(joystick->hwdata->fd, &event, sizeof(event)) < 0) {
1184         return SDL_SetError("Couldn't start rumble effect: %s", strerror(errno));
1185     }
1186     return 0;
1187 }
1188 
1189 static int
LINUX_JoystickRumbleTriggers(SDL_Joystick * joystick,Uint16 left_rumble,Uint16 right_rumble)1190 LINUX_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
1191 {
1192     return SDL_Unsupported();
1193 }
1194 
1195 static Uint32
LINUX_JoystickGetCapabilities(SDL_Joystick * joystick)1196 LINUX_JoystickGetCapabilities(SDL_Joystick *joystick)
1197 {
1198     Uint32 result = 0;
1199 
1200     if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) {
1201         result |= SDL_JOYCAP_RUMBLE;
1202     }
1203 
1204     return result;
1205 }
1206 
1207 static int
LINUX_JoystickSetLED(SDL_Joystick * joystick,Uint8 red,Uint8 green,Uint8 blue)1208 LINUX_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
1209 {
1210     return SDL_Unsupported();
1211 }
1212 
1213 static int
LINUX_JoystickSendEffect(SDL_Joystick * joystick,const void * data,int size)1214 LINUX_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
1215 {
1216     return SDL_Unsupported();
1217 }
1218 
1219 static int
LINUX_JoystickSetSensorsEnabled(SDL_Joystick * joystick,SDL_bool enabled)1220 LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
1221 {
1222     return SDL_Unsupported();
1223 }
1224 
1225 static void
HandleHat(SDL_Joystick * stick,Uint8 hat,int axis,int value)1226 HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
1227 {
1228     struct hwdata_hat *the_hat;
1229     const Uint8 position_map[3][3] = {
1230         {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
1231         {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
1232         {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
1233     };
1234 
1235     the_hat = &stick->hwdata->hats[hat];
1236     if (value < 0) {
1237         value = 0;
1238     } else if (value == 0) {
1239         value = 1;
1240     } else if (value > 0) {
1241         value = 2;
1242     }
1243     if (value != the_hat->axis[axis]) {
1244         the_hat->axis[axis] = value;
1245         SDL_PrivateJoystickHat(stick, hat,
1246                                position_map[the_hat->axis[1]][the_hat->axis[0]]);
1247     }
1248 }
1249 
1250 static void
HandleBall(SDL_Joystick * stick,Uint8 ball,int axis,int value)1251 HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
1252 {
1253     stick->hwdata->balls[ball].axis[axis] += value;
1254 }
1255 
1256 
1257 static int
AxisCorrect(SDL_Joystick * joystick,int which,int value)1258 AxisCorrect(SDL_Joystick *joystick, int which, int value)
1259 {
1260     struct axis_correct *correct;
1261 
1262     correct = &joystick->hwdata->abs_correct[which];
1263     if (correct->minimum != correct->maximum) {
1264         if (correct->use_deadzones) {
1265             value *= 2;
1266             if (value > correct->coef[0]) {
1267                 if (value < correct->coef[1]) {
1268                     return 0;
1269                 }
1270                 value -= correct->coef[1];
1271             } else {
1272                 value -= correct->coef[0];
1273             }
1274             value *= correct->coef[2];
1275             value >>= 13;
1276         } else {
1277             value = (int)SDL_floorf((value - correct->minimum) * correct->scale + SDL_JOYSTICK_AXIS_MIN + 0.5f);
1278         }
1279     }
1280 
1281     /* Clamp and return */
1282     if (value < SDL_JOYSTICK_AXIS_MIN) {
1283         return SDL_JOYSTICK_AXIS_MIN;
1284     }
1285     if (value > SDL_JOYSTICK_AXIS_MAX) {
1286         return SDL_JOYSTICK_AXIS_MAX;
1287     }
1288     return value;
1289 }
1290 
1291 static void
PollAllValues(SDL_Joystick * joystick)1292 PollAllValues(SDL_Joystick *joystick)
1293 {
1294     struct input_absinfo absinfo;
1295     unsigned long keyinfo[NBITS(KEY_MAX)];
1296     int i;
1297 
1298     /* Poll all axis */
1299     for (i = ABS_X; i < ABS_MAX; i++) {
1300         if (i == ABS_HAT0X) {  /* we handle hats in the next loop, skip them for now. */
1301             i = ABS_HAT3Y;
1302             continue;
1303         }
1304         if (joystick->hwdata->has_abs[i]) {
1305             if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
1306                 absinfo.value = AxisCorrect(joystick, i, absinfo.value);
1307 
1308 #ifdef DEBUG_INPUT_EVENTS
1309                 SDL_Log("Joystick : Re-read Axis %d (%d) val= %d\n",
1310                     joystick->hwdata->abs_map[i], i, absinfo.value);
1311 #endif
1312                 SDL_PrivateJoystickAxis(joystick,
1313                         joystick->hwdata->abs_map[i],
1314                         absinfo.value);
1315             }
1316         }
1317     }
1318 
1319     /* Poll all hats */
1320     for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
1321         const int baseaxis = i - ABS_HAT0X;
1322         const int hatidx = baseaxis / 2;
1323         SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
1324         if (joystick->hwdata->has_hat[hatidx]) {
1325             if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
1326                 const int hataxis = baseaxis % 2;
1327                 HandleHat(joystick, joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
1328             }
1329         }
1330     }
1331 
1332     /* Poll all buttons */
1333     SDL_zeroa(keyinfo);
1334     if (ioctl(joystick->hwdata->fd, EVIOCGKEY(sizeof (keyinfo)), keyinfo) >= 0) {
1335         for (i = 0; i < KEY_MAX; i++) {
1336             if (joystick->hwdata->has_key[i]) {
1337                 const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED;
1338 #ifdef DEBUG_INPUT_EVENTS
1339                 SDL_Log("Joystick : Re-read Button %d (%d) val= %d\n",
1340                     joystick->hwdata->key_map[i], i, value);
1341 #endif
1342                 SDL_PrivateJoystickButton(joystick,
1343                         joystick->hwdata->key_map[i], value);
1344             }
1345         }
1346     }
1347 
1348     /* Joyballs are relative input, so there's no poll state. Events only! */
1349 }
1350 
1351 static void
HandleInputEvents(SDL_Joystick * joystick)1352 HandleInputEvents(SDL_Joystick *joystick)
1353 {
1354     struct input_event events[32];
1355     int i, len, code;
1356 
1357     if (joystick->hwdata->fresh) {
1358         PollAllValues(joystick);
1359         joystick->hwdata->fresh = SDL_FALSE;
1360     }
1361 
1362     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1363         len /= sizeof(events[0]);
1364         for (i = 0; i < len; ++i) {
1365             code = events[i].code;
1366 
1367             /* If the kernel sent a SYN_DROPPED, we are supposed to ignore the
1368                rest of the packet (the end of it signified by a SYN_REPORT) */
1369             if ( joystick->hwdata->recovering_from_dropped &&
1370                  ((events[i].type != EV_SYN) || (code != SYN_REPORT)) ) {
1371                 continue;
1372             }
1373 
1374             switch (events[i].type) {
1375             case EV_KEY:
1376                 SDL_PrivateJoystickButton(joystick,
1377                                           joystick->hwdata->key_map[code],
1378                                           events[i].value);
1379                 break;
1380             case EV_ABS:
1381                 switch (code) {
1382                 case ABS_HAT0X:
1383                 case ABS_HAT0Y:
1384                 case ABS_HAT1X:
1385                 case ABS_HAT1Y:
1386                 case ABS_HAT2X:
1387                 case ABS_HAT2Y:
1388                 case ABS_HAT3X:
1389                 case ABS_HAT3Y:
1390                     code -= ABS_HAT0X;
1391                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
1392                     break;
1393                 default:
1394                     events[i].value = AxisCorrect(joystick, code, events[i].value);
1395                     SDL_PrivateJoystickAxis(joystick,
1396                                             joystick->hwdata->abs_map[code],
1397                                             events[i].value);
1398                     break;
1399                 }
1400                 break;
1401             case EV_REL:
1402                 switch (code) {
1403                 case REL_X:
1404                 case REL_Y:
1405                     code -= REL_X;
1406                     HandleBall(joystick, code / 2, code % 2, events[i].value);
1407                     break;
1408                 default:
1409                     break;
1410                 }
1411                 break;
1412             case EV_SYN:
1413                 switch (code) {
1414                 case SYN_DROPPED :
1415 #ifdef DEBUG_INPUT_EVENTS
1416                     SDL_Log("Event SYN_DROPPED detected\n");
1417 #endif
1418                     joystick->hwdata->recovering_from_dropped = SDL_TRUE;
1419                     break;
1420                 case SYN_REPORT :
1421                     if (joystick->hwdata->recovering_from_dropped) {
1422                         joystick->hwdata->recovering_from_dropped = SDL_FALSE;
1423                         PollAllValues(joystick);  /* try to sync up to current state now */
1424                     }
1425                     break;
1426                 default:
1427                     break;
1428                 }
1429             default:
1430                 break;
1431             }
1432         }
1433     }
1434 
1435     if (errno == ENODEV) {
1436         /* We have to wait until the JoystickDetect callback to remove this */
1437         joystick->hwdata->gone = SDL_TRUE;
1438     }
1439 }
1440 
1441 static void
HandleClassicEvents(SDL_Joystick * joystick)1442 HandleClassicEvents(SDL_Joystick *joystick)
1443 {
1444     struct js_event events[32];
1445     int i, len, code;
1446 
1447     joystick->hwdata->fresh = SDL_FALSE;
1448     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1449         len /= sizeof(events[0]);
1450         for (i = 0; i < len; ++i) {
1451             switch (events[i].type) {
1452             case JS_EVENT_BUTTON:
1453                 code = joystick->hwdata->key_pam[events[i].number];
1454                 SDL_PrivateJoystickButton(joystick,
1455                                           joystick->hwdata->key_map[code],
1456                                           events[i].value);
1457                 break;
1458             case JS_EVENT_AXIS:
1459                 code = joystick->hwdata->abs_pam[events[i].number];
1460                 switch (code) {
1461                 case ABS_HAT0X:
1462                 case ABS_HAT0Y:
1463                 case ABS_HAT1X:
1464                 case ABS_HAT1Y:
1465                 case ABS_HAT2X:
1466                 case ABS_HAT2Y:
1467                 case ABS_HAT3X:
1468                 case ABS_HAT3Y:
1469                     code -= ABS_HAT0X;
1470                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
1471                     break;
1472                 default:
1473                     SDL_PrivateJoystickAxis(joystick,
1474                                             joystick->hwdata->abs_map[code],
1475                                             events[i].value);
1476                     break;
1477                 }
1478             }
1479         }
1480     }
1481 }
1482 
1483 static void
LINUX_JoystickUpdate(SDL_Joystick * joystick)1484 LINUX_JoystickUpdate(SDL_Joystick *joystick)
1485 {
1486     int i;
1487 
1488     if (joystick->hwdata->m_bSteamController) {
1489         SDL_UpdateSteamController(joystick);
1490         return;
1491     }
1492 
1493     if (joystick->hwdata->classic) {
1494         HandleClassicEvents(joystick);
1495     } else {
1496         HandleInputEvents(joystick);
1497     }
1498 
1499     /* Deliver ball motion updates */
1500     for (i = 0; i < joystick->nballs; ++i) {
1501         int xrel, yrel;
1502 
1503         xrel = joystick->hwdata->balls[i].axis[0];
1504         yrel = joystick->hwdata->balls[i].axis[1];
1505         if (xrel || yrel) {
1506             joystick->hwdata->balls[i].axis[0] = 0;
1507             joystick->hwdata->balls[i].axis[1] = 0;
1508             SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
1509         }
1510     }
1511 }
1512 
1513 /* Function to close a joystick after use */
1514 static void
LINUX_JoystickClose(SDL_Joystick * joystick)1515 LINUX_JoystickClose(SDL_Joystick *joystick)
1516 {
1517     if (joystick->hwdata) {
1518         if (joystick->hwdata->effect.id >= 0) {
1519             ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id);
1520             joystick->hwdata->effect.id = -1;
1521         }
1522         if (joystick->hwdata->fd >= 0) {
1523             close(joystick->hwdata->fd);
1524         }
1525         if (joystick->hwdata->item) {
1526             joystick->hwdata->item->hwdata = NULL;
1527         }
1528         SDL_free(joystick->hwdata->key_pam);
1529         SDL_free(joystick->hwdata->abs_pam);
1530         SDL_free(joystick->hwdata->hats);
1531         SDL_free(joystick->hwdata->balls);
1532         SDL_free(joystick->hwdata->fname);
1533         SDL_free(joystick->hwdata);
1534     }
1535 }
1536 
1537 /* Function to perform any system-specific joystick related cleanup */
1538 static void
LINUX_JoystickQuit(void)1539 LINUX_JoystickQuit(void)
1540 {
1541     SDL_joylist_item *item = NULL;
1542     SDL_joylist_item *next = NULL;
1543 
1544     if (inotify_fd >= 0) {
1545         close(inotify_fd);
1546         inotify_fd = -1;
1547     }
1548 
1549     for (item = SDL_joylist; item; item = next) {
1550         next = item->next;
1551         FreeJoylistItem(item);
1552     }
1553 
1554     SDL_joylist = SDL_joylist_tail = NULL;
1555 
1556     numjoysticks = 0;
1557 
1558 #if SDL_USE_LIBUDEV
1559     if (enumeration_method == ENUMERATION_LIBUDEV) {
1560         SDL_UDEV_DelCallback(joystick_udev_callback);
1561         SDL_UDEV_Quit();
1562     }
1563 #endif
1564 
1565     SDL_QuitSteamControllers();
1566 }
1567 
1568 /*
1569    This is based on the Linux Gamepad Specification
1570    available at: https://www.kernel.org/doc/html/v4.15/input/gamepad.html
1571  */
1572 static SDL_bool
LINUX_JoystickGetGamepadMapping(int device_index,SDL_GamepadMapping * out)1573 LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
1574 {
1575     SDL_Joystick *joystick;
1576     SDL_joylist_item *item = JoystickByDevIndex(device_index);
1577 
1578     if (item->mapping) {
1579         SDL_memcpy(out, item->mapping, sizeof(*out));
1580         return SDL_TRUE;
1581     }
1582 
1583     /* We temporarily open the device to check how it's configured. Make
1584        a fake SDL_Joystick object to do so. */
1585     joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
1586     if (joystick == NULL) {
1587         SDL_OutOfMemory();
1588         return SDL_FALSE;
1589     }
1590     SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
1591 
1592     joystick->hwdata = (struct joystick_hwdata *)
1593         SDL_calloc(1, sizeof(*joystick->hwdata));
1594     if (joystick->hwdata == NULL) {
1595         SDL_free(joystick);
1596         SDL_OutOfMemory();
1597         return SDL_FALSE;
1598     }
1599 
1600     if (PrepareJoystickHwdata(joystick, item) == -1) {
1601         SDL_free(joystick->hwdata);
1602         SDL_free(joystick);
1603         return SDL_FALSE;  /* SDL_SetError will already have been called */
1604     }
1605 
1606     /* don't assign `item->hwdata` so it's not in any global state. */
1607 
1608     /* it is now safe to call LINUX_JoystickClose on this fake joystick. */
1609 
1610     if (!joystick->hwdata->has_key[BTN_GAMEPAD]) {
1611         /* Not a gamepad according to the specs. */
1612         LINUX_JoystickClose(joystick);
1613         SDL_free(joystick);
1614         return SDL_FALSE;
1615     }
1616 
1617     /* We have a gamepad, start filling out the mappings */
1618 
1619     if (joystick->hwdata->has_key[BTN_A]) {
1620         out->a.kind = EMappingKind_Button;
1621         out->a.target = joystick->hwdata->key_map[BTN_A];
1622     }
1623 
1624     if (joystick->hwdata->has_key[BTN_B]) {
1625         out->b.kind = EMappingKind_Button;
1626         out->b.target = joystick->hwdata->key_map[BTN_B];
1627     }
1628 
1629     /* Xbox controllers use BTN_X and BTN_Y, and PS4 controllers use BTN_WEST and BTN_NORTH */
1630     if (SDL_JoystickGetVendor(joystick) == USB_VENDOR_SONY) {
1631         if (joystick->hwdata->has_key[BTN_WEST]) {
1632             out->x.kind = EMappingKind_Button;
1633             out->x.target = joystick->hwdata->key_map[BTN_WEST];
1634         }
1635 
1636         if (joystick->hwdata->has_key[BTN_NORTH]) {
1637             out->y.kind = EMappingKind_Button;
1638             out->y.target = joystick->hwdata->key_map[BTN_NORTH];
1639         }
1640     } else {
1641         if (joystick->hwdata->has_key[BTN_X]) {
1642             out->x.kind = EMappingKind_Button;
1643             out->x.target = joystick->hwdata->key_map[BTN_X];
1644         }
1645 
1646         if (joystick->hwdata->has_key[BTN_Y]) {
1647             out->y.kind = EMappingKind_Button;
1648             out->y.target = joystick->hwdata->key_map[BTN_Y];
1649         }
1650     }
1651 
1652     if (joystick->hwdata->has_key[BTN_SELECT]) {
1653         out->back.kind = EMappingKind_Button;
1654         out->back.target = joystick->hwdata->key_map[BTN_SELECT];
1655     }
1656 
1657     if (joystick->hwdata->has_key[BTN_START]) {
1658         out->start.kind = EMappingKind_Button;
1659         out->start.target = joystick->hwdata->key_map[BTN_START];
1660     }
1661 
1662     if (joystick->hwdata->has_key[BTN_THUMBL]) {
1663         out->leftstick.kind = EMappingKind_Button;
1664         out->leftstick.target = joystick->hwdata->key_map[BTN_THUMBL];
1665     }
1666 
1667     if (joystick->hwdata->has_key[BTN_THUMBR]) {
1668         out->rightstick.kind = EMappingKind_Button;
1669         out->rightstick.target = joystick->hwdata->key_map[BTN_THUMBR];
1670     }
1671 
1672     if (joystick->hwdata->has_key[BTN_MODE]) {
1673         out->guide.kind = EMappingKind_Button;
1674         out->guide.target = joystick->hwdata->key_map[BTN_MODE];
1675     }
1676 
1677     /*
1678        According to the specs the D-Pad, the shoulder buttons and the triggers
1679        can be digital, or analog, or both at the same time.
1680      */
1681 
1682     /* Prefer digital shoulder buttons, but settle for analog if missing. */
1683     if (joystick->hwdata->has_key[BTN_TL]) {
1684         out->leftshoulder.kind = EMappingKind_Button;
1685         out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
1686     }
1687 
1688     if (joystick->hwdata->has_key[BTN_TR]) {
1689         out->rightshoulder.kind = EMappingKind_Button;
1690         out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
1691     }
1692 
1693     if (joystick->hwdata->has_hat[1] && /* Check if ABS_HAT1{X, Y} is available. */
1694        (!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
1695         int hat = joystick->hwdata->hats_indices[1] << 4;
1696         out->leftshoulder.kind = EMappingKind_Hat;
1697         out->rightshoulder.kind = EMappingKind_Hat;
1698         out->leftshoulder.target = hat | 0x4;
1699         out->rightshoulder.target = hat | 0x2;
1700     }
1701 
1702     /* Prefer analog triggers, but settle for digital if missing. */
1703     if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
1704         int hat = joystick->hwdata->hats_indices[2] << 4;
1705         out->lefttrigger.kind = EMappingKind_Hat;
1706         out->righttrigger.kind = EMappingKind_Hat;
1707         out->lefttrigger.target = hat | 0x4;
1708         out->righttrigger.target = hat | 0x2;
1709     } else {
1710         if (joystick->hwdata->has_abs[ABS_Z]) {
1711             out->lefttrigger.kind = EMappingKind_Axis;
1712             out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
1713         } else if (joystick->hwdata->has_key[BTN_TL2]) {
1714             out->lefttrigger.kind = EMappingKind_Button;
1715             out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
1716         }
1717 
1718         if (joystick->hwdata->has_abs[ABS_RZ]) {
1719             out->righttrigger.kind = EMappingKind_Axis;
1720             out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
1721         } else if (joystick->hwdata->has_key[BTN_TR2]) {
1722             out->righttrigger.kind = EMappingKind_Button;
1723             out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
1724         }
1725     }
1726 
1727     /* Prefer digital D-Pad, but settle for analog if missing. */
1728     if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
1729         out->dpup.kind = EMappingKind_Button;
1730         out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
1731     }
1732 
1733     if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
1734         out->dpdown.kind = EMappingKind_Button;
1735         out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
1736     }
1737 
1738     if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
1739         out->dpleft.kind = EMappingKind_Button;
1740         out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
1741     }
1742 
1743     if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
1744         out->dpright.kind = EMappingKind_Button;
1745         out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
1746     }
1747 
1748     if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
1749        (!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
1750         !joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
1751        int hat = joystick->hwdata->hats_indices[0] << 4;
1752        out->dpleft.kind = EMappingKind_Hat;
1753        out->dpright.kind = EMappingKind_Hat;
1754        out->dpup.kind = EMappingKind_Hat;
1755        out->dpdown.kind = EMappingKind_Hat;
1756        out->dpleft.target = hat | 0x8;
1757        out->dpright.target = hat | 0x2;
1758        out->dpup.target = hat | 0x1;
1759        out->dpdown.target = hat | 0x4;
1760     }
1761 
1762     if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
1763         out->leftx.kind = EMappingKind_Axis;
1764         out->lefty.kind = EMappingKind_Axis;
1765         out->leftx.target = joystick->hwdata->abs_map[ABS_X];
1766         out->lefty.target = joystick->hwdata->abs_map[ABS_Y];
1767     }
1768 
1769     if (joystick->hwdata->has_abs[ABS_RX] && joystick->hwdata->has_abs[ABS_RY]) {
1770         out->rightx.kind = EMappingKind_Axis;
1771         out->righty.kind = EMappingKind_Axis;
1772         out->rightx.target = joystick->hwdata->abs_map[ABS_RX];
1773         out->righty.target = joystick->hwdata->abs_map[ABS_RY];
1774     }
1775 
1776     LINUX_JoystickClose(joystick);
1777     SDL_free(joystick);
1778 
1779     /* Cache the mapping for later */
1780     item->mapping = (SDL_GamepadMapping *)SDL_malloc(sizeof(*item->mapping));
1781     if (item->mapping) {
1782         SDL_memcpy(item->mapping, out, sizeof(*out));
1783     }
1784 
1785     return SDL_TRUE;
1786 }
1787 
1788 SDL_JoystickDriver SDL_LINUX_JoystickDriver =
1789 {
1790     LINUX_JoystickInit,
1791     LINUX_JoystickGetCount,
1792     LINUX_JoystickDetect,
1793     LINUX_JoystickGetDeviceName,
1794     LINUX_JoystickGetDevicePlayerIndex,
1795     LINUX_JoystickSetDevicePlayerIndex,
1796     LINUX_JoystickGetDeviceGUID,
1797     LINUX_JoystickGetDeviceInstanceID,
1798     LINUX_JoystickOpen,
1799     LINUX_JoystickRumble,
1800     LINUX_JoystickRumbleTriggers,
1801     LINUX_JoystickGetCapabilities,
1802     LINUX_JoystickSetLED,
1803     LINUX_JoystickSendEffect,
1804     LINUX_JoystickSetSensorsEnabled,
1805     LINUX_JoystickUpdate,
1806     LINUX_JoystickClose,
1807     LINUX_JoystickQuit,
1808     LINUX_JoystickGetGamepadMapping
1809 };
1810 
1811 #endif /* SDL_JOYSTICK_LINUX */
1812 
1813 /* vi: set ts=4 sw=4 expandtab: */
1814