[PATCH 1/3] Factor evdev and TTY out of the DRM backend.

Yuval Fledel yuvalfl at gmail.com
Mon Nov 29 11:35:46 PST 2010


evdev and TTY handling are not specific for DRM, and could be
useful for Linux framebuffer too.
This patch will move them to evdev.c

---
 compositor/Makefile.am      |    1 +
 compositor/compositor-drm.c |  296 +---------------------------------
 compositor/compositor.h     |   15 ++
 compositor/evdev.c          |  377 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 398 insertions(+), 291 deletions(-)
 create mode 100644 compositor/evdev.c

diff --git a/compositor/Makefile.am b/compositor/Makefile.am
index f8f2307..bcb6cf3 100644
--- a/compositor/Makefile.am
+++ b/compositor/Makefile.am
@@ -20,6 +20,7 @@ compositor_SOURCES =				\
 	screenshooter-protocol.c		\
 	screenshooter-server-protocol.h		\
 	drm.c					\
+	evdev.c					\
 	shm.c

 udevrulesddir = $(sysconfdir)/udev/rules.d
diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c
index e3e9b6f..db5f1e4 100644
--- a/compositor/compositor-drm.c
+++ b/compositor/compositor-drm.c
@@ -42,16 +42,8 @@ struct drm_compositor {
 	struct udev *udev;
 	struct wl_event_source *drm_source;

-	struct wl_event_source *term_signal_source;
-
         /* tty handling state */
-	int tty_fd;
-	uint32_t vt_active : 1;
-
-	struct termios terminal_attributes;
-	struct wl_event_source *tty_input_source;
-	struct wl_event_source *enter_vt_source;
-	struct wl_event_source *leave_vt_source;
+	struct tty_evdev *ttyevdev;
 };

 struct drm_output {
@@ -66,197 +58,6 @@ struct drm_output {
 	uint32_t current;	
 };

-struct drm_input {
-	struct wlsc_input_device base;
-};
-
-struct evdev_input_device {
-	struct drm_input *master;
-	struct wl_event_source *source;
-	int tool, new_x, new_y;
-	int base_x, base_y;
-	int fd;
-};
-
-static void evdev_input_device_data(int fd, uint32_t mask, void *data)
-{
-	struct drm_compositor *c;
-	struct evdev_input_device *device = data;
-	struct input_event ev[8], *e, *end;
-	int len, value, dx, dy, absolute_event;
-	int x, y;
-	uint32_t time;
-
-	c = (struct drm_compositor *) device->master->base.ec;
-	if (!c->vt_active)
-		return;
-
-	dx = 0;
-	dy = 0;
-	absolute_event = 0;
-	x = device->master->base.x;
-	y = device->master->base.y;
-
-	len = read(fd, &ev, sizeof ev);
-	if (len < 0 || len % sizeof e[0] != 0) {
-		/* FIXME: handle error... reopen device? */;
-		return;
-	}
-
-	e = ev;
-	end = (void *) ev + len;
-	for (e = ev; e < end; e++) {
-		/* Get the signed value, earlier kernels had this as unsigned */
-		value = e->value;
-		time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
-
-		switch (e->type) {
-		case EV_REL:
-			switch (e->code) {
-			case REL_X:
-				dx += value;
-				break;
-
-			case REL_Y:
-				dy += value;
-				break;
-			}
-			break;
-
-		case EV_ABS:
-		        absolute_event = 1;
-			switch (e->code) {
-			case ABS_X:
-				if (device->new_x) {
-					device->base_x = x - value;
-					device->new_x = 0;
-				}
-				x = device->base_x + value;
-				break;
-			case ABS_Y:
-				if (device->new_y) {
-					device->base_y = y - value;
-					device->new_y = 0;
-				}
-				y = device->base_y + value;
-				break;
-			}
-			break;
-
-		case EV_KEY:
-			if (value == 2)
-				break;
-
-			switch (e->code) {
-			case BTN_TOUCH:
-			case BTN_TOOL_PEN:
-			case BTN_TOOL_RUBBER:
-			case BTN_TOOL_BRUSH:
-			case BTN_TOOL_PENCIL:
-			case BTN_TOOL_AIRBRUSH:
-			case BTN_TOOL_FINGER:
-			case BTN_TOOL_MOUSE:
-			case BTN_TOOL_LENS:
-				if (device->tool == 0 && value) {
-					device->new_x = 1;
-					device->new_y = 1;
-				}
-				device->tool = value ? e->code : 0;
-				break;
-
-			case BTN_LEFT:
-			case BTN_RIGHT:
-			case BTN_MIDDLE:
-			case BTN_SIDE:
-			case BTN_EXTRA:
-			case BTN_FORWARD:
-			case BTN_BACK:
-			case BTN_TASK:
-				notify_button(&device->master->base,
-					      time, e->code, value);
-				break;
-
-			default:
-				notify_key(&device->master->base,
-					   time, e->code, value);
-				break;
-			}
-		}
-	}
-
-	if (dx != 0 || dy != 0)
-		notify_motion(&device->master->base, time, x + dx, y + dy);
-	if (absolute_event && device->tool)
-		notify_motion(&device->master->base, time, x, y);
-}
-
-static struct evdev_input_device *
-evdev_input_device_create(struct drm_input *master,
-			  struct wl_display *display, const char *path)
-{
-	struct evdev_input_device *device;
-	struct wl_event_loop *loop;
-
-	device = malloc(sizeof *device);
-	if (device == NULL)
-		return NULL;
-
-	device->tool = 1;
-	device->new_x = 1;
-	device->new_y = 1;
-	device->master = master;
-
-	device->fd = open(path, O_RDONLY);
-	if (device->fd < 0) {
-		free(device);
-		fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
-		return NULL;
-	}
-
-	loop = wl_display_get_event_loop(display);
-	device->source = wl_event_loop_add_fd(loop, device->fd,
-					      WL_EVENT_READABLE,
-					      evdev_input_device_data, device);
-	if (device->source == NULL) {
-		close(device->fd);
-		free(device);
-		return NULL;
-	}
-
-	return device;
-}
-
-static void
-drm_input_create(struct drm_compositor *c)
-{
-	struct drm_input *input;
-	struct udev_enumerate *e;
-        struct udev_list_entry *entry;
-	struct udev_device *device;
-	const char *path;
-
-	input = malloc(sizeof *input);
-	if (input == NULL)
-		return;
-
-	memset(input, 0, sizeof *input);
-	wlsc_input_device_init(&input->base, &c->base);
-
-	e = udev_enumerate_new(c->udev);
-	udev_enumerate_add_match_subsystem(e, "input");
-	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
-        udev_enumerate_scan_devices(e);
-        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
-		path = udev_list_entry_get_name(entry);
-		device = udev_device_new_from_syspath(c->udev, path);
-		evdev_input_device_create(input, c->base.wl_display,
-					  udev_device_get_devnode(device));
-	}
-        udev_enumerate_unref(e);
-
-	c->base.input_device = &input->base;
-}
-
 static void
 drm_compositor_present(struct wlsc_compositor *ec)
 {
@@ -498,7 +299,7 @@ create_outputs(struct drm_compositor *ec, int
option_connector)
 	return 0;
 }

