diff --git a/src/main.c b/src/main.c index 29d2df8..c2d1bfc 100644 --- a/src/main.c +++ b/src/main.c @@ -118,7 +118,10 @@ static int setup_app(struct kmscon_app *app) if (ret) goto err_app; - ret = uterm_video_new(&app->video, UTERM_VIDEO_DRM, app->eloop); + ret = uterm_video_new(&app->video, + app->eloop, + UTERM_VIDEO_DRM, + "/dev/dri/card0"); if (ret) goto err_app; diff --git a/src/uterm.h b/src/uterm.h index 2e8bfaf..f113d0f 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -173,8 +173,9 @@ int uterm_display_get_dpms(const struct uterm_display *disp); /* video interface */ int uterm_video_new(struct uterm_video **out, - int type, - struct ev_eloop *eloop); + struct ev_eloop *eloop, + unsigned int type, + const char *node); void uterm_video_ref(struct uterm_video *video); void uterm_video_unref(struct uterm_video *video); diff --git a/src/uterm_internal.h b/src/uterm_internal.h index affa158..77024b6 100644 --- a/src/uterm_internal.h +++ b/src/uterm_internal.h @@ -57,11 +57,11 @@ struct display_ops { }; struct video_ops { - int (*init) (struct uterm_video *video, struct udev_device *dev); + int (*init) (struct uterm_video *video, const char *node); void (*destroy) (struct uterm_video *video); void (*segfault) (struct uterm_video *video); int (*use) (struct uterm_video *video); - int (*poll) (struct uterm_video *video, int mask); + int (*poll) (struct uterm_video *video); void (*sleep) (struct uterm_video *video); int (*wake_up) (struct uterm_video *video); }; @@ -102,7 +102,6 @@ struct drm_display { }; struct drm_video { - int id; int fd; struct ev_fd *efd; struct gbm_device *gbm; @@ -259,10 +258,6 @@ struct uterm_video { unsigned int flags; struct ev_eloop *eloop; - struct udev *udev; - struct udev_monitor *umon; - struct ev_fd *umon_fd; - struct uterm_display *displays; struct kmscon_hook *hook; diff --git a/src/uterm_video.c b/src/uterm_video.c index 7c8ac0a..3240d7a 100644 --- a/src/uterm_video.c +++ b/src/uterm_video.c @@ -351,48 +351,15 @@ int uterm_display_get_dpms(const struct uterm_display *disp) return disp->dpms; } -static void video_poll(struct ev_fd *fd, int mask, void *data) -{ - struct uterm_video *video = data; - int ret; - - ret = VIDEO_CALL(video->ops->poll, 0, video, mask); - if (ret) { - ev_eloop_rm_fd(video->umon_fd); - video->umon_fd = NULL; - } -} - -static volatile int video_protect = 0; - int uterm_video_new(struct uterm_video **out, - int type, - struct ev_eloop *eloop) + struct ev_eloop *eloop, + unsigned int type, + const char *node) { struct uterm_video *video; - int ret, ufd; + int ret; const struct video_ops *ops; - /* - * We allow only one global video object. The reason behind this is that - * the OpenGL API has thread-awareness and we want to hide this behind - * our API. Otherwise, the caller would need to manage GL-contexts - * himself and this makes the API complex. Furthermore, there is really - * no reason why someone wants two video objects in the same process. - * That would mean that you want to control two graphic-cards in one - * process and we have never heard of a situation where this was needed. - * If you think you need two video objects, feel free to contact us and - * we might add a proper GL-context management API. - * But for now we protect this by a GCC-atomic. *_unref() decrements the - * counter again. - */ - ret = __sync_fetch_and_add(&video_protect, 1); - if (ret) { - __sync_fetch_and_sub(&video_protect, 1); - log_err("cannot create multiple instances"); - return -ENOTSUP; - } - if (!out || !eloop) return -EINVAL; @@ -400,14 +367,14 @@ int uterm_video_new(struct uterm_video **out, case UTERM_VIDEO_DRM: if (!drm_available) { log_err("DRM backend is not available"); - return -ENOTSUP; + return -EOPNOTSUPP; } ops = &drm_video_ops; break; case UTERM_VIDEO_FBDEV: if (!fbdev_available) { log_err("FBDEV backend is not available"); - return -ENOTSUP; + return -EOPNOTSUPP; } ops = &fbdev_video_ops; break; @@ -428,47 +395,15 @@ int uterm_video_new(struct uterm_video **out, if (ret) goto err_free; - video->udev = udev_new(); - if (!video->udev) { - log_err("cannot create udev object"); - ret = -EFAULT; + ret = VIDEO_CALL(video->ops->init, 0, video, node); + if (ret) goto err_hook; - } - - video->umon = udev_monitor_new_from_netlink(video->udev, "udev"); - if (!video->umon) { - log_err("cannot create udev monitor"); - ret = -EFAULT; - goto err_udev; - } - - ufd = udev_monitor_get_fd(video->umon); - if (ufd < 0) { - log_err("cannot get udev-monitor fd"); - ret = -EFAULT; - goto err_umon; - } - - ret = ev_eloop_new_fd(video->eloop, &video->umon_fd, ufd, - EV_READABLE, video_poll, video); - if (ret) - goto err_umon; - - ret = VIDEO_CALL(video->ops->init, 0, video, NULL); - if (ret) - goto err_umon_add; ev_eloop_ref(video->eloop); log_info("new device %p", video); *out = video; return 0; -err_umon_add: - ev_eloop_rm_fd(video->umon_fd); -err_umon: - udev_monitor_unref(video->umon); -err_udev: - udev_unref(video->udev); err_hook: kmscon_hook_free(video->hook); err_free: @@ -501,13 +436,9 @@ void uterm_video_unref(struct uterm_video *video) uterm_display_unref(disp); } - ev_eloop_rm_fd(video->umon_fd); - udev_monitor_unref(video->umon); - udev_unref(video->udev); kmscon_hook_free(video->hook); ev_eloop_unref(video->eloop); free(video); - __sync_fetch_and_sub(&video_protect, 1); } void uterm_video_segfault(struct uterm_video *video) @@ -574,3 +505,11 @@ bool uterm_video_is_awake(struct uterm_video *video) { return video && video_is_awake(video); } + +void uterm_video_poll(struct uterm_video *video) +{ + if (!video) + return; + + VIDEO_CALL(video->ops->poll, 0, video); +} diff --git a/src/uterm_video_drm.c b/src/uterm_video_drm.c index 39fc4cc..e4d8b3e 100644 --- a/src/uterm_video_drm.c +++ b/src/uterm_video_drm.c @@ -517,25 +517,6 @@ static void unbind_display(struct uterm_display *disp) uterm_display_unref(disp); } -static int get_id(struct udev_device *dev) -{ - const char *name; - char *end; - int devnum; - - name = udev_device_get_sysname(dev); - if (!name) - return -ENODEV; - if (strncmp(name, "card", 4) || !name[4]) - return -ENODEV; - - devnum = strtol(&name[4], &end, 10); - if (devnum < 0 || *end) - return -ENODEV; - - return devnum; -} - static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { @@ -565,9 +546,9 @@ static void event(struct ev_fd *fd, int mask, void *data) } } -static int init_device(struct uterm_video *video, struct udev_device *dev) +static int video_init(struct uterm_video *video, const char *node) { - const char *node, *ext; + const char *ext; int ret; EGLint major, minor; EGLenum api; @@ -575,17 +556,7 @@ static int init_device(struct uterm_video *video, struct udev_device *dev) { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; struct drm_video *drm = &video->drm; - log_info("probing %s", udev_device_get_sysname(dev)); - - node = udev_device_get_devnode(dev); - if (!node) - return -ENODEV; - - drm->id = get_id(dev); - if (drm->id < 0) { - log_err("cannot get device id"); - return -ENODEV; - } + log_info("probing %s", node); drm->fd = open(node, O_RDWR | O_CLOEXEC); if (drm->fd < 0) { @@ -659,93 +630,6 @@ err_close: return ret; } -static int video_init(struct uterm_video *video, struct udev_device *dev_ign) -{ - struct udev_enumerate *e; - struct udev_list_entry *name; - const char *path, *seat; - struct udev_device *dev; - int ret; - - ret = udev_monitor_filter_add_match_subsystem_devtype(video->umon, - "drm", "drm_minor"); - if (ret) { - log_err("cannot add udev filter (%d): %m", ret); - return -EFAULT; - } - - ret = udev_monitor_enable_receiving(video->umon); - if (ret) { - log_err("cannot start udev_monitor (%d): %m", ret); - return -EFAULT; - } - - e = udev_enumerate_new(video->udev); - if (!e) { - log_err("cannot create udev_enumerate object"); - return -EFAULT; - } - - ret = udev_enumerate_add_match_subsystem(e, "drm"); - if (ret) { - log_err("cannot add udev match (%d): %m", ret); - ret = -EFAULT; - goto err_enum; - } - ret = udev_enumerate_add_match_sysname(e, "card[0-9]*"); - if (ret) { - log_err("cannot add udev match (%d): %m", ret); - ret = -EFAULT; - goto err_enum; - } - if (strcmp(conf_global.seat, "seat0")) { - ret = udev_enumerate_add_match_tag(e, conf_global.seat); - if (ret) { - log_err("cannot add udev match (%d): %m", ret); - ret = -EFAULT; - goto err_enum; - } - } - ret = udev_enumerate_scan_devices(e); - if (ret) { - log_err("cannot scan udev devices (%d): %m", ret); - ret = -EFAULT; - goto err_enum; - } - - udev_list_entry_foreach(name, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(name); - if (!path || !*path) - continue; - dev = udev_device_new_from_syspath(video->udev, path); - if (!dev) - continue; - seat = udev_device_get_property_value(dev, "ID_SEAT"); - if (!seat) - seat = "seat0"; - if (strcmp(conf_global.seat, seat)) { - log_debug("ignoring %s (wrong seat)", path); - udev_device_unref(dev); - continue; - } - - ret = init_device(video, dev); - udev_device_unref(dev); - if (!ret) - goto done; - } - - ret = -ENODEV; - log_err("no drm device found"); - goto err_enum; - -done: - ret = 0; -err_enum: - udev_enumerate_unref(e); - return ret; -} - static void video_destroy(struct uterm_video *video) { struct drm_video *drm = &video->drm; @@ -847,53 +731,9 @@ static int hotplug(struct uterm_video *video) return 0; } -static int monitor(struct uterm_video *video) +static int video_poll(struct uterm_video *video) { - struct udev_device *dev; - const char *action, *val; - int id; - - dev = udev_monitor_receive_device(video->umon); - if (!dev) { - log_warn("cannot receive device from udev_monitor"); - return 0; - } - - action = udev_device_get_action(dev); - if (!action) - goto ignore; - if (strcmp(action, "change")) - goto ignore; - - val = udev_device_get_property_value(dev, "HOTPLUG"); - if (strcmp(val, "1")) - goto ignore; - - id = get_id(dev); - if (id != video->drm.id) - goto ignore; - video->flags |= VIDEO_HOTPLUG; -ignore: - udev_device_unref(dev); - return 0; -} - -static int video_poll(struct uterm_video *video, int mask) -{ - int ret; - - if (mask & (EV_HUP | EV_ERR)) { - log_err("udev_monitor closed unexpectedly"); - return -EFAULT; - } - - if (mask & EV_READABLE) { - ret = monitor(video); - if (ret) - return ret; - } - return hotplug(video); }