diff options
Diffstat (limited to 'backend/udev.c')
-rw-r--r-- | backend/udev.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/backend/udev.c b/backend/udev.c index 30c24e49..fb213339 100644 --- a/backend/udev.c +++ b/backend/udev.c @@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> #include <stdint.h> +#include <errno.h> #include <xf86drm.h> #include <xf86drmMode.h> #include <wayland-server.h> @@ -73,7 +74,6 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { struct udev_list_entry *entry; int fd = -1; - char *drm_path = NULL; udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) { bool is_boot_vga = false; @@ -117,9 +117,6 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { continue; } - free(drm_path); - drm_path = strdup(path); - udev_device_unref(dev); // We've found the primary GPU @@ -130,7 +127,6 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { udev_enumerate_unref(en); - udev->drm_path = drm_path; return fd; } @@ -143,21 +139,23 @@ static int udev_event(int fd, uint32_t mask, void *data) { } const char *action = udev_device_get_action(dev); - const char *path = udev_device_get_devnode(dev); wlr_log(L_DEBUG, "udev event for %s (%s)", udev_device_get_sysname(dev), action); - if (!path || strcmp(path, udev->drm_path) != 0) { - goto out; - } - if (!action || strcmp(action, "change") != 0) { goto out; } - // TODO: Specify the GPU that's being invalidated - wl_signal_emit(&udev->invalidate_drm, udev); + dev_t devnum = udev_device_get_devnum(dev); + struct wlr_udev_dev *signal; + + wl_list_for_each(signal, &udev->devices, link) { + if (signal->dev == devnum) { + wl_signal_emit(&signal->invalidate, udev); + break; + } + } out: udev_device_unref(dev); @@ -174,7 +172,6 @@ struct wlr_udev *wlr_udev_create(struct wl_display *display) { wlr_log(L_ERROR, "Failed to create udev context"); goto error; } - wl_signal_init(&udev->invalidate_drm); udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev"); if (!udev->mon) { @@ -195,6 +192,8 @@ struct wlr_udev *wlr_udev_create(struct wl_display *display) { goto error_mon; } + wl_list_init(&udev->devices); + wlr_log(L_DEBUG, "Successfully initialized udev"); return udev; @@ -212,9 +211,43 @@ void wlr_udev_destroy(struct wlr_udev *udev) { return; } - wl_event_source_remove(udev->event); + struct wlr_udev_dev *dev, *tmp; + wl_list_for_each_safe(dev, tmp, &udev->devices, link) { + free(dev); + } + wl_event_source_remove(udev->event); udev_monitor_unref(udev->mon); udev_unref(udev->udev); - free(udev->drm_path); +} + +bool wlr_udev_signal_add(struct wlr_udev *udev, dev_t dev, struct wl_listener *listener) { + struct wlr_udev_dev *device = malloc(sizeof(*device)); + if (!device) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); + return false; + } + + device->dev = dev; + wl_signal_init(&device->invalidate); + wl_signal_add(&device->invalidate, listener); + wl_list_insert(&udev->devices, &device->link); + + return true; +} + +void wlr_udev_signal_remove(struct wlr_udev *udev, struct wl_listener *listener) { + if (!udev || !listener) { + return; + } + + struct wlr_udev_dev *dev, *tmp; + wl_list_for_each_safe(dev, tmp, &udev->devices, link) { + // The signal should only have a single listener + if (wl_signal_get(&dev->invalidate, listener->notify) != NULL) { + wl_list_remove(&dev->link); + free(dev); + return; + } + } } |