Signed-off-by: Alon Levy <alevy@xxxxxxxxxx> --- src/Makefile.am | 2 + src/qxl.h | 1 + src/qxl_driver.c | 3 ++ src/spiceqxl_uinput.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ src/spiceqxl_uinput.h | 8 ++++ src/spiceqxl_vdagent.c | 2 + 6 files changed, 134 insertions(+) create mode 100644 src/spiceqxl_uinput.c create mode 100644 src/spiceqxl_uinput.h diff --git a/src/Makefile.am b/src/Makefile.am index c6e6dcd..edc2f0b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,8 @@ spiceqxl_drv_la_SOURCES = \ spiceqxl_display.h \ spiceqxl_vdagent.c \ spiceqxl_vdagent.h \ + spiceqxl_uinput.c \ + spiceqxl_uinput.h \ spiceqxl_audio.c \ spiceqxl_audio.h \ spiceqxl_inputs.c \ diff --git a/src/qxl.h b/src/qxl.h index b1ba2e9..2d3a6ee 100644 --- a/src/qxl.h +++ b/src/qxl.h @@ -136,6 +136,7 @@ enum { OPTION_SPICE_PLAYBACK_FIFO_DIR, OPTION_SPICE_VDAGENT_ENABLED, OPTION_SPICE_VDAGENT_VIRTIO_PATH, + OPTION_SPICE_VDAGENT_UINPUT_PATH, #endif OPTION_COUNT, }; diff --git a/src/qxl_driver.c b/src/qxl_driver.c index 00736a2..a27d4fa 100644 --- a/src/qxl_driver.c +++ b/src/qxl_driver.c @@ -69,6 +69,7 @@ static char filter_str[] = "filter"; static char auto_str[] = "auto"; static char auto_glz_str[] = "auto_glz"; static char spice_vdagent_virtio_path_default[] = "/tmp/xspice-virtio"; +static char spice_vdagent_uinput_path_default[] = "/tmp/xspice-uinput"; #endif static char driver_name[] = QXL_DRIVER_NAME; const OptionInfoRec DefaultOptions[] = @@ -139,6 +140,8 @@ const OptionInfoRec DefaultOptions[] = "SpiceVdagentEnabled", OPTV_BOOLEAN, {0}, FALSE}, { OPTION_SPICE_VDAGENT_VIRTIO_PATH, "SpiceVdagentVirtioPath", OPTV_STRING, {.str = spice_vdagent_virtio_path_default}, FALSE}, + { OPTION_SPICE_VDAGENT_UINPUT_PATH, + "SpiceVdagentUinputPath", OPTV_STRING, {.str = spice_vdagent_uinput_path_default}, FALSE}, #endif { -1, NULL, OPTV_NONE, {0}, FALSE } diff --git a/src/spiceqxl_uinput.c b/src/spiceqxl_uinput.c new file mode 100644 index 0000000..ec927ad --- /dev/null +++ b/src/spiceqxl_uinput.c @@ -0,0 +1,118 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> + +#include <linux/input.h> +#include <linux/uinput.h> + +#include "qxl_option_helpers.h" +#include "spiceqxl_inputs.h" + +#include "spiceqxl_uinput.h" + +static const char *uinput_filename; +static int uinput_fd; +static struct input_event inp_event; +static int offset; + +static void spiceqxl_uinput_read_cb(int fd, int event, void *opaque) +{ + int n; + static int x = -1; + static int y = -1; + static int buttons_state = 0; + int button = -1; + + n = read(uinput_fd, (char *)&inp_event + offset, sizeof(inp_event) - offset); + offset += n; + if (offset < sizeof(inp_event)) { + return; + } + offset = 0; + switch (inp_event.type) { + case EV_KEY: + /* XXX Here we hardcode vdagent-uinput.c mapping since we don't support ioctls. + * We could replace the ioctls with additional non uinput messages + * used in vdagentd fake uinput mode. */ + switch (inp_event.code) { + case BTN_LEFT: + button = 1 << 0; + break; + case BTN_MIDDLE: + button = 1 << 1; + break; + case BTN_RIGHT: + button = 1 << 2; + break; + } + if (inp_event.value > 0) { + buttons_state |= button; + } else { + buttons_state &= ~button; + } + spiceqxl_tablet_buttons(buttons_state); + break; + case EV_REL: + button = 1; + if (inp_event.value == 1) { + button = 1 << 3; + } else { + button = 1 << 4; + } + buttons_state |= button; + spiceqxl_tablet_buttons(buttons_state); + buttons_state &= ~button; + spiceqxl_tablet_buttons(buttons_state); + break; + case EV_ABS: + switch (inp_event.code) { + case ABS_X: + x = inp_event.value; + break; + case ABS_Y: + y = inp_event.value; + break; + default: + fprintf(stderr, "%s: unknown axis %d, ignoring\n", __func__, inp_event.code); + return; + break; + } + spiceqxl_tablet_position(x, y, buttons_state); + break; + } +} + +void spiceqxl_uinput_init(qxl_screen_t *qxl) +{ + int ret; + int enabled; + + uinput_filename = get_str_option(qxl->options, OPTION_SPICE_VDAGENT_UINPUT_PATH, + "XSPICE_VDAGENT_UINPUT_PATH"); + enabled = get_bool_option(qxl->options, OPTION_SPICE_VDAGENT_ENABLED, "XSPICE_VDAGENT_ENABLED"); + + if (!enabled || uinput_filename == NULL) { + return; + } + ret = mkfifo(uinput_filename, 0666); + if (ret != 0) { + fprintf(stderr, "spice: failed to create uinput fifo %s: %s\n", + uinput_filename, strerror(errno)); + return; + } + uinput_fd = open(uinput_filename, O_RDONLY | O_NONBLOCK, 0666); + if (uinput_fd == -1) { + fprintf(stderr, "spice: failed creating uinput file %s: %s\n", + uinput_filename, strerror(errno)); + return; + } + qxl->core->watch_add(uinput_fd, SPICE_WATCH_EVENT_READ, spiceqxl_uinput_read_cb, qxl); + spice_server_set_agent_mouse(qxl->spice_server, 1); +} diff --git a/src/spiceqxl_uinput.h b/src/spiceqxl_uinput.h new file mode 100644 index 0000000..59c704c --- /dev/null +++ b/src/spiceqxl_uinput.h @@ -0,0 +1,8 @@ +#ifndef SPICEQXL_UINPUT_H +#define SPICEQXL_UINPUT_H + +#include "qxl.h" + +void spiceqxl_uinput_init(qxl_screen_t *qxl); + +#endif diff --git a/src/spiceqxl_vdagent.c b/src/spiceqxl_vdagent.c index c00b34c..963b168 100644 --- a/src/spiceqxl_vdagent.c +++ b/src/spiceqxl_vdagent.c @@ -10,6 +10,7 @@ #include "qxl_option_helpers.h" +#include "spiceqxl_uinput.h" #include "spiceqxl_vdagent.h" static const char *vdagent_virtio_filename; @@ -175,4 +176,5 @@ void spiceqxl_vdagent_init(qxl_screen_t *qxl) vdagent_sin.base.sif = &vmc_interface.base; spice_server_add_interface(qxl->spice_server, &vdagent_sin.base); + spiceqxl_uinput_init(qxl); } -- 1.8.3.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel