Add VT handling
As long as we are run in a VT we need to correctly handle VT-switches to avoid blocking the crtc/input. This is copied from wayland-compositor demos and modified to fit to our needs. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
1fb4c71895
commit
bb5f11baa1
26
COPYING
26
COPYING
@ -27,3 +27,29 @@ apply:
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
== Third-Party Source ==
|
||||
|
||||
This software includes code from several other Open-Source projects. See below
|
||||
for all copyright and license notes:
|
||||
|
||||
Copyright © 2008 Kristian Høgsberg
|
||||
Copyright © 2010 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and
|
||||
its documentation for any purpose is hereby granted without fee provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of the copyright holders not be used in
|
||||
advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission. The copyright holders make
|
||||
no representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
@ -1,7 +1,7 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
bin_PROGRAMS = kmscon
|
||||
check_PROGRAMS = test_console test_output
|
||||
check_PROGRAMS = test_console test_output test_vt
|
||||
noinst_LTLIBRARIES = libkmscon-core.la
|
||||
|
||||
AM_CFLAGS = \
|
||||
@ -19,7 +19,8 @@ libkmscon_core_la_SOURCES = \
|
||||
src/output.c src/output.h \
|
||||
src/console_char.c \
|
||||
src/log.c src/log.h \
|
||||
src/eloop.c src/eloop.h
|
||||
src/eloop.c src/eloop.h \
|
||||
src/vt.c src/vt.h
|
||||
|
||||
libkmscon_core_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
@ -53,4 +54,8 @@ test_output_LDADD = libkmscon-core.la \
|
||||
test_output_CPPFLAGS = $(kmscon_CFLAGS) \
|
||||
$(OPENGL_CFLAGS)
|
||||
|
||||
test_vt_SOURCES = tests/test_vt.c
|
||||
test_vt_LDADD = libkmscon-core.la
|
||||
test_vt_CPPFLAGS = $(kmscon_CFLAGS)
|
||||
|
||||
dist_doc_DATA = README TODO
|
||||
|
341
src/vt.c
Normal file
341
src/vt.c
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* kmscon - VT compatibility layer
|
||||
*
|
||||
* Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
|
||||
* Copyright (c) 2011 University of Tuebingen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This kmscon-VT API is based on the wayland-compositor demo:
|
||||
*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VT compatibility
|
||||
* Although we do not use the VT for drawing or anything, we set it to graphical
|
||||
* mode to avoid side effects.
|
||||
* This behavior is copied from wayland. If someone has more insight in VT
|
||||
* handling, they may adjust this code.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/vt.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "eloop.h"
|
||||
#include "log.h"
|
||||
#include "vt.h"
|
||||
|
||||
struct kmscon_vt {
|
||||
unsigned long ref;
|
||||
|
||||
int fd;
|
||||
struct termios saved_attribs;
|
||||
kmscon_vt_cb cb;
|
||||
void *data;
|
||||
|
||||
struct kmscon_signal *sig1;
|
||||
struct kmscon_signal *sig2;
|
||||
struct kmscon_fd *efd;
|
||||
};
|
||||
|
||||
int kmscon_vt_new(struct kmscon_vt **out, kmscon_vt_cb cb, void *data)
|
||||
{
|
||||
struct kmscon_vt *vt;
|
||||
|
||||
if (!out)
|
||||
return -EINVAL;
|
||||
|
||||
vt = malloc(sizeof(*vt));
|
||||
if (!vt)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(vt, 0, sizeof(*vt));
|
||||
vt->ref = 1;
|
||||
vt->fd = -1;
|
||||
vt->cb = cb;
|
||||
vt->data = data;
|
||||
|
||||
log_debug("vt: create VT object\n");
|
||||
*out = vt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kmscon_vt_ref(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt)
|
||||
return;
|
||||
|
||||
++vt->ref;
|
||||
}
|
||||
|
||||
void kmscon_vt_unref(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt || !vt->ref)
|
||||
return;
|
||||
|
||||
if (--vt->ref)
|
||||
return;
|
||||
|
||||
log_debug("vt: destroy VT object\n");
|
||||
kmscon_vt_close(vt);
|
||||
free(vt);
|
||||
}
|
||||
|
||||
static void vt_enter(struct kmscon_signal *sig, int signum, void *data)
|
||||
{
|
||||
struct kmscon_vt *vt = data;
|
||||
|
||||
if (!vt || vt->fd < 0)
|
||||
return;
|
||||
|
||||
log_debug("vt: entering VT\n");
|
||||
|
||||
ioctl(vt->fd, VT_RELDISP, VT_ACKACQ);
|
||||
if (ioctl(vt->fd, KDSETMODE, KD_GRAPHICS))
|
||||
log_warning("vt: cannot set graphics mode on vt\n");
|
||||
|
||||
if (vt->cb)
|
||||
vt->cb(vt, KMSCON_VT_ENTER, vt->data);
|
||||
}
|
||||
|
||||
static void vt_leave(struct kmscon_signal *sig, int signum, void *data)
|
||||
{
|
||||
struct kmscon_vt *vt = data;
|
||||
|
||||
if (!vt || vt->fd < 0)
|
||||
return;
|
||||
|
||||
|
||||
if (vt->cb && !vt->cb(vt, KMSCON_VT_LEAVE, vt->data)) {
|
||||
log_debug("vt: leaving VT denied\n");
|
||||
ioctl(vt->fd, VT_RELDISP, 0);
|
||||
} else {
|
||||
log_debug("vt: leaving VT\n");
|
||||
ioctl(vt->fd, VT_RELDISP, 1);
|
||||
if (ioctl(vt->fd, KDSETMODE, KD_TEXT))
|
||||
log_warning("vt: cannot set text mode on vt\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void vt_input(struct kmscon_fd *fd, int mask, void *data)
|
||||
{
|
||||
struct kmscon_vt *vt = data;
|
||||
|
||||
if (!vt || vt->fd < 0)
|
||||
return;
|
||||
|
||||
/* we ignore input from the VT because we get it from evdev */
|
||||
tcflush(vt->fd, TCIFLUSH);
|
||||
}
|
||||
|
||||
static int open_tty(int id)
|
||||
{
|
||||
int fd;
|
||||
char filename[16];
|
||||
|
||||
if (id == KMSCON_VT_NEW) {
|
||||
fd = open("/dev/tty0", O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
fd = open("/dev/tty1", O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
log_err("vt: cannot find unused tty\n");
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(fd, VT_OPENQRY, &id) || id <= 0) {
|
||||
close(fd);
|
||||
log_err("vt: cannot find unused tty\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "/dev/tty%d", id);
|
||||
filename[sizeof(filename) - 1] = 0;
|
||||
log_debug("vt: using tty %s\n", filename);
|
||||
|
||||
fd = open(filename, O_RDWR | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
log_err("vt: cannot open vt\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id)
|
||||
{
|
||||
struct termios raw_attribs;
|
||||
struct vt_mode mode;
|
||||
int ret, fd;
|
||||
sigset_t mask;
|
||||
|
||||
if (vt->fd >= 0)
|
||||
return -EALREADY;
|
||||
|
||||
fd = open_tty(id);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
vt->fd = fd;
|
||||
|
||||
if (tcgetattr(vt->fd, &vt->saved_attribs) < 0) {
|
||||
log_err("vt: cannot get terminal attributes\n");
|
||||
ret = -EFAULT;
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
/* Ignore control characters and disable echo */
|
||||
raw_attribs = vt->saved_attribs;
|
||||
cfmakeraw(&raw_attribs);
|
||||
|
||||
/* Fix up line endings to be normal (cfmakeraw hoses them) */
|
||||
raw_attribs.c_oflag |= OPOST | OCRNL;
|
||||
|
||||
if (tcsetattr(vt->fd, TCSANOW, &raw_attribs) < 0)
|
||||
log_warning("vt: cannot put terminal into raw mode\n");
|
||||
|
||||
if (ioctl(vt->fd, KDSETMODE, KD_GRAPHICS)) {
|
||||
log_err("vt: cannot set graphics mode\n");
|
||||
ret = -errno;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
memset(&mode, 0, sizeof(mode));
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGUSR1;
|
||||
mode.acqsig = SIGUSR2;
|
||||
|
||||
if (ioctl(vt->fd, VT_SETMODE, &mode)) {
|
||||
log_err("vt: cannot take control of vt handling\n");
|
||||
ret = -errno;
|
||||
goto err_text;
|
||||
}
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigaddset(&mask, SIGUSR2);
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
err_text:
|
||||
ioctl(vt->fd, KDSETMODE, KD_TEXT);
|
||||
err_reset:
|
||||
tcsetattr(vt->fd, TCSANOW, &vt->saved_attribs);
|
||||
err_fd:
|
||||
close(vt->fd);
|
||||
vt->fd = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kmscon_vt_close(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt || vt->fd < 0)
|
||||
return;
|
||||
|
||||
ioctl(vt->fd, KDSETMODE, KD_TEXT);
|
||||
tcsetattr(vt->fd, TCSANOW, &vt->saved_attribs);
|
||||
|
||||
kmscon_vt_disconnect_eloop(vt);
|
||||
close(vt->fd);
|
||||
vt->fd = -1;
|
||||
}
|
||||
|
||||
int kmscon_vt_connect_eloop(struct kmscon_vt *vt, struct kmscon_eloop *loop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!vt || !loop || vt->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (vt->sig1 || vt->sig2)
|
||||
return -EALREADY;
|
||||
|
||||
ret = kmscon_eloop_new_signal(loop, &vt->sig1, SIGUSR1, vt_leave,
|
||||
vt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kmscon_eloop_new_signal(loop, &vt->sig2, SIGUSR2, vt_enter,
|
||||
vt);
|
||||
if (ret)
|
||||
goto err_sig1;
|
||||
|
||||
ret = kmscon_eloop_new_fd(loop, &vt->efd, vt->fd, KMSCON_READABLE,
|
||||
vt_input, vt);
|
||||
if (ret)
|
||||
goto err_sig2;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sig2:
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
vt->sig2 = NULL;
|
||||
err_sig1:
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
vt->sig1 = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kmscon_vt_disconnect_eloop(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt)
|
||||
return;
|
||||
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
kmscon_eloop_rm_fd(vt->efd);
|
||||
vt->sig1 = NULL;
|
||||
vt->sig2 = NULL;
|
||||
vt->efd = NULL;
|
||||
}
|
67
src/vt.h
Normal file
67
src/vt.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* kmscon - VT compatibility layer
|
||||
*
|
||||
* Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
|
||||
* Copyright (c) 2011 University of Tuebingen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VT compatibility
|
||||
* If the kmscon application runs in a VT we need to react on VT switch events
|
||||
* to allow other applications to access the DRM. This is only needed as long as
|
||||
* we run in a VT. In the future we will be able to disable all VTs and run as
|
||||
* service daemon. We then need another way to switch between graphical
|
||||
* applications, though.
|
||||
*/
|
||||
|
||||
#ifndef KMSCON_VT_H
|
||||
#define KMSCON_VT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "eloop.h"
|
||||
|
||||
struct kmscon_vt;
|
||||
typedef bool (*kmscon_vt_cb) (struct kmscon_vt *vt, int action, void *data);
|
||||
|
||||
enum kmscon_vt_action {
|
||||
KMSCON_VT_ENTER,
|
||||
KMSCON_VT_LEAVE,
|
||||
};
|
||||
|
||||
enum kmscon_vt_id {
|
||||
KMSCON_VT_CUR = 0,
|
||||
KMSCON_VT_NEW = -1,
|
||||
};
|
||||
|
||||
int kmscon_vt_new(struct kmscon_vt **out, kmscon_vt_cb cb, void *data);
|
||||
void kmscon_vt_ref(struct kmscon_vt *vt);
|
||||
void kmscon_vt_unref(struct kmscon_vt *vt);
|
||||
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id);
|
||||
void kmscon_vt_close(struct kmscon_vt *vt);
|
||||
|
||||
int kmscon_vt_connect_eloop(struct kmscon_vt *vt, struct kmscon_eloop *loop);
|
||||
void kmscon_vt_disconnect_eloop(struct kmscon_vt *vt);
|
||||
|
||||
#endif /* KMSCON_VT_H */
|
Loading…
x
Reference in New Issue
Block a user