From b17242bf9839a3796d82264f653df2dd4d416f9b Mon Sep 17 00:00:00 2001
From: Ludovico de Nittis <[EMAIL REDACTED]>
Date: Tue, 16 Feb 2021 11:50:20 +0100
Subject: [PATCH] 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>
---
src/joystick/hidapi/SDL_hidapijoystick.c | 100 +++++++++++++++--------
1 file changed, 64 insertions(+), 36 deletions(-)
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index d73ba4078..e751bb15f 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));