|
@@ -34,11 +34,13 @@
|
|
|
#include <limits.h> /* For the definition of PATH_MAX */
|
|
|
#include <sys/ioctl.h>
|
|
|
#include <unistd.h>
|
|
|
+#include <dirent.h>
|
|
|
#include <linux/joystick.h>
|
|
|
|
|
|
#include "SDL_assert.h"
|
|
|
#include "SDL_joystick.h"
|
|
|
#include "SDL_endian.h"
|
|
|
+#include "SDL_timer.h"
|
|
|
#include "../../events/SDL_events_c.h"
|
|
|
#include "../SDL_sysjoystick.h"
|
|
|
#include "../SDL_joystick_c.h"
|
|
@@ -56,10 +58,8 @@
|
|
|
static int MaybeAddDevice(const char *path);
|
|
|
#if SDL_USE_LIBUDEV
|
|
|
static int MaybeRemoveDevice(const char *path);
|
|
|
-static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
|
|
|
#endif /* SDL_USE_LIBUDEV */
|
|
|
|
|
|
-
|
|
|
/* A linked list of available joysticks */
|
|
|
typedef struct SDL_joylist_item
|
|
|
{
|
|
@@ -79,6 +79,9 @@ static SDL_joylist_item *SDL_joylist = NULL;
|
|
|
static SDL_joylist_item *SDL_joylist_tail = NULL;
|
|
|
static int numjoysticks = 0;
|
|
|
|
|
|
+#if !SDL_USE_LIBUDEV
|
|
|
+static Uint32 last_joy_detect_time = 0;
|
|
|
+#endif
|
|
|
|
|
|
#define test_bit(nr, addr) \
|
|
|
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
|
|
@@ -177,8 +180,6 @@ static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_clas
|
|
|
}
|
|
|
#endif /* SDL_USE_LIBUDEV */
|
|
|
|
|
|
-
|
|
|
-/* !!! FIXME: I would love to dump this code and use libudev instead. */
|
|
|
static int
|
|
|
MaybeAddDevice(const char *path)
|
|
|
{
|
|
@@ -254,7 +255,6 @@ MaybeAddDevice(const char *path)
|
|
|
}
|
|
|
|
|
|
#if SDL_USE_LIBUDEV
|
|
|
-/* !!! FIXME: I would love to dump this code and use libudev instead. */
|
|
|
static int
|
|
|
MaybeRemoveDevice(const char *path)
|
|
|
{
|
|
@@ -299,45 +299,46 @@ MaybeRemoveDevice(const char *path)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-#if ! SDL_USE_LIBUDEV
|
|
|
-static int
|
|
|
-JoystickInitWithoutUdev(void)
|
|
|
+static void
|
|
|
+HandlePendingRemovals(void)
|
|
|
{
|
|
|
- int i;
|
|
|
- char path[PATH_MAX];
|
|
|
+ SDL_joylist_item *prev = NULL;
|
|
|
+ SDL_joylist_item *item = SDL_joylist;
|
|
|
|
|
|
- /* !!! FIXME: only finds sticks if they're called /dev/input/event[0..31] */
|
|
|
- /* !!! FIXME: we could at least readdir() through /dev/input...? */
|
|
|
- /* !!! FIXME: (or delete this and rely on libudev?) */
|
|
|
- for (i = 0; i < 32; i++) {
|
|
|
- SDL_snprintf(path, SDL_arraysize(path), "/dev/input/event%d", i);
|
|
|
- MaybeAddDevice(path);
|
|
|
- }
|
|
|
+ while (item != NULL) {
|
|
|
+ if (item->hwdata && item->hwdata->gone) {
|
|
|
+ item->hwdata->item = NULL;
|
|
|
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
+ if (prev != NULL) {
|
|
|
+ prev->next = item->next;
|
|
|
+ } else {
|
|
|
+ SDL_assert(SDL_joylist == item);
|
|
|
+ SDL_joylist = item->next;
|
|
|
+ }
|
|
|
+ if (item == SDL_joylist_tail) {
|
|
|
+ SDL_joylist_tail = prev;
|
|
|
+ }
|
|
|
|
|
|
-#if SDL_USE_LIBUDEV
|
|
|
-static int
|
|
|
-JoystickInitWithUdev(void)
|
|
|
-{
|
|
|
- if (SDL_UDEV_Init() < 0) {
|
|
|
- return SDL_SetError("Could not initialize UDEV");
|
|
|
- }
|
|
|
+ /* Need to decrement the joystick count before we post the event */
|
|
|
+ --numjoysticks;
|
|
|
|
|
|
- /* Set up the udev callback */
|
|
|
- if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
|
|
- SDL_UDEV_Quit();
|
|
|
- return SDL_SetError("Could not set up joystick <-> udev callback");
|
|
|
- }
|
|
|
-
|
|
|
- /* Force a scan to build the initial device list */
|
|
|
- SDL_UDEV_Scan();
|
|
|
+ SDL_PrivateJoystickRemoved(item->device_instance);
|
|
|
|
|
|
- return 0;
|
|
|
+ SDL_free(item->path);
|
|
|
+ SDL_free(item->name);
|
|
|
+ SDL_free(item);
|
|
|
+
|
|
|
+ if (prev != NULL) {
|
|
|
+ item = prev->next;
|
|
|
+ } else {
|
|
|
+ item = SDL_joylist;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ prev = item;
|
|
|
+ item = item->next;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
|
|
|
{
|
|
@@ -410,6 +411,42 @@ static void SteamControllerDisconnectedCallback(int device_instance)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+LINUX_JoystickDetect(void)
|
|
|
+{
|
|
|
+#if SDL_USE_LIBUDEV
|
|
|
+ SDL_UDEV_Poll();
|
|
|
+#else
|
|
|
+ const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
|
|
|
+ Uint32 now = SDL_GetTicks();
|
|
|
+
|
|
|
+ if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
|
|
|
+ DIR *folder;
|
|
|
+ struct dirent *dent;
|
|
|
+
|
|
|
+ folder = opendir("/dev/input");
|
|
|
+ if (folder) {
|
|
|
+ while ((dent = readdir(folder))) {
|
|
|
+ int len = SDL_strlen(dent->d_name);
|
|
|
+ if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
|
|
|
+ char path[PATH_MAX];
|
|
|
+ SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
|
|
|
+ MaybeAddDevice(path);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ closedir(folder);
|
|
|
+ }
|
|
|
+
|
|
|
+ last_joy_detect_time = now;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ HandlePendingRemovals();
|
|
|
+
|
|
|
+ SDL_UpdateSteamControllers();
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
LINUX_JoystickInit(void)
|
|
|
{
|
|
@@ -433,10 +470,24 @@ LINUX_JoystickInit(void)
|
|
|
SteamControllerDisconnectedCallback);
|
|
|
|
|
|
#if SDL_USE_LIBUDEV
|
|
|
- return JoystickInitWithUdev();
|
|
|
-#else
|
|
|
- return JoystickInitWithoutUdev();
|
|
|
+ if (SDL_UDEV_Init() < 0) {
|
|
|
+ return SDL_SetError("Could not initialize UDEV");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Set up the udev callback */
|
|
|
+ if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
|
|
+ SDL_UDEV_Quit();
|
|
|
+ return SDL_SetError("Could not set up joystick <-> udev callback");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Force a scan to build the initial device list */
|
|
|
+ SDL_UDEV_Scan();
|
|
|
+#else
|
|
|
+ /* Report all devices currently present */
|
|
|
+ LINUX_JoystickDetect();
|
|
|
#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -445,16 +496,6 @@ LINUX_JoystickGetCount(void)
|
|
|
return numjoysticks;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-LINUX_JoystickDetect(void)
|
|
|
-{
|
|
|
-#if SDL_USE_LIBUDEV
|
|
|
- SDL_UDEV_Poll();
|
|
|
-#endif
|
|
|
-
|
|
|
- SDL_UpdateSteamControllers();
|
|
|
-}
|
|
|
-
|
|
|
static SDL_joylist_item *
|
|
|
JoystickByDevIndex(int device_index)
|
|
|
{
|
|
@@ -915,6 +956,11 @@ HandleInputEvents(SDL_Joystick * joystick)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (errno == ENODEV) {
|
|
|
+ /* We have to wait until the JoystickDetect callback to remove this */
|
|
|
+ joystick->hwdata->gone = SDL_TRUE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void
|