Dynamically load libudev.so.1 on Linux if udev=yes

This makes it possibly to run Linux binaries compiled with udev support on
Linux systems which do not provide udev (typically systemd-less distros).

If udev is missing, we fall back to parsing `/dev/input` like when compiled
without udev support (`udev=no`).

Also adding some verbose debug statements to know which method we're using
when debugging Linux joypad issues.

The libudev so wrappers were generated on Mageia 8 with libudev 246.9 using
https://github.com/hpvb/dynload-wrapper:
```
./generate-wrapper.py --include /usr/include/libudev.h --sys-include '<libudev.h>' \
  --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ \
  --output-header libudev-so_wrap.h --output-implementation libudev-so_wrap.c
```
This commit is contained in:
Rémi Verschelde 2021-02-17 11:28:27 +01:00
parent fa8a47e1bf
commit a10c259c1d
No known key found for this signature in database
GPG key ID: C3336907360768E1
8 changed files with 1154 additions and 14 deletions

View file

@ -39,7 +39,7 @@
#include <unistd.h>
#ifdef UDEV_ENABLED
#include <libudev.h>
#include "libudev-so_wrap.h"
#endif
#define LONG_BITS (sizeof(long) * 8)
@ -72,13 +72,22 @@ void JoypadLinux::Joypad::reset() {
}
JoypadLinux::JoypadLinux(Input *in) {
exit_udev = false;
#ifdef UDEV_ENABLED
use_udev = initialize_libudev() == 0;
if (use_udev) {
print_verbose("JoypadLinux: udev enabled and loaded successfully.");
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
}
#else
print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
#endif
input = in;
joy_thread.start(joy_thread_func, this);
}
JoypadLinux::~JoypadLinux() {
exit_udev = true;
exit_monitor = true;
joy_thread.wait_to_finish();
close_joypad();
}
@ -92,11 +101,18 @@ void JoypadLinux::joy_thread_func(void *p_user) {
void JoypadLinux::run_joypad_thread() {
#ifdef UDEV_ENABLED
udev *_udev = udev_new();
ERR_FAIL_COND(!_udev);
enumerate_joypads(_udev);
monitor_joypads(_udev);
udev_unref(_udev);
if (use_udev) {
udev *_udev = udev_new();
if (!_udev) {
use_udev = false;
ERR_FAIL_MSG("Failed getting an udev context, falling back to parsing /dev/input.");
}
enumerate_joypads(_udev);
monitor_joypads(_udev);
udev_unref(_udev);
} else {
monitor_joypads();
}
#else
monitor_joypads();
#endif
@ -137,7 +153,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
udev_monitor_enable_receiving(mon);
int fd = udev_monitor_get_fd(mon);
while (!exit_udev) {
while (!exit_monitor) {
fd_set fds;
struct timeval tv;
int ret;
@ -179,7 +195,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
#endif
void JoypadLinux::monitor_joypads() {
while (!exit_udev) {
while (!exit_monitor) {
{
MutexLock lock(joy_mutex);