Allow libudev for HIDAPI joystick to be disabled at runtime As already explained in the previous commit "joystick: Allow libudev to be disabled at runtime" (13e7d1a9), libudev can fail in a container. To make it easier to experiment with, we add a new environment variable "SDL_HIDAPI_JOYSTICK_DISABLE_UDEV" that disables udev and let it fallback to the device enumeration using polling. Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index d73ba40..e751bb1 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -28,6 +28,7 @@
#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_joystick.h"
+#include "SDL_log.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
@@ -53,6 +54,15 @@
#endif
#endif
+typedef enum
+{
+ ENUMERATION_UNSET,
+ ENUMERATION_LIBUDEV,
+ ENUMERATION_FALLBACK
+} LinuxEnumerationMethod;
+
+static LinuxEnumerationMethod linux_enumeration_method = ENUMERATION_UNSET;
+
struct joystick_hwdata
{
SDL_HIDAPI_Device *device;
@@ -273,23 +283,24 @@ HIDAPI_InitializeDiscovery()
#endif // __MACOSX__
#if defined(SDL_USE_LIBUDEV)
- SDL_HIDAPI_discovery.m_pUdev = NULL;
- SDL_HIDAPI_discovery.m_pUdevMonitor = NULL;
- SDL_HIDAPI_discovery.m_nUdevFd = -1;
-
- usyms = SDL_UDEV_GetUdevSyms();
- if (usyms) {
- SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
- }
- if (SDL_HIDAPI_discovery.m_pUdev) {
- SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev, "udev");
- if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
- usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
- SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
- SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
+ if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
+ SDL_HIDAPI_discovery.m_pUdev = NULL;
+ SDL_HIDAPI_discovery.m_pUdevMonitor = NULL;
+ SDL_HIDAPI_discovery.m_nUdevFd = -1;
+
+ usyms = SDL_UDEV_GetUdevSyms();
+ if (usyms) {
+ SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
+ }
+ if (SDL_HIDAPI_discovery.m_pUdev) {
+ SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev, "udev");
+ if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
+ usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
+ SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
+ SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
+ }
}
}
-
#endif /* SDL_USE_LIBUDEV */
}
@@ -331,31 +342,33 @@ HIDAPI_UpdateDiscovery()
#endif
#if defined(SDL_USE_LIBUDEV)
- if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
- /* Drain all notification events.
- * We don't expect a lot of device notifications so just
- * do a new discovery on any kind or number of notifications.
- * This could be made more restrictive if necessary.
- */
- for (;;) {
- struct pollfd PollUdev;
- struct udev_device *pUdevDevice;
-
- PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
- PollUdev.events = POLLIN;
- if (poll(&PollUdev, 1, 0) != 1) {
- break;
- }
+ if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
+ if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
+ /* Drain all notification events.
+ * We don't expect a lot of device notifications so just
+ * do a new discovery on any kind or number of notifications.
+ * This could be made more restrictive if necessary.
+ */
+ for (;;) {
+ struct pollfd PollUdev;
+ struct udev_device *pUdevDevice;
+
+ PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
+ PollUdev.events = POLLIN;
+ if (poll(&PollUdev, 1, 0) != 1) {
+ break;
+ }
- SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
+ SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
- pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
- if (pUdevDevice) {
- usyms->udev_device_unref(pUdevDevice);
+ pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
+ if (pUdevDevice) {
+ usyms->udev_device_unref(pUdevDevice);
+ }
}
}
}
-#endif
+#endif /* SDL_USE_LIBUDEV */
}
static void
@@ -379,7 +392,8 @@ HIDAPI_ShutdownDiscovery()
#endif
#if defined(SDL_USE_LIBUDEV)
- if (usyms) {
+ if (linux_enumeration_method == ENUMERATION_LIBUDEV &&
+ usyms) {
if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
usyms->udev_monitor_unref(SDL_HIDAPI_discovery.m_pUdevMonitor);
}
@@ -600,6 +614,20 @@ HIDAPI_JoystickInit(void)
return 0;
}
+#if defined(SDL_USE_LIBUDEV)
+ if (linux_enumeration_method == ENUMERATION_UNSET) {
+ if (SDL_getenv("SDL_HIDAPI_JOYSTICK_DISABLE_UDEV") != NULL) {
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+ "udev disabled by SDL_HIDAPI_JOYSTICK_DISABLE_UDEV");
+ linux_enumeration_method = ENUMERATION_FALLBACK;
+ } else {
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+ "Using udev for HIDAPI joystick device discovery");
+ linux_enumeration_method = ENUMERATION_LIBUDEV;
+ }
+ }
+#endif
+
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)
/* The hidapi framwork is weak-linked on Apple platforms */
int HID_API_EXPORT HID_API_CALL hid_init(void) __attribute__((weak_import));