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 
510 static int
StrHasPrefix(const char * string,const char * prefix)511 StrHasPrefix(const char *string, const char *prefix)
512 {
513     return (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0);
514 }
515 
516 static int
StrIsInteger(const char * string)517 StrIsInteger(const char *string)
518 {
519     const char *p;
520 
521     if (*string == '\0') {
522         return 0;
523     }
524 
525     for (p = string; *p != '\0'; p++) {
526         if (*p < '0' || *p > '9') {
527             return 0;
528         }
529     }
530 
531     return 1;
532 }
533 
534 static SDL_bool
IsJoystickJSNode(const char * node)535 IsJoystickJSNode(const char *node)
536 {
537     const char *last_slash = SDL_strrchr(node, '/');
538     if (last_slash) {
539         node = last_slash + 1;
540     }
541     return (StrHasPrefix(node, "js") && StrIsInteger(node + 2));
542 }
543 
544 static SDL_bool
IsJoystickEventNode(const char * node)545 IsJoystickEventNode(const char *node)
546 {
547     const char *last_slash = SDL_strrchr(node, '/');
548     if (last_slash) {
549         node = last_slash + 1;
550     }
551     return (StrHasPrefix(node, "event") && StrIsInteger(node + 5));
552 }
553 
554 static SDL_bool
IsJoystickDeviceNode(const char * node)555 IsJoystickDeviceNode(const char *node)
556 {
557     if (SDL_classic_joysticks) {
558         return IsJoystickJSNode(node);
559     } else {
560         return IsJoystickEventNode(node);
561     }
562 }
563 
564 static void
LINUX_InotifyJoystickDetect(void)565 LINUX_InotifyJoystickDetect(void)
566 {
567     union
568     {
569         struct inotify_event event;
570         char storage[4096];
571         char enough_for_inotify[sizeof (struct inotify_event) + NAME_MAX + 1];
572     } buf;
573     ssize_t bytes;
574     size_t remain = 0;
575     size_t len;
576     char path[PATH_MAX];
577 
578     bytes = read(inotify_fd, &buf, sizeof (buf));
579 
580     if (bytes > 0) {
581         remain = (size_t) bytes;
582     }
583 
584     while (remain > 0) {
585         if (buf.event.len > 0) {
586             if (IsJoystickDeviceNode(buf.event.name)) {
587                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name);
588 
589                 if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) {
590                     MaybeAddDevice(path);
591                 }
592                 else if (buf.event.mask & (IN_DELETE | IN_MOVED_FROM)) {
593                     MaybeRemoveDevice(path);
594                 }
595             }
596         }
597 
598         len = sizeof (struct inotify_event) + buf.event.len;
599         remain -= len;
600 
601         if (remain != 0) {
602             SDL_memmove (&buf.storage[0], &buf.storage[len], remain);
603         }
604     }
605 }
606 #endif /* HAVE_INOTIFY */
607 
608 /* Detect devices by reading /dev/input. In the inotify code path we
609  * have to do this the first time, to detect devices that already existed
610  * before we started; in the non-inotify code path we do this repeatedly
611  * (polling). */
612 static int
filter_entries(const struct dirent * entry)613 filter_entries(const struct dirent *entry)
614 {
615     return IsJoystickDeviceNode(entry->d_name);
616 }
617 static int
sort_entries(const struct dirent ** a,const struct dirent ** b)618 sort_entries(const struct dirent **a, const struct dirent **b)
619 {
620     int numA = SDL_atoi((*a)->d_name+5);
621     int numB = SDL_atoi((*b)->d_name+5);
622     return (numA - numB);
623 }
624 static void
LINUX_FallbackJoystickDetect(void)625 LINUX_FallbackJoystickDetect(void)
626 {
627     const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000;  /* Update every 3 seconds */
628     Uint32 now = SDL_GetTicks();
629 
630     if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
631         struct stat sb;
632 
633         /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
634         if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
635             int i, count;
636             struct dirent **entries;
637             char path[PATH_MAX];
638 
639             count = scandir("/dev/input", &entries, filter_entries, sort_entries);
640             for (i = 0; i < count; ++i) {
641                 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
642                 MaybeAddDevice(path);
643 
644                 free(entries[i]); /* This should NOT be SDL_free() */
645             }
646             free(entries); /* This should NOT be SDL_free() */
647 
648             last_input_dir_mtime = sb.st_mtime;
649         }
650 
651         last_joy_detect_time = now;
652     }
653 }
654 
655 static void
LINUX_JoystickDetect(void)656 LINUX_JoystickDetect(void)
657 {
658 #if SDL_USE_LIBUDEV
659     if (enumeration_method == ENUMERATION_LIBUDEV) {
660         SDL_UDEV_Poll();
661     }
662     else
663 #endif
664 #ifdef HAVE_INOTIFY
665     if (inotify_fd >= 0 && last_joy_detect_time != 0) {
666         LINUX_InotifyJoystickDetect();
667     }
668     else
669 #endif
670     {
671         LINUX_FallbackJoystickDetect();
672     }
673 
674     HandlePendingRemovals();
675 
676     SDL_UpdateSteamControllers();
677 }
678 
679 static int
LINUX_JoystickInit(void)680 LINUX_JoystickInit(void)
681 {
682     const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE);
683 
684     SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE);
685 
686 #if SDL_USE_LIBUDEV
687     if (enumeration_method == ENUMERATION_UNSET) {
688         if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
689             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
690                          "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
691             enumeration_method = ENUMERATION_FALLBACK;
692 
693         } else if (access("/.flatpak-info", F_OK) == 0
694                  || access("/run/host/container-manager", F_OK) == 0) {
695             /* Explicitly check `/.flatpak-info` because, for old versions of
696              * Flatpak, this was the only available way to tell if we were in
697              * a Flatpak container. */
698             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
699                          "Container detected, disabling udev integration");
700             enumeration_method = ENUMERATION_FALLBACK;
701 
702         } else {
703             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
704                          "Using udev for joystick device discovery");
705             enumeration_method = ENUMERATION_LIBUDEV;
706         }
707     }
708 #endif
709 
710     /* First see if the user specified one or more joysticks to use */
711     if (devices != NULL) {
712         char *envcopy, *envpath, *delim;
713         envcopy = SDL_strdup(devices);
714         envpath = envcopy;
715         while (envpath != NULL) {
716             delim = SDL_strchr(envpath, ':');
717             if (delim != NULL) {
718                 *delim++ = '\0';
719             }
720             MaybeAddDevice(envpath);
721             envpath = delim;
722         }
723         SDL_free(envcopy);
724     }
725 
726     SDL_InitSteamControllers(SteamControllerConnectedCallback,
727                              SteamControllerDisconnectedCallback);
728 
729     /* Force immediate joystick detection if using fallback */
730     last_joy_detect_time = 0;
731     last_input_dir_mtime = 0;
732 
733     /* Manually scan first, since we sort by device number and udev doesn't */
734     LINUX_JoystickDetect();
735 
736 #if SDL_USE_LIBUDEV
737     if (enumeration_method == ENUMERATION_LIBUDEV) {
738         if (SDL_UDEV_Init() < 0) {
739             return SDL_SetError("Could not initialize UDEV");
740         }
741 
742         /* Set up the udev callback */
743         if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
744             SDL_UDEV_Quit();
745             return SDL_SetError("Could not set up joystick <-> udev callback");
746         }
747 
748         /* Force a scan to build the initial device list */
749         SDL_UDEV_Scan();
750     }
751     else
752 #endif
753     {
754 #if defined(HAVE_INOTIFY)
755         inotify_fd = SDL_inotify_init1();
756 
757         if (inotify_fd < 0) {
758             SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
759                         "Unable to initialize inotify, falling back to polling: %s",
760                         strerror (errno));
761         } else {
762             /* We need to watch for attribute changes in addition to
763              * creation, because when a device is first created, it has
764              * permissions that we can't read. When udev chmods it to
765              * something that we maybe *can* read, we'll get an
766              * IN_ATTRIB event to tell us. */
767             if (inotify_add_watch(inotify_fd, "/dev/input",
768                                   IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
769                 close(inotify_fd);
770                 inotify_fd = -1;
771                 SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
772                             "Unable to add inotify watch, falling back to polling: %s",
773                             strerror (errno));
774             }
775         }
776 #endif /* HAVE_INOTIFY */
777     }
778 
779     return 0;
780 }
781 
782 static int
LINUX_JoystickGetCount(void)783 LINUX_JoystickGetCount(void)
784 {
785     return numjoysticks;
786 }
787 
788 static SDL_joylist_item *
JoystickByDevIndex(int device_index)789 JoystickByDevIndex(int device_index)
790 {
791     SDL_joylist_item *item = SDL_joylist;
792 
793     if ((device_index < 0) || (device_index >= numjoysticks)) {
794         return NULL;
795     }
796 
797     while (device_index > 0) {
798         SDL_assert(item != NULL);
799         device_index--;
800         item = item->next;
801     }
802 
803     return item;
804 }
805 
806 /* Function to get the device-dependent name of a joystick */
807 static const char *
LINUX_JoystickGetDeviceName(int device_index)808 LINUX_JoystickGetDeviceName(int device_index)
809 {
810     return JoystickByDevIndex(device_index)->name;
811 }
812 
813 static int
LINUX_JoystickGetDevicePlayerIndex(int device_index)814 LINUX_JoystickGetDevicePlayerIndex(int device_index)
815 {
816     return -1;
817 }
818 
819 static void
LINUX_JoystickSetDevicePlayerIndex(int device_index,int player_index)820 LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
821 {
822 }
823 
824 static SDL_JoystickGUID
LINUX_JoystickGetDeviceGUID(int device_index)825 LINUX_JoystickGetDeviceGUID( int device_index )
826 {
827     return JoystickByDevIndex(device_index)->guid;
828 }
829 
830 /* Function to perform the mapping from device index to the instance id for this index */
831 static SDL_JoystickID
LINUX_JoystickGetDeviceInstanceID(int device_index)832 LINUX_JoystickGetDeviceInstanceID(int device_index)
833 {
834     return JoystickByDevIndex(device_index)->device_instance;
835 }
836 
837 static int
allocate_hatdata(SDL_Joystick * joystick)838 allocate_hatdata(SDL_Joystick *joystick)
839 {
840     int i;
841 
842     joystick->hwdata->hats =
843         (struct hwdata_hat *) SDL_malloc(joystick->nhats *
844                                          sizeof(struct hwdata_hat));
845     if (joystick->hwdata->hats == NULL) {
846         return (-1);
847     }
848     for (i = 0; i < joystick->nhats; ++i) {
849         joystick->hwdata->hats[i].axis[0] = 1;
850         joystick->hwdata->hats[i].axis[1] = 1;
851     }
852     return (0);
853 }
854 
855 static int
allocate_balldata(SDL_Joystick * joystick)856 allocate_balldata(SDL_Joystick *joystick)
857 {
858     int i;
859 
860     joystick->hwdata->balls =
861         (struct hwdata_ball *) SDL_malloc(joystick->nballs *
862                                           sizeof(struct hwdata_ball));
863     if (joystick->hwdata->balls == NULL) {
864         return (-1);
865     }
866     for (i = 0; i < joystick->nballs; ++i) {
867         joystick->hwdata->balls[i].axis[0] = 0;
868         joystick->hwdata->balls[i].axis[1] = 0;
869     }
870     return (0);
871 }
872 
873 static void
ConfigJoystick(SDL_Joystick * joystick,int fd)874 ConfigJoystick(SDL_Joystick *joystick, int fd)
875 {
876     int i, t;
877     unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
878     unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
879     unsigned long relbit[NBITS(REL_MAX)] = { 0 };
880     unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
881     Uint8 key_pam_size, abs_pam_size;
882     SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE);
883 
884     /* See if this device uses the new unified event API */
885     if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
886         (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
887         (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
888 
889         /* Get the number of buttons, axes, and other thingamajigs */
890         for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
891             if (test_bit(i, keybit)) {
892 #ifdef DEBUG_INPUT_EVENTS
893                 SDL_Log("Joystick has button: 0x%x\n", i);
894 #endif
895                 joystick->hwdata->key_map[i] = joystick->nbuttons;
896                 joystick->hwdata->has_key[i] = SDL_TRUE;
897                 ++joystick->nbuttons;
898             }
899         }
900         for (i = 0; i < BTN_JOYSTICK; ++i) {
901             if (test_bit(i, keybit)) {
902 #ifdef DEBUG_INPUT_EVENTS
903                 SDL_Log("Joystick has button: 0x%x\n", i);
904 #endif
905                 joystick->hwdata->key_map[i] = joystick->nbuttons;
906                 joystick->hwdata->has_key[i] = SDL_TRUE;
907                 ++joystick->nbuttons;
908             }
909         }
910         for (i = 0; i < ABS_MAX; ++i) {
911             /* Skip hats */
912             if (i == ABS_HAT0X) {
913                 i = ABS_HAT3Y;
914                 continue;
915             }
916             if (test_bit(i, absbit)) {
917                 struct input_absinfo absinfo;
918                 struct axis_correct *correct = &joystick->hwdata->abs_correct[i];
919 
920                 if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
921                     continue;
922                 }
923 #ifdef DEBUG_INPUT_EVENTS
924                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
925                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
926                         absinfo.value, absinfo.minimum, absinfo.maximum,
927                         absinfo.fuzz, absinfo.flat);
928 #endif /* DEBUG_INPUT_EVENTS */
929                 joystick->hwdata->abs_map[i] = joystick->naxes;
930                 joystick->hwdata->has_abs[i] = SDL_TRUE;
931 
932                 correct->minimum = absinfo.minimum;
933                 correct->maximum = absinfo.maximum;
934                 if (correct->minimum != correct->maximum) {
935                     if (use_deadzones) {
936                         correct->use_deadzones = SDL_TRUE;
937                         correct->coef[0] = (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
938                         correct->coef[1] = (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
939                         t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
940                         if (t != 0) {
941                             correct->coef[2] = (1 << 28) / t;
942                         } else {
943                             correct->coef[2] = 0;
944                         }
945                     } else {
946                         float value_range = (correct->maximum - correct->minimum);
947                         float output_range = (SDL_JOYSTICK_AXIS_MAX - SDL_JOYSTICK_AXIS_MIN);
948 
949                         correct->scale = (output_range / value_range);
950                     }
951                 }
952                 ++joystick->naxes;
953             }
954         }
955         for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
956             if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
957                 struct input_absinfo absinfo;
958                 int hat_index = (i - ABS_HAT0X) / 2;
959 
960                 if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
961                     continue;
962                 }
963 #ifdef DEBUG_INPUT_EVENTS
964                 SDL_Log("Joystick has hat %d\n", hat_index);
965                 SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
966                         absinfo.value, absinfo.minimum, absinfo.maximum,
967                         absinfo.fuzz, absinfo.flat);
968 #endif /* DEBUG_INPUT_EVENTS */
969                 joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
970                 joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
971             }
972         }
973         if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
974             ++joystick->nballs;
975         }
976 
977     } else if ((ioctl(fd, JSIOCGBUTTONS, &key_pam_size, sizeof(key_pam_size)) >= 0) &&
978                (ioctl(fd, JSIOCGAXES, &abs_pam_size, sizeof(abs_pam_size)) >= 0)) {
979         size_t len;
980 
981         joystick->hwdata->classic = SDL_TRUE;
982 
983         len = (KEY_MAX - BTN_MISC + 1) * sizeof(*joystick->hwdata->key_pam);
984         joystick->hwdata->key_pam = (Uint16 *)SDL_calloc(1, len);
985         if (joystick->hwdata->key_pam) {
986             if (ioctl(fd, JSIOCGBTNMAP, joystick->hwdata->key_pam, len) < 0) {
987                 SDL_free(joystick->hwdata->key_pam);
988                 joystick->hwdata->key_pam = NULL;
989                 key_pam_size = 0;
990             }
991         } else {
992             key_pam_size = 0;
993         }
994         for (i = 0; i < key_pam_size; ++i) {
995             Uint16 code = joystick->hwdata->key_pam[i];
996 #ifdef DEBUG_INPUT_EVENTS
997             SDL_Log("Joystick has button: 0x%x\n", code);
998 #endif
999             joystick->hwdata->key_map[code] = joystick->nbuttons;
1000             joystick->hwdata->has_key[code] = SDL_TRUE;
1001             ++joystick->nbuttons;
1002         }
1003 
1004         len = ABS_CNT * sizeof(*joystick->hwdata->abs_pam);
1005         joystick->hwdata->abs_pam = (Uint8 *)SDL_calloc(1, len);
1006         if (joystick->hwdata->abs_pam) {
1007             if (ioctl(fd, JSIOCGAXMAP, joystick->hwdata->abs_pam, len) < 0) {
1008                 SDL_free(joystick->hwdata->abs_pam);
1009                 joystick->hwdata->abs_pam = NULL;
1010                 abs_pam_size = 0;
1011             }
1012         } else {
1013             abs_pam_size = 0;
1014         }
1015         for (i = 0; i < abs_pam_size; ++i) {
1016             Uint8 code = joystick->hwdata->abs_pam[i];
1017 
1018             if (code >= ABS_HAT0X && code <= ABS_HAT3Y) {
1019                 int hat_index = (code - ABS_HAT0X) / 2;
1020                 if (!joystick->hwdata->has_hat[hat_index]) {
1021 #ifdef DEBUG_INPUT_EVENTS
1022                     SDL_Log("Joystick has hat %d\n", hat_index);
1023 #endif
1024                     joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
1025                     joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
1026                 }
1027             } else {
1028 #ifdef DEBUG_INPUT_EVENTS
1029                 SDL_Log("Joystick has absolute axis: 0x%.2x\n", code);
1030 #endif
1031                 joystick->hwdata->abs_map[code] = joystick->naxes;
1032                 joystick->hwdata->has_abs[code] = SDL_TRUE;
1033                 ++joystick->naxes;
1034             }
1035         }
1036     }
1037 
1038     /* Allocate data to keep track of these thingamajigs */
1039     if (joystick->nhats > 0) {
1040         if (allocate_hatdata(joystick) < 0) {
1041             joystick->nhats = 0;
1042         }
1043     }
1044     if (joystick->nballs > 0) {
1045         if (allocate_balldata(joystick) < 0) {
1046             joystick->nballs = 0;
1047         }
1048     }
1049 
1050     if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) {
1051         if (test_bit(FF_RUMBLE, ffbit)) {
1052             joystick->hwdata->ff_rumble = SDL_TRUE;
1053         }
1054         if (test_bit(FF_SINE, ffbit)) {
1055             joystick->hwdata->ff_sine = SDL_TRUE;
1056         }
1057     }
1058 }
1059 
1060 
1061 /* This is used to do the heavy lifting for LINUX_JoystickOpen and
1062    also LINUX_JoystickGetGamepadMapping, so we can query the hardware
1063    without adding an opened SDL_Joystick object to the system.
1064    This expects `joystick->hwdata` to be allocated and will not free it
1065    on error. Returns -1 on error, 0 on success. */
1066 static int
PrepareJoystickHwdata(SDL_Joystick * joystick,SDL_joylist_item * item)1067 PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item)
1068 {
1069     joystick->hwdata->item = item;
1070     joystick->hwdata->guid = item->guid;
1071     joystick->hwdata->effect.id = -1;
1072     joystick->hwdata->m_bSteamController = item->m_bSteamController;
1073     SDL_memset(joystick->hwdata->key_map, 0xFF, sizeof(joystick->hwdata->key_map));
1074     SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
1075 
1076     if (item->m_bSteamController) {
1077         joystick->hwdata->fd = -1;
1078         SDL_GetSteamControllerInputs(&joystick->nbuttons,
1079                                      &joystick->naxes,
1080                                      &joystick->nhats);
1081     } else {
1082         /* Try read-write first, so we can do rumble */
1083         int fd = open(item->path, O_RDWR | O_CLOEXEC, 0);
1084         if (fd < 0) {
1085             /* Try read-only again, at least we'll get events in this case */
1086             fd = open(item->path, O_RDONLY | O_CLOEXEC, 0);
1087         }
1088         if (fd < 0) {
1089             return SDL_SetError("Unable to open %s", item->path);
1090         }
1091 
1092         joystick->hwdata->fd = fd;
1093         joystick->hwdata->fname = SDL_strdup(item->path);
1094         if (joystick->hwdata->fname == NULL) {
1095             close(fd);
1096             return SDL_OutOfMemory();
1097         }
1098 
1099         /* Set the joystick to non-blocking read mode */
1100         fcntl(fd, F_SETFL, O_NONBLOCK);
1101 
1102         /* Get the number of buttons and axes on the joystick */
1103         ConfigJoystick(joystick, fd);
1104     }
1105     return 0;
1106 }
1107 
1108 
1109 /* Function to open a joystick for use.
1110    The joystick to open is specified by the device index.
1111    This should fill the nbuttons and naxes fields of the joystick structure.
1112    It returns 0, or -1 if there is an error.
1113  */
1114 static int
LINUX_JoystickOpen(SDL_Joystick * joystick,int device_index)1115 LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index)
1116 {
1117     SDL_joylist_item *item = JoystickByDevIndex(device_index);
1118 
1119     if (item == NULL) {
1120         return SDL_SetError("No such device");
1121     }
1122 
1123     joystick->instance_id = item->device_instance;
1124     joystick->hwdata = (struct joystick_hwdata *)
1125         SDL_calloc(1, sizeof(*joystick->hwdata));
1126     if (joystick->hwdata == NULL) {
1127         return SDL_OutOfMemory();
1128     }
1129 
1130     if (PrepareJoystickHwdata(joystick, item) == -1) {
1131         SDL_free(joystick->hwdata);
1132         joystick->hwdata = NULL;
1133         return -1;  /* SDL_SetError will already have been called */
1134     }
1135 
1136     SDL_assert(item->hwdata == NULL);
1137     item->hwdata = joystick->hwdata;
1138 
1139     /* mark joystick as fresh and ready */
1140     joystick->hwdata->fresh = SDL_TRUE;
1141 
1142     return 0;
1143 }
1144 
1145 static int
LINUX_JoystickRumble(SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)1146 LINUX_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1147 {
1148     struct input_event event;
1149 
1150     if (joystick->hwdata->ff_rumble) {
1151         struct ff_effect *effect = &joystick->hwdata->effect;
1152 
1153         effect->type = FF_RUMBLE;
1154         effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
1155         effect->u.rumble.strong_magnitude = low_frequency_rumble;
1156         effect->u.rumble.weak_magnitude = high_frequency_rumble;
1157     } else if (joystick->hwdata->ff_sine) {
1158         /* Scale and average the two rumble strengths */
1159         Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
1160         struct ff_effect *effect = &joystick->hwdata->effect;
1161 
1162         effect->type = FF_PERIODIC;
1163         effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
1164         effect->u.periodic.waveform = FF_SINE;
1165         effect->u.periodic.magnitude = magnitude;
1166     } else {
1167         return SDL_Unsupported();
1168     }
1169 
1170     if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
1171         /* The kernel may have lost this effect, try to allocate a new one */
1172         joystick->hwdata->effect.id = -1;
1173         if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
1174             return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
1175         }
1176     }
1177 
1178     event.type = EV_FF;
1179     event.code = joystick->hwdata->effect.id;
1180     event.value = 1;
1181     if (write(joystick->hwdata->fd, &event, sizeof(event)) < 0) {
1182         return SDL_SetError("Couldn't start rumble effect: %s", strerror(errno));
1183     }
1184     return 0;
1185 }
1186 
1187 static int
LINUX_JoystickRumbleTriggers(SDL_Joystick * joystick,Uint16 left_rumble,Uint16 right_rumble)1188 LINUX_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
1189 {
1190     return SDL_Unsupported();
1191 }
1192 
1193 static Uint32
LINUX_JoystickGetCapabilities(SDL_Joystick * joystick)1194 LINUX_JoystickGetCapabilities(SDL_Joystick *joystick)
1195 {
1196     Uint32 result = 0;
1197 
1198     if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) {
1199         result |= SDL_JOYCAP_RUMBLE;
1200     }
1201 
1202     return result;
1203 }
1204 
1205 static int
LINUX_JoystickSetLED(SDL_Joystick * joystick,Uint8 red,Uint8 green,Uint8 blue)1206 LINUX_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
1207 {
1208     return SDL_Unsupported();
1209 }
1210 
1211 static int
LINUX_JoystickSendEffect(SDL_Joystick * joystick,const void * data,int size)1212 LINUX_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
1213 {
1214     return SDL_Unsupported();
1215 }
1216 
1217 static int
LINUX_JoystickSetSensorsEnabled(SDL_Joystick * joystick,SDL_bool enabled)1218 LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
1219 {
1220     return SDL_Unsupported();
1221 }
1222 
1223 static void
HandleHat(SDL_Joystick * stick,Uint8 hat,int axis,int value)1224 HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
1225 {
1226     struct hwdata_hat *the_hat;
1227     const Uint8 position_map[3][3] = {
1228         {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
1229         {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
1230         {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
1231     };
1232 
1233     the_hat = &stick->hwdata->hats[hat];
1234     if (value < 0) {
1235         value = 0;
1236     } else if (value == 0) {
1237         value = 1;
1238     } else if (value > 0) {
1239         value = 2;
1240     }
1241     if (value != the_hat->axis[axis]) {
1242         the_hat->axis[axis] = value;
1243         SDL_PrivateJoystickHat(stick, hat,
1244                                position_map[the_hat->axis[1]][the_hat->axis[0]]);
1245     }
1246 }
1247 
1248 static void
HandleBall(SDL_Joystick * stick,Uint8 ball,int axis,int value)1249 HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
1250 {
1251     stick->hwdata->balls[ball].axis[axis] += value;
1252 }
1253 
1254 
1255 static int
AxisCorrect(SDL_Joystick * joystick,int which,int value)1256 AxisCorrect(SDL_Joystick *joystick, int which, int value)
1257 {
1258     struct axis_correct *correct;
1259 
1260     correct = &joystick->hwdata->abs_correct[which];
1261     if (correct->minimum != correct->maximum) {
1262         if (correct->use_deadzones) {
1263             value *= 2;
1264             if (value > correct->coef[0]) {
1265                 if (value < correct->coef[1]) {
1266                     return 0;
1267                 }
1268                 value -= correct->coef[1];
1269             } else {
1270                 value -= correct->coef[0];
1271             }
1272             value *= correct->coef[2];
1273             value >>= 13;
1274         } else {
1275             value = (int)SDL_floorf((value - correct->minimum) * correct->scale + SDL_JOYSTICK_AXIS_MIN + 0.5f);
1276         }
1277     }
1278 
1279     /* Clamp and return */
1280     if (value < SDL_JOYSTICK_AXIS_MIN) {
1281         return SDL_JOYSTICK_AXIS_MIN;
1282     }
1283     if (value > SDL_JOYSTICK_AXIS_MAX) {
1284         return SDL_JOYSTICK_AXIS_MAX;
1285     }
1286     return value;
1287 }
1288 
1289 static void
PollAllValues(SDL_Joystick * joystick)1290 PollAllValues(SDL_Joystick *joystick)
1291 {
1292     struct input_absinfo absinfo;
1293     unsigned long keyinfo[NBITS(KEY_MAX)];
1294     int i;
1295 
1296     /* Poll all axis */
1297     for (i = ABS_X; i < ABS_MAX; i++) {
1298         if (i == ABS_HAT0X) {  /* we handle hats in the next loop, skip them for now. */
1299             i = ABS_HAT3Y;
1300             continue;
1301         }
1302         if (joystick->hwdata->has_abs[i]) {
1303             if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
1304                 absinfo.value = AxisCorrect(joystick, i, absinfo.value);
1305 
1306 #ifdef DEBUG_INPUT_EVENTS
1307                 SDL_Log("Joystick : Re-read Axis %d (%d) val= %d\n",
1308                     joystick->hwdata->abs_map[i], i, absinfo.value);
1309 #endif
1310                 SDL_PrivateJoystickAxis(joystick,
1311                         joystick->hwdata->abs_map[i],
1312                         absinfo.value);
1313             }
1314         }
1315     }
1316 
1317     /* Poll all hats */
1318     for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
1319         const int baseaxis = i - ABS_HAT0X;
1320         const int hatidx = baseaxis / 2;
1321         SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
1322         if (joystick->hwdata->has_hat[hatidx]) {
1323             if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
1324                 const int hataxis = baseaxis % 2;
1325                 HandleHat(joystick, joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
1326             }
1327         }
1328     }
1329 
1330     /* Poll all buttons */
1331     SDL_zeroa(keyinfo);
1332     if (ioctl(joystick->hwdata->fd, EVIOCGKEY(sizeof (keyinfo)), keyinfo) >= 0) {
1333         for (i = 0; i < KEY_MAX; i++) {
1334             if (joystick->hwdata->has_key[i]) {
1335                 const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED;
1336 #ifdef DEBUG_INPUT_EVENTS
1337                 SDL_Log("Joystick : Re-read Button %d (%d) val= %d\n",
1338                     joystick->hwdata->key_map[i], i, value);
1339 #endif
1340                 SDL_PrivateJoystickButton(joystick,
1341                         joystick->hwdata->key_map[i], value);
1342             }
1343         }
1344     }
1345 
1346     /* Joyballs are relative input, so there's no poll state. Events only! */
1347 }
1348 
1349 static void
HandleInputEvents(SDL_Joystick * joystick)1350 HandleInputEvents(SDL_Joystick *joystick)
1351 {
1352     struct input_event events[32];
1353     int i, len, code;
1354 
1355     if (joystick->hwdata->fresh) {
1356         PollAllValues(joystick);
1357         joystick->hwdata->fresh = SDL_FALSE;
1358     }
1359 
1360     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1361         len /= sizeof(events[0]);
1362         for (i = 0; i < len; ++i) {
1363             code = events[i].code;
1364 
1365             /* If the kernel sent a SYN_DROPPED, we are supposed to ignore the
1366                rest of the packet (the end of it signified by a SYN_REPORT) */
1367             if ( joystick->hwdata->recovering_from_dropped &&
1368                  ((events[i].type != EV_SYN) || (code != SYN_REPORT)) ) {
1369                 continue;
1370             }
1371 
1372             switch (events[i].type) {
1373             case EV_KEY:
1374                 SDL_PrivateJoystickButton(joystick,
1375                                           joystick->hwdata->key_map[code],
1376                                           events[i].value);
1377                 break;
1378             case EV_ABS:
1379                 switch (code) {
1380                 case ABS_HAT0X:
1381                 case ABS_HAT0Y:
1382                 case ABS_HAT1X:
1383                 case ABS_HAT1Y:
1384                 case ABS_HAT2X:
1385                 case ABS_HAT2Y:
1386                 case ABS_HAT3X:
1387                 case ABS_HAT3Y:
1388                     code -= ABS_HAT0X;
1389                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
1390                     break;
1391                 default:
1392                     events[i].value = AxisCorrect(joystick, code, events[i].value);
1393                     SDL_PrivateJoystickAxis(joystick,
1394                                             joystick->hwdata->abs_map[code],
1395                                             events[i].value);
1396                     break;
1397                 }
1398                 break;
1399             case EV_REL:
1400                 switch (code) {
1401                 case REL_X:
1402                 case REL_Y:
1403                     code -= REL_X;
1404                     HandleBall(joystick, code / 2, code % 2, events[i].value);
1405                     break;
1406                 default:
1407                     break;
1408                 }
1409                 break;
1410             case EV_SYN:
1411                 switch (code) {
1412                 case SYN_DROPPED :
1413 #ifdef DEBUG_INPUT_EVENTS
1414                     SDL_Log("Event SYN_DROPPED detected\n");
1415 #endif
1416                     joystick->hwdata->recovering_from_dropped = SDL_TRUE;
1417                     break;
1418                 case SYN_REPORT :
1419                     if (joystick->hwdata->recovering_from_dropped) {
1420                         joystick->hwdata->recovering_from_dropped = SDL_FALSE;
1421                         PollAllValues(joystick);  /* try to sync up to current state now */
1422                     }
1423                     break;
1424                 default:
1425                     break;
1426                 }
1427             default:
1428                 break;
1429             }
1430         }
1431     }
1432 
1433     if (errno == ENODEV) {
1434         /* We have to wait until the JoystickDetect callback to remove this */
1435         joystick->hwdata->gone = SDL_TRUE;
1436     }
1437 }
1438 
1439 static void
HandleClassicEvents(SDL_Joystick * joystick)1440 HandleClassicEvents(SDL_Joystick *joystick)
1441 {
1442     struct js_event events[32];
1443     int i, len, code;
1444 
1445     joystick->hwdata->fresh = SDL_FALSE;
1446     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1447         len /= sizeof(events[0]);
1448         for (i = 0; i < len; ++i) {
1449             switch (events[i].type) {
1450             case JS_EVENT_BUTTON:
1451                 code = joystick->hwdata->key_pam[events[i].number];
1452                 SDL_PrivateJoystickButton(joystick,
1453                                           joystick->hwdata->key_map[code],
1454                                           events[i].value);
1455                 break;
1456             case JS_EVENT_AXIS:
1457                 code = joystick->hwdata->abs_pam[events[i].number];
1458                 switch (code) {
1459                 case ABS_HAT0X:
1460                 case ABS_HAT0Y:
1461                 case ABS_HAT1X:
1462                 case ABS_HAT1Y:
1463                 case ABS_HAT2X:
1464                 case ABS_HAT2Y:
1465                 case ABS_HAT3X:
1466                 case ABS_HAT3Y:
1467                     code -= ABS_HAT0X;
1468                     HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
1469                     break;
1470                 default:
1471                     SDL_PrivateJoystickAxis(joystick,
1472                                             joystick->hwdata->abs_map[code],
1473                                             events[i].value);
1474                     break;
1475                 }
1476             }
1477         }
1478     }
1479 }
1480 
1481 static void
LINUX_JoystickUpdate(SDL_Joystick * joystick)1482 LINUX_JoystickUpdate(SDL_Joystick *joystick)
1483 {
1484     int i;
1485 
1486     if (joystick->hwdata->m_bSteamController) {
1487         SDL_UpdateSteamController(joystick);
1488         return;
1489     }
1490 
1491     if (joystick->hwdata->classic) {
1492         HandleClassicEvents(joystick);
1493     } else {
1494         HandleInputEvents(joystick);
1495     }
1496 
1497     /* Deliver ball motion updates */
1498     for (i = 0; i < joystick->nballs; ++i) {
1499         int xrel, yrel;
1500 
1501         xrel = joystick->hwdata->balls[i].axis[0];
1502         yrel = joystick->hwdata->balls[i].axis[1];
1503         if (xrel || yrel) {
1504             joystick->hwdata->balls[i].axis[0] = 0;
1505             joystick->hwdata->balls[i].axis[1] = 0;
1506             SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
1507         }
1508     }
1509 }
1510 
1511 /* Function to close a joystick after use */
1512 static void
LINUX_JoystickClose(SDL_Joystick * joystick)1513 LINUX_JoystickClose(SDL_Joystick *joystick)
1514 {
1515     if (joystick->hwdata) {
1516         if (joystick->hwdata->effect.id >= 0) {
1517             ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id);
1518             joystick->hwdata->effect.id = -1;
1519         }
1520         if (joystick->hwdata->fd >= 0) {
1521             close(joystick->hwdata->fd);
1522         }
1523         if (joystick->hwdata->item) {
1524             joystick->hwdata->item->hwdata = NULL;
1525         }
1526         SDL_free(joystick->hwdata->key_pam);
1527         SDL_free(joystick->hwdata->abs_pam);
1528         SDL_free(joystick->hwdata->hats);
1529         SDL_free(joystick->hwdata->balls);
1530         SDL_free(joystick->hwdata->fname);
1531         SDL_free(joystick->hwdata);
1532     }
1533 }
1534 
1535 /* Function to perform any system-specific joystick related cleanup */
1536 static void
LINUX_JoystickQuit(void)1537 LINUX_JoystickQuit(void)
1538 {
1539     SDL_joylist_item *item = NULL;
1540     SDL_joylist_item *next = NULL;
1541 
1542     if (inotify_fd >= 0) {
1543         close(inotify_fd);
1544         inotify_fd = -1;
1545     }
1546 
1547     for (item = SDL_joylist; item; item = next) {
1548         next = item->next;
1549         FreeJoylistItem(item);
1550     }
1551 
1552     SDL_joylist = SDL_joylist_tail = NULL;
1553 
1554     numjoysticks = 0;
1555 
1556 #if SDL_USE_LIBUDEV
1557     if (enumeration_method == ENUMERATION_LIBUDEV) {
1558         SDL_UDEV_DelCallback(joystick_udev_callback);
1559         SDL_UDEV_Quit();
1560     }
1561 #endif
1562 
1563     SDL_QuitSteamControllers();
1564 }
1565 
1566 /*
1567    This is based on the Linux Gamepad Specification
1568    available at: https://www.kernel.org/doc/html/v4.15/input/gamepad.html
1569  */
1570 static SDL_bool
LINUX_JoystickGetGamepadMapping(int device_index,SDL_GamepadMapping * out)1571 LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
1572 {
1573     SDL_Joystick *joystick;
1574     SDL_joylist_item *item = JoystickByDevIndex(device_index);
1575 
1576     if (item->mapping) {
1577         SDL_memcpy(out, item->mapping, sizeof(*out));
1578         return SDL_TRUE;
1579     }
1580 
1581     /* We temporarily open the device to check how it's configured. Make
1582        a fake SDL_Joystick object to do so. */
1583     joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
1584     if (joystick == NULL) {
1585         SDL_OutOfMemory();
1586         return SDL_FALSE;
1587     }
1588     SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
1589 
1590     joystick->hwdata = (struct joystick_hwdata *)
1591         SDL_calloc(1, sizeof(*joystick->hwdata));
1592     if (joystick->hwdata == NULL) {
1593         SDL_free(joystick);
1594         SDL_OutOfMemory();
1595         return SDL_FALSE;
1596     }
1597 
1598     if (PrepareJoystickHwdata(joystick, item) == -1) {
1599         SDL_free(joystick->hwdata);
1600         SDL_free(joystick);
1601         return SDL_FALSE;  /* SDL_SetError will already have been called */
1602     }
1603 
1604     /* don't assign `item->hwdata` so it's not in any global state. */
1605 
1606     /* it is now safe to call LINUX_JoystickClose on this fake joystick. */
1607 
1608     if (!joystick->hwdata->has_key[BTN_GAMEPAD]) {
1609         /* Not a gamepad according to the specs. */
1610         LINUX_JoystickClose(joystick);
1611         SDL_free(joystick);
1612         return SDL_FALSE;
1613     }
1614 
1615     /* We have a gamepad, start filling out the mappings */
1616 
1617     if (joystick->hwdata->has_key[BTN_A]) {
1618         out->a.kind = EMappingKind_Button;
1619         out->a.target = joystick->hwdata->key_map[BTN_A];
1620     }
1621 
1622     if (joystick->hwdata->has_key[BTN_B]) {
1623         out->b.kind = EMappingKind_Button;
1624         out->b.target = joystick->hwdata->key_map[BTN_B];
1625     }
1626 
1627     /* Xbox controllers use BTN_X and BTN_Y, and PS4 controllers use BTN_WEST and BTN_NORTH */
1628     if (SDL_JoystickGetVendor(joystick) == USB_VENDOR_SONY) {
1629         if (joystick->hwdata->has_key[BTN_WEST]) {
1630             out->x.kind = EMappingKind_Button;
1631             out->x.target = joystick->hwdata->key_map[BTN_WEST];
1632         }
1633 
1634         if (joystick->hwdata->has_key[BTN_NORTH]) {
1635             out->y.kind = EMappingKind_Button;
1636             out->y.target = joystick->hwdata->key_map[BTN_NORTH];
1637         }
1638     } else {
1639         if (joystick->hwdata->has_key[BTN_X]) {
1640             out->x.kind = EMappingKind_Button;
1641             out->x.target = joystick->hwdata->key_map[BTN_X];
1642         }
1643 
1644         if (joystick->hwdata->has_key[BTN_Y]) {
1645             out->y.kind = EMappingKind_Button;
1646             out->y.target = joystick->hwdata->key_map[BTN_Y];
1647         }
1648     }
1649 
1650     if (joystick->hwdata->has_key[BTN_SELECT]) {
1651         out->back.kind = EMappingKind_Button;
1652         out->back.target = joystick->hwdata->key_map[BTN_SELECT];
1653     }
1654 
1655     if (joystick->hwdata->has_key[BTN_START]) {
1656         out->start.kind = EMappingKind_Button;
1657         out->start.target = joystick->hwdata->key_map[BTN_START];
1658     }
1659 
1660     if (joystick->hwdata->has_key[BTN_THUMBL]) {
1661         out->leftstick.kind = EMappingKind_Button;
1662         out->leftstick.target = joystick->hwdata->key_map[BTN_THUMBL];
1663     }
1664 
1665     if (joystick->hwdata->has_key[BTN_THUMBR]) {
1666         out->rightstick.kind = EMappingKind_Button;
1667         out->rightstick.target = joystick->hwdata->key_map[BTN_THUMBR];
1668     }
1669 
1670     if (joystick->hwdata->has_key[BTN_MODE]) {
1671         out->guide.kind = EMappingKind_Button;
1672         out->guide.target = joystick->hwdata->key_map[BTN_MODE];
1673     }
1674 
1675     /*
1676        According to the specs the D-Pad, the shoulder buttons and the triggers
1677        can be digital, or analog, or both at the same time.
1678      */
1679 
1680     /* Prefer digital shoulder buttons, but settle for analog if missing. */
1681     if (joystick->hwdata->has_key[BTN_TL]) {
1682         out->leftshoulder.kind = EMappingKind_Button;
1683         out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
1684     }
1685 
1686     if (joystick->hwdata->has_key[BTN_TR]) {
1687         out->rightshoulder.kind = EMappingKind_Button;
1688         out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
1689     }
1690 
1691     if (joystick->hwdata->has_hat[1] && /* Check if ABS_HAT1{X, Y} is available. */
1692        (!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
1693         int hat = joystick->hwdata->hats_indices[1] << 4;
1694         out->leftshoulder.kind = EMappingKind_Hat;
1695         out->rightshoulder.kind = EMappingKind_Hat;
1696         out->leftshoulder.target = hat | 0x4;
1697         out->rightshoulder.target = hat | 0x2;
1698     }
1699 
1700     /* Prefer analog triggers, but settle for digital if missing. */
1701     if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
1702         int hat = joystick->hwdata->hats_indices[2] << 4;
1703         out->lefttrigger.kind = EMappingKind_Hat;
1704         out->righttrigger.kind = EMappingKind_Hat;
1705         out->lefttrigger.target = hat | 0x4;
1706         out->righttrigger.target = hat | 0x2;
1707     } else {
1708         if (joystick->hwdata->has_abs[ABS_Z]) {
1709             out->lefttrigger.kind = EMappingKind_Axis;
1710             out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
1711         } else if (joystick->hwdata->has_key[BTN_TL2]) {
1712             out->lefttrigger.kind = EMappingKind_Button;
1713             out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
1714         }
1715 
1716         if (joystick->hwdata->has_abs[ABS_RZ]) {
1717             out->righttrigger.kind = EMappingKind_Axis;
1718             out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
1719         } else if (joystick->hwdata->has_key[BTN_TR2]) {
1720             out->righttrigger.kind = EMappingKind_Button;
1721             out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
1722         }
1723     }
1724 
1725     /* Prefer digital D-Pad, but settle for analog if missing. */
1726     if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
1727         out->dpup.kind = EMappingKind_Button;
1728         out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
1729     }
1730 
1731     if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
1732         out->dpdown.kind = EMappingKind_Button;
1733         out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
1734     }
1735 
1736     if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
1737         out->dpleft.kind = EMappingKind_Button;
1738         out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
1739     }
1740 
1741     if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
1742         out->dpright.kind = EMappingKind_Button;
1743         out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
1744     }
1745 
1746     if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
1747        (!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
1748         !joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
1749        int hat = joystick->hwdata->hats_indices[0] << 4;
1750        out->dpleft.kind = EMappingKind_Hat;
1751        out->dpright.kind = EMappingKind_Hat;
1752        out->dpup.kind = EMappingKind_Hat;
1753        out->dpdown.kind = EMappingKind_Hat;
1754        out->dpleft.target = hat | 0x8;
1755        out->dpright.target = hat | 0x2;
1756        out->dpup.target = hat | 0x1;
1757        out->dpdown.target = hat | 0x4;
1758     }
1759 
1760     if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
1761         out->leftx.kind = EMappingKind_Axis;
1762         out->lefty.kind = EMappingKind_Axis;
1763         out->leftx.target = joystick->hwdata->abs_map[ABS_X];
1764         out->lefty.target = joystick->hwdata->abs_map[ABS_Y];
1765     }
1766 
1767     if (joystick->hwdata->has_abs[ABS_RX] && joystick->hwdata->has_abs[ABS_RY]) {
1768         out->rightx.kind = EMappingKind_Axis;
1769         out->righty.kind = EMappingKind_Axis;
1770         out->rightx.target = joystick->hwdata->abs_map[ABS_RX];
1771         out->righty.target = joystick->hwdata->abs_map[ABS_RY];
1772     }
1773 
1774     LINUX_JoystickClose(joystick);
1775     SDL_free(joystick);
1776 
1777     /* Cache the mapping for later */
1778     item->mapping = (SDL_GamepadMapping *)SDL_malloc(sizeof(*item->mapping));
1779     if (item->mapping) {
1780         SDL_memcpy(item->mapping, out, sizeof(*out));
1781     }
1782 
1783     return SDL_TRUE;
1784 }
1785 
1786 SDL_JoystickDriver SDL_LINUX_JoystickDriver =
1787 {
1788     LINUX_JoystickInit,
1789     LINUX_JoystickGetCount,
1790     LINUX_JoystickDetect,
1791     LINUX_JoystickGetDeviceName,
1792     LINUX_JoystickGetDevicePlayerIndex,
1793     LINUX_JoystickSetDevicePlayerIndex,
1794     LINUX_JoystickGetDeviceGUID,
1795     LINUX_JoystickGetDeviceInstanceID,
1796     LINUX_JoystickOpen,
1797     LINUX_JoystickRumble,
1798     LINUX_JoystickRumbleTriggers,
1799     LINUX_JoystickGetCapabilities,
1800     LINUX_JoystickSetLED,
1801     LINUX_JoystickSendEffect,
1802     LINUX_JoystickSetSensorsEnabled,
1803     LINUX_JoystickUpdate,
1804     LINUX_JoystickClose,
1805     LINUX_JoystickQuit,
1806     LINUX_JoystickGetGamepadMapping
1807 };
1808 
1809 #endif /* SDL_JOYSTICK_LINUX */
1810 
1811 /* vi: set ts=4 sw=4 expandtab: */
1812