fc5c27
>From d98187ff877341b5db5ca7f9d50b238d5936052b Mon Sep 17 00:00:00 2001
5e10b1
From: Hans de Goede <hdegoede@redhat.com>
5e10b1
Date: Thu, 21 Jul 2011 15:36:40 +0200
fc5c27
Subject: [PATCH 25/28] spice-qemu-char: Generate chardev open/close events
5e10b1
5e10b1
Define a state callback and make that generate chardev open/close events when
5e10b1
called by the spice-server.
5e10b1
5e10b1
Note that for all but the newest spice-server versions (which have a fix for
5e10b1
this) the code ignores these events for a spicevmc with a subtype of vdagent,
5e10b1
this subtype specific knowledge is undesirable, but unavoidable for now, see:
5e10b1
http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
5e10b1
5e10b1
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
5e10b1
---
fc5c27
 spice-qemu-char.c |   35 ++++++++++++++++++++++++++++++++++-
fc5c27
 1 files changed, 34 insertions(+), 1 deletions(-)
5e10b1
5e10b1
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
fc5c27
index 2b8aec4..d55e74a 100644
5e10b1
--- a/spice-qemu-char.c
5e10b1
+++ b/spice-qemu-char.c
fc5c27
@@ -89,11 +89,39 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
5e10b1
     return bytes;
5e10b1
 }
5e10b1
 
5e10b1
+static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
5e10b1
+{
5e10b1
+    SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
5e10b1
+
5e10b1
+#if SPICE_SERVER_VERSION < 0x000901
5e10b1
+    /*
5e10b1
+     * spice-server calls the state callback for the agent channel when the
5e10b1
+     * spice client connects / disconnects. Given that not the client but
5e10b1
+     * the server is doing the parsing of the messages this is wrong as the
5e10b1
+     * server is still listening. Worse, this causes the parser in the server
5e10b1
+     * to go out of sync, so we ignore state calls for subtype vdagent
5e10b1
+     * spicevmc chardevs. For the full story see:
5e10b1
+     * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
5e10b1
+     */
5e10b1
+    if (strcmp(sin->subtype, "vdagent") == 0) {
5e10b1
+        return;
5e10b1
+    }
5e10b1
+#endif
5e10b1
+
5e10b1
+    if ((scd->chr->opened && connected) ||
5e10b1
+        (!scd->chr->opened && !connected)) {
5e10b1
+        return;
5e10b1
+    }
5e10b1
+
fc5c27
+    qemu_chr_event(scd->chr, connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
5e10b1
+}
5e10b1
+
5e10b1
 static SpiceCharDeviceInterface vmc_interface = {
5e10b1
     .base.type          = SPICE_INTERFACE_CHAR_DEVICE,
5e10b1
     .base.description   = "spice virtual channel char device",
5e10b1
     .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
5e10b1
     .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
5e10b1
+    .state              = vmc_state,
5e10b1
     .write              = vmc_write,
5e10b1
     .read               = vmc_read,
5e10b1
 };
fc5c27
@@ -222,7 +250,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
5e10b1
     chr->chr_guest_close = spice_chr_guest_close;
5e10b1
     s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
5e10b1
 
5e10b1
-    qemu_chr_generic_open(chr);
5e10b1
+#if SPICE_SERVER_VERSION < 0x000901
5e10b1
+    /* See comment in vmc_state() */
5e10b1
+    if (strcmp(subtype, "vdagent") == 0) {
5e10b1
+        qemu_chr_generic_open(chr);
5e10b1
+    }
5e10b1
+#endif
5e10b1
 
5e10b1
     *_chr = chr;
5e10b1
     return 0;
5e10b1
-- 
5e10b1
1.7.5.1
5e10b1