uterm_video: remove hotplug awareness

To introduce the new uterm-monitor object we need to remove all the udev
handling from uterm_video. To not break "git bisect" we now remove all the
udev code from uterm_video and uterm_video_drm and make kmscon use the
static /dev/dri/card0 interface for now.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-05-05 17:39:46 +02:00
parent 394879e603
commit d1be1d60fa
5 changed files with 29 additions and 251 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}