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)
|
if (ret)
|
||||||
goto err_app;
|
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)
|
if (ret)
|
||||||
goto err_app;
|
goto err_app;
|
||||||
|
|
||||||
|
@ -173,8 +173,9 @@ int uterm_display_get_dpms(const struct uterm_display *disp);
|
|||||||
/* video interface */
|
/* video interface */
|
||||||
|
|
||||||
int uterm_video_new(struct uterm_video **out,
|
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_ref(struct uterm_video *video);
|
||||||
void uterm_video_unref(struct uterm_video *video);
|
void uterm_video_unref(struct uterm_video *video);
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ struct display_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct video_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 (*destroy) (struct uterm_video *video);
|
||||||
void (*segfault) (struct uterm_video *video);
|
void (*segfault) (struct uterm_video *video);
|
||||||
int (*use) (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);
|
void (*sleep) (struct uterm_video *video);
|
||||||
int (*wake_up) (struct uterm_video *video);
|
int (*wake_up) (struct uterm_video *video);
|
||||||
};
|
};
|
||||||
@ -102,7 +102,6 @@ struct drm_display {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct drm_video {
|
struct drm_video {
|
||||||
int id;
|
|
||||||
int fd;
|
int fd;
|
||||||
struct ev_fd *efd;
|
struct ev_fd *efd;
|
||||||
struct gbm_device *gbm;
|
struct gbm_device *gbm;
|
||||||
@ -259,10 +258,6 @@ struct uterm_video {
|
|||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
struct ev_eloop *eloop;
|
struct ev_eloop *eloop;
|
||||||
|
|
||||||
struct udev *udev;
|
|
||||||
struct udev_monitor *umon;
|
|
||||||
struct ev_fd *umon_fd;
|
|
||||||
|
|
||||||
struct uterm_display *displays;
|
struct uterm_display *displays;
|
||||||
struct kmscon_hook *hook;
|
struct kmscon_hook *hook;
|
||||||
|
|
||||||
|
@ -351,48 +351,15 @@ int uterm_display_get_dpms(const struct uterm_display *disp)
|
|||||||
return disp->dpms;
|
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 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;
|
struct uterm_video *video;
|
||||||
int ret, ufd;
|
int ret;
|
||||||
const struct video_ops *ops;
|
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)
|
if (!out || !eloop)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -400,14 +367,14 @@ int uterm_video_new(struct uterm_video **out,
|
|||||||
case UTERM_VIDEO_DRM:
|
case UTERM_VIDEO_DRM:
|
||||||
if (!drm_available) {
|
if (!drm_available) {
|
||||||
log_err("DRM backend is not available");
|
log_err("DRM backend is not available");
|
||||||
return -ENOTSUP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
ops = &drm_video_ops;
|
ops = &drm_video_ops;
|
||||||
break;
|
break;
|
||||||
case UTERM_VIDEO_FBDEV:
|
case UTERM_VIDEO_FBDEV:
|
||||||
if (!fbdev_available) {
|
if (!fbdev_available) {
|
||||||
log_err("FBDEV backend is not available");
|
log_err("FBDEV backend is not available");
|
||||||
return -ENOTSUP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
ops = &fbdev_video_ops;
|
ops = &fbdev_video_ops;
|
||||||
break;
|
break;
|
||||||
@ -428,47 +395,15 @@ int uterm_video_new(struct uterm_video **out,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
video->udev = udev_new();
|
ret = VIDEO_CALL(video->ops->init, 0, video, node);
|
||||||
if (!video->udev) {
|
if (ret)
|
||||||
log_err("cannot create udev object");
|
|
||||||
ret = -EFAULT;
|
|
||||||
goto err_hook;
|
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);
|
ev_eloop_ref(video->eloop);
|
||||||
log_info("new device %p", video);
|
log_info("new device %p", video);
|
||||||
*out = video;
|
*out = video;
|
||||||
return 0;
|
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:
|
err_hook:
|
||||||
kmscon_hook_free(video->hook);
|
kmscon_hook_free(video->hook);
|
||||||
err_free:
|
err_free:
|
||||||
@ -501,13 +436,9 @@ void uterm_video_unref(struct uterm_video *video)
|
|||||||
uterm_display_unref(disp);
|
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);
|
kmscon_hook_free(video->hook);
|
||||||
ev_eloop_unref(video->eloop);
|
ev_eloop_unref(video->eloop);
|
||||||
free(video);
|
free(video);
|
||||||
__sync_fetch_and_sub(&video_protect, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uterm_video_segfault(struct uterm_video *video)
|
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);
|
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);
|
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,
|
static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
||||||
unsigned int usec, void *data)
|
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;
|
int ret;
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
EGLenum api;
|
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 };
|
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||||
struct drm_video *drm = &video->drm;
|
struct drm_video *drm = &video->drm;
|
||||||
|
|
||||||
log_info("probing %s", udev_device_get_sysname(dev));
|
log_info("probing %s", node);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
drm->fd = open(node, O_RDWR | O_CLOEXEC);
|
drm->fd = open(node, O_RDWR | O_CLOEXEC);
|
||||||
if (drm->fd < 0) {
|
if (drm->fd < 0) {
|
||||||
@ -659,93 +630,6 @@ err_close:
|
|||||||
return ret;
|
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)
|
static void video_destroy(struct uterm_video *video)
|
||||||
{
|
{
|
||||||
struct drm_video *drm = &video->drm;
|
struct drm_video *drm = &video->drm;
|
||||||
@ -847,53 +731,9 @@ static int hotplug(struct uterm_video *video)
|
|||||||
return 0;
|
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;
|
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);
|
return hotplug(video);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user