[Spice-devel] [PATCH xf86-video-qxl v2 07/11] xspice: add uinput support to vdagent support

Alon Levy alevy at redhat.com
Sun Sep 8 05:11:49 PDT 2013


Signed-off-by: Alon Levy <alevy at redhat.com>
---
 src/Makefile.am        |   2 +
 src/qxl.h              |   1 +
 src/qxl_driver.c       |   3 ++
 src/spiceqxl_uinput.c  | 124 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/spiceqxl_uinput.h  |   8 ++++
 src/spiceqxl_vdagent.c |   2 +
 6 files changed, 140 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..443f931
--- /dev/null
+++ b/src/spiceqxl_uinput.c
@@ -0,0 +1,124 @@
+#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);
+    if (n == -1) {
+        if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
+            fprintf(stderr, "spice: uinput read failed: %s\n", strerror(errno));
+        }
+        return;
+    }
+    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 4b029bd..fdeddd3 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;
@@ -165,4 +166,5 @@ void spiceqxl_vdagent_init(qxl_screen_t *qxl)
 
     vdagent_sin.base.base.sif = &vmc_interface.base;
     spice_server_add_interface(qxl->spice_server, &vdagent_sin.base.base);
+    spiceqxl_uinput_init(qxl);
 }
-- 
1.8.3.1



More information about the Spice-devel mailing list