-static void on_enter_vt(int signal_number, void *data)
+static void on_enter_vt(void *data)
 {
 	struct drm_compositor *ec = data;
 	struct drm_output *output;
@@ -513,12 +314,6 @@ static void on_enter_vt(int signal_number, void *data)

 	fprintf(stderr, "enter vt\n");

-	ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
-	ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
-	if (ret)
-		fprintf(stderr, "failed to set KD_GRAPHICS mode on console: %m\n");
-	ec->vt_active = 1;
-
 	wl_list_for_each(output, &ec->base.output_list, base.link) {
 		ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
 				     output->fb_id[output->current ^ 1], 0, 0,
@@ -530,7 +325,7 @@ static void on_enter_vt(int signal_number, void *data)
 	}
 }

-static void on_leave_vt(int signal_number, void *data)
+static void on_leave_vt(void *data)
 {
 	struct drm_compositor *ec = data;
 	int ret;
@@ -541,86 +336,6 @@ static void on_leave_vt(int signal_number, void *data)
 		kill(0, SIGTERM);
 		return;
 	}
-
-	ioctl (ec->tty_fd, VT_RELDISP, 1);
-	ret = ioctl(ec->tty_fd, KDSETMODE, KD_TEXT);
-	if (ret)
-		fprintf(stderr, "failed to set KD_TEXT mode on console: %m\n");
-	ec->vt_active = 0;
-}
-
-static void
-on_tty_input(int fd, uint32_t mask, void *data)
-{
-	struct drm_compositor *ec = data;
-
-	/* Ignore input to tty.  We get keyboard events from evdev
-	 */
-	tcflush(ec->tty_fd, TCIFLUSH);
-}
-
-static void on_term_signal(int signal_number, void *data)
-{
-	struct drm_compositor *ec = data;
-
-	if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
-		fprintf(stderr, "could not restore terminal to canonical mode\n");
-
-	exit(0);
-}
-
-static int setup_tty(struct drm_compositor *ec, struct wl_event_loop *loop)
-{
-	struct termios raw_attributes;
-	struct vt_mode mode = { 0 };
-	int ret;
-
-	ec->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
-	if (ec->tty_fd <= 0) {
-		fprintf(stderr, "failed to open active tty: %m\n");
-		return -1;
-	}
-
-	if (tcgetattr(ec->tty_fd, &ec->terminal_attributes) < 0) {
-		fprintf(stderr, "could not get terminal attributes: %m\n");
-		return -1;
-	}
-
-	/* Ignore control characters and disable echo */
-	raw_attributes = ec->terminal_attributes;
-	cfmakeraw(&raw_attributes);
-
-	/* Fix up line endings to be normal (cfmakeraw hoses them) */
-	raw_attributes.c_oflag |= OPOST | OCRNL;
-
-	if (tcsetattr(ec->tty_fd, TCSANOW, &raw_attributes) < 0)
-		fprintf(stderr, "could not put terminal into raw mode: %m\n");
-
-	ec->term_signal_source =
-		wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec);
-
-	ec->tty_input_source =
-		wl_event_loop_add_fd(loop, ec->tty_fd,
-				     WL_EVENT_READABLE, on_tty_input, ec);
-
-	ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
-	if (ret)
-		fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
-
-	ec->vt_active = 1;
-	mode.mode = VT_PROCESS;
-	mode.relsig = SIGUSR1;
-	mode.acqsig = SIGUSR2;
-	if (!ioctl(ec->tty_fd, VT_SETMODE, &mode) < 0) {
-		fprintf(stderr, "failed to take control of vt handling\n");
-	}
-
-	ec->leave_vt_source =
-		wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, ec);
-	ec->enter_vt_source =
-		wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, ec);
-
-	return 0;
 }

 static int
