diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index e41e5d966..0d1079912 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -84,6 +84,19 @@
 #define DEBUG_INPUT_EVENTS 1
 #endif
 
+typedef enum
+{
+    ENUMERATION_UNSET,
+    ENUMERATION_LIBUDEV,
+    ENUMERATION_FALLBACK
+} EnumerationMethod;
+
+#if SDL_USE_LIBUDEV
+static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
+#else
+const EnumerationMethod enumeration_method = ENUMERATION_FALLBACK;
+#endif
+
 static int MaybeAddDevice(const char *path);
 #if SDL_USE_LIBUDEV
 static int MaybeRemoveDevice(const char *path);
@@ -108,10 +121,8 @@ 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;
 static time_t last_input_dir_mtime;
-#endif
 
 #define test_bit(nr, addr) \
     (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
@@ -147,15 +158,8 @@ IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, const char *nam
 #endif /* SDL_JOYSTICK_HIDAPI */
 
 static int
-IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
+GuessIsJoystick(int fd)
 {
-    struct input_id inpid;
-    Uint16 *guid16 = (Uint16 *)guid->data;
-    char *name;
-    char product_string[128];
-
-#if !SDL_USE_LIBUDEV
-    /* When udev is enabled we only get joystick devices here, so there's no need to test them */
     unsigned long evbit[NBITS(EV_MAX)] = { 0 };
     unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
     unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
@@ -170,7 +174,22 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
           test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
         return 0;
     }
-#endif
+
+    return 1;
+}
+
+static int
+IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
+{
+    struct input_id inpid;
+    Uint16 *guid16 = (Uint16 *)guid->data;
+    char *name;
+    char product_string[128];
+
+    /* When udev is enabled we only get joystick devices here, so there's no need to test them */
+    if (enumeration_method == ENUMERATION_FALLBACK && !GuessIsJoystick(fd)) {
+        return 0;
+    }
 
     if (ioctl(fd, EVIOCGID, &inpid) < 0) {
         return 0;
@@ -484,11 +503,8 @@ static void SteamControllerDisconnectedCallback(int device_instance)
 }
 
 static void
-LINUX_JoystickDetect(void)
+LINUX_FallbackJoystickDetect(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();
 
@@ -519,7 +535,20 @@ LINUX_JoystickDetect(void)
 
         last_joy_detect_time = now;
     }
+}
+
+static void
+LINUX_JoystickDetect(void)
+{
+#if SDL_USE_LIBUDEV
+    if (enumeration_method == ENUMERATION_LIBUDEV) {
+        SDL_UDEV_Poll();
+    }
+    else
 #endif
+    {
+        LINUX_FallbackJoystickDetect();
+    }
 
     HandlePendingRemovals();
 
@@ -529,6 +558,17 @@ LINUX_JoystickDetect(void)
 static int
 LINUX_JoystickInit(void)
 {
+#if SDL_USE_LIBUDEV
+    if (enumeration_method == ENUMERATION_UNSET) {
+        if (SDL_getenv("SDL_JOYSTICK_DISABLE_UDEV") != NULL) {
+            enumeration_method = ENUMERATION_FALLBACK;
+        }
+        else {
+            enumeration_method = ENUMERATION_LIBUDEV;
+        }
+    }
+#endif
+
     /* First see if the user specified one or more joysticks to use */
     if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
         char *envcopy, *envpath, *delim;
@@ -549,26 +589,30 @@ LINUX_JoystickInit(void)
                              SteamControllerDisconnectedCallback);
 
 #if SDL_USE_LIBUDEV
-    if (SDL_UDEV_Init() < 0) {
-        return SDL_SetError("Could not initialize UDEV");
+    if (enumeration_method == ENUMERATION_LIBUDEV) {
+        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();
     }
-
-    /* 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
-    /* Force immediate joystick detection */
-    last_joy_detect_time = 0;
-    last_input_dir_mtime = 0;
-
-    /* Report all devices currently present */
-    LINUX_JoystickDetect();
+    else
 #endif
+    {
+        /* Force immediate joystick detection */
+        last_joy_detect_time = 0;
+        last_input_dir_mtime = 0;
+
+        /* Report all devices currently present */
+        LINUX_JoystickDetect();
+    }
 
     return 0;
 }
@@ -1191,8 +1235,10 @@ LINUX_JoystickQuit(void)
     numjoysticks = 0;
 
 #if SDL_USE_LIBUDEV
-    SDL_UDEV_DelCallback(joystick_udev_callback);
-    SDL_UDEV_Quit();
+    if (enumeration_method == ENUMERATION_LIBUDEV) {
+        SDL_UDEV_DelCallback(joystick_udev_callback);
+        SDL_UDEV_Quit();
+    }
 #endif
 
     SDL_QuitSteamControllers();