From 02ddaaeb9f1436ed35595d5b8564d6624984a17c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 21 Sep 2012 14:25:10 +0200 Subject: [PATCH] uterm: monitor: mark DRM-fbdev devices as such Most DRM drivers also provide a legacy fbdev device so fbcon can pick it up (and more importantly, we get kernel panics on it). However, as an application developer, I don't want to use two devices which drive the same physical hardware. This marks all such DRM fbdev devices as FBDEV_DRM so kmscon doesn't pick them up automatically. Signed-off-by: David Herrmann --- src/uterm.h | 1 + src/uterm_monitor.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/uterm.h b/src/uterm.h index ba56786..dcaf84a 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -373,6 +373,7 @@ enum uterm_monitor_event_type { enum uterm_monitor_dev_type { UTERM_MONITOR_DRM, UTERM_MONITOR_FBDEV, + UTERM_MONITOR_FBDEV_DRM, UTERM_MONITOR_INPUT, }; diff --git a/src/uterm_monitor.c b/src/uterm_monitor.c index 7a8789c..b1131a9 100644 --- a/src/uterm_monitor.c +++ b/src/uterm_monitor.c @@ -34,9 +34,12 @@ #include #include #include +#include #include #include #include +#include +#include #include "log.h" #include "shl_dlist.h" #include "uterm.h" @@ -389,6 +392,56 @@ static int get_fb_id(struct udev_device *dev) return devnum; } +/* + * Nearly all DRM drivers do also create fbdev nodes which refer to the same + * hardware as the DRM devices. So we shouldn't advertise these fbdev nodes as + * real devices. Otherwise, the user might use these and the DRM devices + * simultaneously, thinking that they deal with two different hardware devices. + * + * We also report that it is a drm-device if we actually cannot verify that it + * is not some DRM device. + */ +static bool is_drm_fbdev(const char *node) +{ + int fd, ret, len; + struct fb_fix_screeninfo finfo; + bool res = true; + + fd = open(node, O_RDWR | O_CLOEXEC); + if (fd < 0) { + log_warning("cannot open fbdev node %s for drm-device verification (%d): %m", + node, errno); + return true; + } + + ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo); + if (ret) { + log_warning("cannot retrieve finfo from fbdev node %s for drm-device verification (%d): %m", + node, errno); + goto err_close; + } + + /* TODO: we really need some reliable flag here that tells us that we + * are dealing with a DRM device indirectly. Checking for "drmfb" suffix + * seems fine, but that may be just luck. + * If this turns out to not work reliably, we can also fall back to + * checking whether the parent udev device node does also provide a DRM + * device. */ + len = strlen(finfo.id); + if (len > 5 && !strcmp(&finfo.id[len - 5], "drmfb")) + goto err_close; + if (!strcmp(finfo.id, "nouveaufb")) + goto err_close; + if (!strcmp(finfo.id, "psbfb")) + goto err_close; + + res = false; + +err_close: + close(fd); + return res; +} + static void monitor_udev_add(struct uterm_monitor *mon, struct udev_device *dev) { @@ -447,7 +500,10 @@ static void monitor_udev_add(struct uterm_monitor *mon, return; } sname = udev_device_get_property_value(dev, "ID_SEAT"); - type = UTERM_MONITOR_FBDEV; + if (is_drm_fbdev(node)) + type = UTERM_MONITOR_FBDEV_DRM; + else + type = UTERM_MONITOR_FBDEV; } else if (!strcmp(subs, "input")) { sysname = udev_device_get_sysname(dev); if (!sysname || strncmp(sysname, "event", 5)) { -- 2.7.4