@@ -684,13 +399,12 @@ drm_compositor_create(struct wl_display
*display, int connector)
 		return NULL;
 	}

-	drm_input_create(ec);
-
 	loop = wl_display_get_event_loop(ec->base.wl_display);
 	ec->drm_source =
 		wl_event_loop_add_fd(loop, ec->base.drm.fd,
 				     WL_EVENT_READABLE, on_drm_input, ec);
-	setup_tty(ec, loop);
+	ec->ttyevdev = evdev_tty_setup(&ec->base, loop, ec->udev,
on_enter_vt, on_leave_vt, ec);
+
 	ec->base.authenticate = drm_authenticate;
 	ec->base.present = drm_compositor_present;
 	ec->base.focus = 1;
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 85535f3..4280a33 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -40,6 +40,7 @@ struct wlsc_matrix {
 };

 struct wlsc_surface;
+struct tty_evdev;

 struct wlsc_listener {
 	struct wl_list link;
@@ -228,12 +229,26 @@ struct wl_buffer *
 wl_buffer_create_drm(struct wlsc_compositor *compositor,
 		     struct wl_visual *visual);

+/* Backends */
+
 struct wlsc_compositor *
 x11_compositor_create(struct wl_display *display, int width, int height);

 struct wlsc_compositor *
 drm_compositor_create(struct wl_display *display, int connector);

+/* TTY and evdev */
+
+typedef void (* on_enter_vt_t)(void *data);
+typedef void (* on_leave_vt_t)(void *data);
+
+struct tty_evdev *evdev_tty_setup(struct wlsc_compositor *ec,
+		struct wl_event_loop *loop, struct udev *udev,
+		on_enter_vt_t on_enter, on_leave_vt_t on_leave,
+		void *callback_data);
+
+/* Extensions */
+
 void
 screenshooter_create(struct wlsc_compositor *ec);

diff --git a/compositor/evdev.c b/compositor/evdev.c
new file mode 100644
index 0000000..8ff23ce
--- /dev/null
+++ b/compositor/evdev.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright ֲ© 2008-2010 Kristian Hֳ¸gsberg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <signal.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <linux/input.h>
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "compositor.h"
+
+struct tty_evdev {
+	struct wlsc_compositor *ec;
+	struct wl_list input_devices;
+
+	/* tty handling state */
+	int tty_fd;
+	uint32_t vt_active : 1;
+	struct termios terminal_attributes;
+	struct wl_event_source *term_signal_source;
+	struct wl_event_source *tty_input_source;
+	struct wl_event_source *enter_vt_source;
+	struct wl_event_source *leave_vt_source;
+
+	on_enter_vt_t on_enter;
+	on_leave_vt_t on_leave;
+	void *callback_data;
+};
+
+struct evdev_input_device {
+	struct wlsc_input_device *master;
+	struct tty_evdev *tty_evdev;
+	struct wl_event_source *source;
+	int tool, new_x, new_y;
+	int base_x, base_y;
+	int fd;
+};
+
+static void evdev_input_device_data(int fd, uint32_t mask, void *data)
+{
+	struct evdev_input_device *device = data;
+	struct input_event ev[8], *e, *end;
+	int len, value, dx, dy, absolute_event;
+	int x, y;
+	uint32_t time;
+
+	dx = 0;
+	dy = 0;
+	absolute_event = 0;
+	x = device->master->x;
+	y = device->master->y;
+
+	len = read(fd, &ev, sizeof ev);
+	if (len < 0 || len % sizeof e[0] != 0) {
+		/* FIXME: handle error... reopen device? */;
+		return;
+	}
+
+	/* evdev events aren't targeted only to the current VT */
+	if (!device->tty_evdev->vt_active)
+		return;
+
+	e = ev;
+	end = (void *) ev + len;
+	for (e = ev; e < end; e++) {
+		/* Get the signed value, earlier kernels had this as unsigned */
+		value = e->value;
+		time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
+
+		switch (e->type) {
+		case EV_REL:
+			switch (e->code) {
+			case REL_X:
+				dx += value;
+				break;
+
+			case REL_Y:
+				dy += value;
+				break;
+			}
+			break;
+
+		case EV_ABS:
+			absolute_event = 1;
+			switch (e->code) {
+			case ABS_X:
+				if (device->new_x) {
+					device->base_x = x - value;
+					device->new_x = 0;
+				}
+				x = device->base_x + value;
+				break;
+			case ABS_Y:
+				if (device->new_y) {
+					device->base_y = y - value;
+					device->new_y = 0;
+				}
+				y = device->base_y + value;
+				break;
+			}
+			break;
+
+		case EV_KEY:
+			if (value == 2)
+				break;
+
+			switch (e->code) {
+			case BTN_TOUCH:
+			case BTN_TOOL_PEN:
+			case BTN_TOOL_RUBBER:
+			case BTN_TOOL_BRUSH:
+			case BTN_TOOL_PENCIL:
+			case BTN_TOOL_AIRBRUSH:
+			case BTN_TOOL_FINGER:
+			case BTN_TOOL_MOUSE:
+			case BTN_TOOL_LENS:
+				if (device->tool == 0 && value) {
+					device->new_x = 1;
+					device->new_y = 1;
+				}
+				device->tool = value ? e->code : 0;
+				break;
+
+			case BTN_LEFT:
+			case BTN_RIGHT:
+			case BTN_MIDDLE:
+			case BTN_SIDE:
+			case BTN_EXTRA:
+			case BTN_FORWARD:
+			case BTN_BACK:
+			case BTN_TASK:
+				notify_button(device->master,
+					      time, e->code, value);
+				break;
+
+			default:
+				notify_key(device->master,
+					   time, e->code, value);
+				break;
+			}
+		}
+	}
+
+	if (dx != 0 || dy != 0)
+		notify_motion(device->master, time, x + dx, y + dy);
+	if (absolute_event && device->tool)
+		notify_motion(device->master, time, x, y);
+}
+
+static struct evdev_input_device *
+evdev_input_device_create(struct tty_evdev *te,
+			  struct wlsc_input_device *master,
+			  struct wl_display *display, const char *path)
+{
+	struct evdev_input_device *device;
+	struct wl_event_loop *loop;
+
+	if (path == NULL)
+		return NULL;
+
+	device = malloc(sizeof *device);
+	if (device == NULL)
+		return NULL;
+
+	device->tool = 1;
+	device->new_x = 1;
+	device->new_y = 1;
+	device->master = master;
+	device->tty_evdev = te;
+
+	device->fd = open(path, O_RDONLY);
+	if (device->fd < 0) {
+		free(device);
+		fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
+		return NULL;
+	}
+
+	loop = wl_display_get_event_loop(display);
+	device->source = wl_event_loop_add_fd(loop, device->fd,
+					      WL_EVENT_READABLE,
+					      evdev_input_device_data, device);
+	if (device->source == NULL) {
+		close(device->fd);
+		free(device);
+		return NULL;
+	}
+
+	return device;
+}
+
+static void
+evdev_input_init(struct tty_evdev *te, struct udev *udev)
+{
+	struct wlsc_compositor *c = te->ec;
+	struct wlsc_input_device *input;
+	struct udev_enumerate *e;
+	struct udev_list_entry *entry;
+	struct udev_device *device;
+	const char *path;
+
+	input = malloc(sizeof *input);
+	if (input == NULL)
+		return;
+
+	memset(input, 0, sizeof *input);
+	wlsc_input_device_init(input, c);
+
+	e = udev_enumerate_new(udev);
+	udev_enumerate_add_match_subsystem(e, "input");
+//	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
+	udev_enumerate_scan_devices(e);
+	udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+		path = udev_list_entry_get_name(entry);
+		device = udev_device_new_from_syspath(udev, path);
+		evdev_input_device_create(te, input, c->wl_display,
+					  udev_device_get_devnode(device));
+	}
+	udev_enumerate_unref(e);
+
+	c->input_device = input;
+}
+
+static void on_enter_vt(int signal_number, void *data)
+{
+	struct tty_evdev *te = data;
+	int ret;
+
+	ioctl(te->tty_fd, VT_RELDISP, VT_ACKACQ);
+	ret = ioctl(te->tty_fd, KDSETMODE, KD_GRAPHICS);
+	if (ret)
+		fprintf(stderr,
+			"failed to set KD_GRAPHICS mode on console: %m\n");
+	te->vt_active = 1;
+
+	if (te->on_enter != NULL)
+		(*te->on_enter)(te->callback_data);
+}
+
+static void on_leave_vt(int signal_number, void *data)
+{
+	struct tty_evdev *te = data;
+	int ret;
+
+	if (te->on_leave != NULL)
+		(*te->on_leave)(te->callback_data);
+
+	ioctl (te->tty_fd, VT_RELDISP, 1);
+	ret = ioctl(te->tty_fd, KDSETMODE, KD_TEXT);
+	if (ret)
+		fprintf(stderr,
+			"failed to set KD_TEXT mode on console: %m\n");
+	te->vt_active = 0;
+}
+
+static void
+on_tty_input(int fd, uint32_t mask, void *data)
+{
+	struct tty_evdev *te = data;
+
+	/* Ignore input to tty.  We get keyboard events from evdev. */
+	tcflush(te->tty_fd, TCIFLUSH);
+}
+
+static void on_term_signal(int signal_number, void *data)
+{
+	struct tty_evdev *te = data;
+
+	if (tcsetattr(te->tty_fd, TCSANOW, &te->terminal_attributes) < 0)
+		fprintf(stderr,
+			"Could not restore terminal to canonical mode\n");
+
+	exit(0);
+}
+
+static int setup_tty(struct tty_evdev *te, struct wl_event_loop *loop)
+{
+	struct termios raw_attributes;
+	struct vt_mode mode = { 0 };
+	int ret;
+
+	te->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
+	if (te->tty_fd <= 0) {
+		fprintf(stderr, "failed to open active tty: %m\n");
+		return -1;
+	}
+
+	if (tcgetattr(te->tty_fd, &te->terminal_attributes) < 0) {
+		fprintf(stderr, "could not get terminal attributes: %m\n");
+		return -1;
+	}
+
+	/* Ignore control characters and disable echo */
+	raw_attributes = te->terminal_attributes;
+	cfmakeraw(&raw_attributes);
+
+	/* Fix up line endings to be normal (cfmakeraw hoses them) */
+	raw_attributes.c_oflag |= OPOST | OCRNL;
+
+	if (tcsetattr(te->tty_fd, TCSANOW, &raw_attributes) < 0)
+		fprintf(stderr, "could not put terminal into raw mode: %m\n");
+
+	te->term_signal_source =
+		wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, te);
+
+	te->tty_input_source =
+		wl_event_loop_add_fd(loop, te->tty_fd,
+				     WL_EVENT_READABLE, on_tty_input, te);
+
+	ret = ioctl(te->tty_fd, KDSETMODE, KD_GRAPHICS);
+	if (ret)
+		fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
+
+	te->vt_active = 1;
+	mode.mode = VT_PROCESS;
+	mode.relsig = SIGUSR1;
+	mode.acqsig = SIGUSR2;
+	if (!ioctl(te->tty_fd, VT_SETMODE, &mode) < 0) {
+		fprintf(stderr, "failed to take control of vt handling\n");
+	}
+
+	te->leave_vt_source =
+		wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, te);
+	te->enter_vt_source =
+		wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, te);
+
+	return 0;
+}
+
+struct tty_evdev *evdev_tty_setup(struct wlsc_compositor *ec,
+		struct wl_event_loop *loop, struct udev *udev,
+		on_enter_vt_t on_enter, on_leave_vt_t on_leave,
+		void *callback_data)
+{
+	struct tty_evdev *te;
+
+	te = calloc(1, sizeof(*te));
+	if (te == NULL)
+		return NULL;
+
+	te->ec = ec;
+	te->on_enter = on_enter;
+	te->on_leave = on_leave;
+	te->callback_data = callback_data;
+	wl_list_init(&te->input_devices);
+
+	evdev_input_init(te, udev);
+	setup_tty(te, loop);
+
+	return te;
+}
-- 
1.7.1


More information about the wayland-devel mailing list