diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c index 9ad9f2a28a..22b6237c7d 100644 --- a/input/drivers/udev_input.c +++ b/input/drivers/udev_input.c @@ -24,6 +24,9 @@ #include #include +#include +#include + #include #include #include @@ -33,8 +36,6 @@ #include "../drivers_keyboard/keyboard_event_udev.h" #include "../common/linux_common.h" -#include "../common/epoll_common.h" -#include "../common/udev_common.h" #include "../input_config.h" #include "../input_joypad_driver.h" @@ -78,8 +79,13 @@ struct udev_input_device struct udev_input { bool blocked; + struct udev *udev; + struct udev_monitor *monitor; + + const input_device_driver_t *joypad; + int epfd; udev_input_device_t **devices; unsigned num_devices; @@ -217,6 +223,19 @@ static void udev_handle_mouse(void *data, } } +static bool udev_input_hotplug_available(udev_input_t *udev) +{ + struct pollfd fds = {0}; + + if (!udev || !udev->monitor) + return false; + + fds.fd = udev_monitor_get_fd(udev->monitor); + fds.events = POLLIN; + + return (poll(&fds, 1, 0) == 1) && (fds.revents & POLLIN); +} + static bool add_device(udev_input_t *udev, const char *devnode, device_handle_cb cb) { @@ -224,6 +243,7 @@ static bool add_device(udev_input_t *udev, udev_input_device_t **tmp; udev_input_device_t *device = NULL; struct stat st = {0}; + struct epoll_event event = {0}; if (stat(devnode, &st) < 0) return false; @@ -257,7 +277,13 @@ static bool add_device(udev_input_t *udev, tmp[udev->num_devices++] = device; udev->devices = tmp; - epoll_add(fd, device); + event.events = EPOLLIN; + event.data.ptr = device; + + /* Shouldn't happen, but just check it. */ + if (epoll_ctl(udev->epfd, EPOLL_CTL_ADD, fd, &event) < 0) + RARCH_ERR("Failed to add FD (%d) to epoll list (%s).\n", + fd, strerror(errno)); return true; @@ -289,6 +315,7 @@ static void udev_input_remove_device(udev_input_t *udev, const char *devnode) static void udev_input_handle_hotplug(udev_input_t *udev) { bool is_keyboard, is_mouse, is_touchpad; + struct udev_device *dev = udev_monitor_receive_device(udev->monitor); device_handle_cb cb = NULL; const char *devtype = NULL; const char *val_keyboard = NULL; @@ -296,7 +323,6 @@ static void udev_input_handle_hotplug(udev_input_t *udev) const char *val_touchpad = NULL; const char *action = NULL; const char *devnode = NULL; - struct udev_device *dev = udev_mon_receive_device(); if (!dev) return; @@ -355,10 +381,10 @@ static void udev_input_poll(void *data) udev->mouse_wu = udev->mouse_wd = 0; udev->mouse_whu = udev->mouse_whd = 0; - while (udev_mon_hotplug_available()) + while (udev_input_hotplug_available(udev)) udev_input_handle_hotplug(udev); - ret = epoll_waiting(events, ARRAY_SIZE(events), 0); + ret = epoll_wait(udev->epfd, events, ARRAY_SIZE(events), 0); for (i = 0; i < ret; i++) { @@ -550,7 +576,8 @@ static void udev_input_free(void *data) if (udev->joypad) udev->joypad->destroy(); - epoll_free(false); + if (udev->epfd >= 0) + close(udev->epfd); for (i = 0; i < udev->num_devices; i++) { @@ -559,7 +586,10 @@ static void udev_input_free(void *data) } free(udev->devices); - udev_mon_free(false); + if (udev->monitor) + udev_monitor_unref(udev->monitor); + if (udev->udev) + udev_unref(udev->udev); udev_input_kb_free(); @@ -570,7 +600,7 @@ static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb { struct udev_list_entry *devs = NULL; struct udev_list_entry *item = NULL; - struct udev_enumerate *enumerate = udev_mon_enumerate(); + struct udev_enumerate *enumerate = udev_enumerate_new(udev->udev); if (!enumerate) return false; @@ -581,9 +611,12 @@ static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb for (item = devs; item; item = udev_list_entry_get_next(item)) { - const char *name = udev_list_entry_get_name(item); - struct udev_device *dev = udev_mon_device_new(name); - const char *devnode = udev_device_get_devnode(dev); + const char *name = udev_list_entry_get_name(item); + + /* Get the filename of the /sys entry for the device + * and create a udev_device object (dev) representing it. */ + struct udev_device *dev = udev_device_new_from_syspath(udev->udev, name); + const char *devnode = udev_device_get_devnode(dev); if (devnode) { @@ -611,15 +644,27 @@ static void *udev_input_init(void) if (!udev) return NULL; - if (!udev_mon_new(false)) + udev->udev = udev_new(); + if (!udev->udev) + { + RARCH_ERR("Failed to create udev handle.\n"); goto error; + } + + udev->monitor = udev_monitor_new_from_netlink(udev->udev, "udev"); + if (udev->monitor) + { + udev_monitor_filter_add_match_subsystem_devtype(udev->monitor, "input", NULL); + udev_monitor_enable_receiving(udev->monitor); + } #ifdef HAVE_XKBCOMMON if (init_xkb() == -1) goto error; #endif - if (!epoll_new(false)) + udev->epfd = epoll_create(32); + if (udev->epfd < 0) { RARCH_ERR("Failed to create epoll FD.\n"); goto error; diff --git a/input/drivers_joypad/udev_joypad.c b/input/drivers_joypad/udev_joypad.c index 53e876d5d2..c4e78c7996 100644 --- a/input/drivers_joypad/udev_joypad.c +++ b/input/drivers_joypad/udev_joypad.c @@ -22,13 +22,14 @@ #include #include +#include +#include #include #include #include #include "../input_autodetect.h" -#include "../common/udev_common.h" #include "../../general.h" #include "../../verbosity.h" @@ -70,12 +71,14 @@ struct udev_joypad uint16_t strength[2]; uint16_t configured_strength[2]; - char ident[256]; + char ident[PATH_MAX_LENGTH]; char *path; int32_t vid; int32_t pid; }; +static struct udev *g_udev; +static struct udev_monitor *g_udev_mon; static struct udev_joypad udev_pads[MAX_USERS]; static INLINE int16_t udev_compute_axis(const struct input_absinfo *info, int value) @@ -152,6 +155,19 @@ static void udev_poll_pad(struct udev_joypad *pad, unsigned p) } } +static bool udev_hotplug_available(void) +{ + struct pollfd fds = {0}; + + if (!g_udev_mon) + return false; + + fds.fd = udev_monitor_get_fd(g_udev_mon); + fds.events = POLLIN; + + return (poll(&fds, 1, 0) == 1) && (fds.revents & POLLIN); +} + static int udev_find_vacant_pad(void) { unsigned i; @@ -341,7 +357,7 @@ static void udev_check_device(struct udev_device *dev, const char *path, bool ho default: if (hotplugged) { - char msg[256]; + char msg[PATH_MAX_LENGTH] = {0}; snprintf(msg, sizeof(msg), "Device #%u (%s) connected.", pad, path); runloop_msg_queue_push(msg, 0, 60, false); @@ -389,15 +405,20 @@ static void udev_joypad_destroy(void) for (i = 0; i < MAX_USERS; i++) udev_free_pad(i); - udev_mon_free(true); + if (g_udev_mon) + udev_monitor_unref(g_udev_mon); + g_udev_mon = NULL; + if (g_udev) + udev_unref(g_udev); + g_udev = NULL; } static void udev_joypad_handle_hotplug(void) { + struct udev_device *dev = udev_monitor_receive_device(g_udev_mon); const char *val; const char *action; const char *devnode; - struct udev_device *dev = udev_mon_receive_device(); if (!dev) return; @@ -495,7 +516,7 @@ static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, uint16_ static void udev_joypad_poll(void) { unsigned i; - while (udev_mon_hotplug_available()) + while (udev_hotplug_available()) udev_joypad_handle_hotplug(); for (i = 0; i < MAX_USERS; i++) @@ -515,10 +536,18 @@ static bool udev_joypad_init(void *data) for (i = 0; i < MAX_USERS; i++) udev_pads[i].fd = -1; - if (!udev_mon_new(true)) - goto error; + g_udev = udev_new(); + if (!g_udev) + return false; - enumerate = udev_mon_enumerate(); + g_udev_mon = udev_monitor_new_from_netlink(g_udev, "udev"); + if (g_udev_mon) + { + udev_monitor_filter_add_match_subsystem_devtype(g_udev_mon, "input", NULL); + udev_monitor_enable_receiving(g_udev_mon); + } + + enumerate = udev_enumerate_new(g_udev); if (!enumerate) goto error; @@ -529,7 +558,7 @@ static bool udev_joypad_init(void *data) for (item = devs; item; item = udev_list_entry_get_next(item)) { const char *name = udev_list_entry_get_name(item); - struct udev_device *dev = udev_mon_device_new(name); + struct udev_device *dev = udev_device_new_from_syspath(g_udev, name); const char *devnode = udev_device_get_devnode(dev); if (devnode) @@ -589,12 +618,12 @@ static uint64_t udev_joypad_get_buttons(unsigned port) static int16_t udev_joypad_axis(unsigned port, uint32_t joyaxis) { int16_t val = 0; - const struct udev_joypad *pad = (const struct udev_joypad*) - &udev_pads[port]; - + const struct udev_joypad *pad; if (joyaxis == AXIS_NONE) return 0; + pad = (const struct udev_joypad*)&udev_pads[port]; + if (AXIS_NEG_GET(joyaxis) < NUM_AXES) { val = pad->axes[AXIS_NEG_GET(joyaxis)];