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:
parent
394879e603
commit
d1be1d60fa
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user