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

Kristian Høgsberg krh at bitplanet.net
Mon Dec 6 08:12:28 PST 2010


On Mon, Nov 29, 2010 at 2:35 PM, Yuval Fledel <yuvalfl at gmail.com> wrote:
> 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

Yeah, I think we can do that, but I'd like to split it into evdev.c
and tty.c in two patches.  I'd like to see struct tty and struct
evdev, defined in compositor.h so that the compositors can just embed
the struct in their compositor subclass (struct drm_compositor, for
example).  Then just do evdev_init(&ec->base, &ec->evdev) and
tty_init(&ec->base, &ev->tty).  The init functions don't need to take
both &ec->base and ec, and they can just get the main loop by calling
wl_display_get_event_loop() instead of passing that as a parameter.

Kristian

>  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
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>


More information about the wayland-devel mailing list