summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2013-09-02 17:28:50 +0300
committerAlon Levy <alevy@redhat.com>2013-09-08 15:10:16 +0300
commit0bd94ebdfdee55580566ef7b4831f777a227baab (patch)
tree21206f16cc42eaddacd77d6ed342ee48bfcf94b9
parentc246fd9e5c8ff9f0ed428bdd97a248667601ff5a (diff)
xspice: add uinput support to vdagent support
Signed-off-by: Alon Levy <alevy@redhat.com>
-rw-r--r--src/Makefile.am2
-rw-r--r--src/qxl.h1
-rw-r--r--src/qxl_driver.c3
-rw-r--r--src/spiceqxl_uinput.c124
-rw-r--r--src/spiceqxl_uinput.h8
-rw-r--r--src/spiceqxl_vdagent.c2
6 files changed, 140 insertions, 0 deletions
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);
}