]> xenbits.xensource.com Git - xenclient/ioemu.git/commitdiff
Fix the switch.
authorJean Guyader <jean.guyader@eu.citrix.com>
Fri, 21 Nov 2008 16:00:02 +0000 (16:00 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Fri, 21 Nov 2008 16:00:02 +0000 (16:00 +0000)
  You can use the command node to switch the keyboard only or both
  (mouse/keyboard).

  If you switch the mouse and the keyboard it will also change the focus to
  the new vm.

  To switch only the keyboard:
    write into /local/domain/0/dom0_driver "keyboard slot-id"
  To switch mouse and keyboard:
    write into /local/domain/0/dom0_driver "switch slot-id"

  Each vm owns a slot-id. It's the value of the dom0-input config option.

dom0_driver.c
qemu-xen.h
xen-config-host.h
xenstore.c

index 4291f00ee10892d110af83d0bbfa57e1dd8ea64e..90fd78a40d830d90a37eca2835ca6066b1a17dd9 100644 (file)
@@ -25,6 +25,7 @@
 #include "qemu-common.h"
 #include "console.h"
 #include "qemu-timer.h"
+#include "qemu-xen.h"
 
 #include <sys/types.h>
 #include <linux/input.h>
 #include <errno.h>
 #include <string.h>
 #include <assert.h>
+#include <time.h>
 
 extern int vga_passthrough;
 
-void xenstore_watch_dom0_driver(const char *, const char *);
+static void dom0_driver_state_change(const char *path, void *opaque);
+static void dom0_driver_command(const char *path, void *opaque);
 
 #define DEBUG_DOM0_DRIVER       1
 #define EVENT_PATH              "/dev/input/event"
@@ -82,6 +85,7 @@ struct dom0_driver_xs_info
   int domid;
   int leaving_dir;
   int new_slot;
+  int timestamp;
 };
 
 static struct dom0_driver driver;
@@ -104,7 +108,7 @@ static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info,
     char        *str = NULL;
     char        path[128];
     int         val[10];
-    const char  *key[] = {"state", "domid", "new-slot"};
+    const char  *key[] = {"state", "domid", "new-slot", "timestamp"};
 
     memset(info, -1, sizeof (struct dom0_driver_xs_info));
     for (int i = 0; i < sizeof (key) / sizeof (key[0]); i++)
@@ -130,24 +134,27 @@ static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info,
     info->state = val[0];
     info->domid = val[1];
     info->new_slot = val[2];
+    info->timestamp = val[3];
 }
 
 static void dom0_driver_xs_write(const char *key, int val, int controller)
 {
-    char        path[128];
+    char        path[128], str[10];
 
     if (controller == DOM0_MOUSE)
         sprintf(path, "mouse/%s", key);
     if (controller == DOM0_KEYBOARD)
         sprintf(path, "keyboard/%s", key);
 
-    xenstore_write_dom0_driver(path, val);
+    sprintf(str, "%d", val);
+    xenstore_write_dom0_driver(path, str);
 }
 
 static int dom0_windows_key_switch(int code, int keycode)
 {
     int                         new_slot = 0;
     struct dom0_driver_xs_info  info;
+    char                        buff[128];
 
     dom0_driver_read_xs_info(&info, DOM0_MOUSE);
     if (info.state == 0)
@@ -177,14 +184,10 @@ static int dom0_windows_key_switch(int code, int keycode)
             default:
                 return 0;
         }
+        sprintf(buff, "switch %d", new_slot);
 
-        DEBUG("Write state = 0 inside xenstore\n");
-
-        dom0_driver_xs_write("new-slot", new_slot, DOM0_KEYBOARD);
-        dom0_driver_xs_write("new-slot", new_slot, DOM0_MOUSE);
-
-        dom0_driver_xs_write("state", 0, DOM0_KEYBOARD);
-        dom0_driver_xs_write("state", 0, DOM0_MOUSE);
+        DEBUG("Write \"%s\" into xenstore\n", buff);
+        xenstore_write_dom0_driver("command", buff);
 
         return 1;
     }
@@ -259,7 +262,7 @@ static void dom0_get_positions(int *positions)
     int *domids = NULL;
     int num;
     char *tmp;
-    unsigned long len;
+    unsigned int len;
     int pos = 0;
 
     memset(positions, 0, NB_SLOTS * 4);
@@ -390,7 +393,12 @@ static void dom0_gr_devices(int grab, int controller)
     if (controller == DOM0_MOUSE)
     {
         if (vga_passthrough)
-            xenstore_write_dom0_driver("blank", !grab);
+        {
+            char str[10];
+
+            sprintf(str, "%d", !grab);
+            xenstore_write_dom0_driver("blank", str);
+        }
         else
         {
             struct dom0_driver_xs_info  info;
@@ -425,12 +433,13 @@ static int dom0_dom_alive(int id)
 
 static int dom0_driver_failover_switch(void *opaque)
 {
-    struct dom0_driver_xs_info  info;
+    struct dom0_driver_xs_info  mouse, keyboard;
     int                         ret = 1;
 
-    dom0_driver_read_xs_info(&info, DOM0_MOUSE);
+    dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
+    dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
 
-    if (info.state == -1)
+    if (mouse.state == -1)
     {
         DEBUG("No state grab the device\n");
         dom0_gr_devices(1, DOM0_KEYBOARD);
@@ -439,14 +448,26 @@ static int dom0_driver_failover_switch(void *opaque)
     }
 
     /* The domain which has the focus crash */
-    if (!dom0_dom_alive(info.domid))
+    if (!dom0_dom_alive(mouse.domid))
     {
-        DEBUG("steal the focus from %d\n", info.domid);
+        DEBUG("steal the focus from %d\n", mouse.domid);
         dom0_gr_devices(1, DOM0_KEYBOARD);
         dom0_gr_devices(1, DOM0_MOUSE);
         goto out;
     }
 
+    /* The domain is still alive but nobody grab the device
+    ** on the other side after 3 secondes */
+    if (keyboard.state == 0 && keyboard.timestamp != -1 &&
+        (time(NULL) - keyboard.timestamp) > 3)
+        dom0_gr_devices(1, DOM0_KEYBOARD);
+    if (mouse.state == 0 && keyboard.timestamp == -1 &&
+        (time(NULL) - mouse.timestamp) > 3)
+    {
+        dom0_gr_devices(1, DOM0_MOUSE);
+        xenstore_write_dom0_driver("blank", "0");
+    }
+
     ret = 0;
 out:
     qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
@@ -514,11 +535,17 @@ static void dom0_driver_event_init(const char *str_arg)
     }
 
     if (vga_passthrough)
-        xenstore_write_dom0_driver("natif", domid);
+    {
+        char str[10];
+
+        sprintf(str, "%d", domid);
+        xenstore_write_dom0_driver("natif", str);
+    }
 
-    xenstore_watch_dom0_driver("mouse/state", "dom0_driver_keyboard_state");
-    xenstore_watch_dom0_driver("keyboard/state", "dom0_driver_mouse_state");
-    xenstore_watch_dom0_driver("blank", "dom0_driver_blank_done");
+    xenstore_watch_dom0_driver("mouse/state", dom0_driver_state_change, NULL);
+    xenstore_watch_dom0_driver("keyboard/state", dom0_driver_state_change, NULL);
+    xenstore_watch_dom0_driver("blank", dom0_driver_state_change, NULL);
+    xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
 
     /* Register the failover switch */
     driver.xs_timer = qemu_new_timer(rt_clock, dom0_driver_failover_switch, NULL);
@@ -558,6 +585,46 @@ static void dom0_driver_slots(int controller)
     }
 }
 
+static void dom0_driver_switch_controller(int slot, int controller)
+{
+    dom0_driver_xs_write("new-slot", slot, controller);
+    dom0_driver_xs_write("timestamp", time(NULL), controller);
+    dom0_driver_xs_write("state", 0, controller);
+}
+
+void dom0_driver_command(const char *path, void *opaque)
+{
+    char        *val = NULL;
+
+    val = xenstore_read(path);
+    if (val == NULL)
+        return;
+
+    if (!strncmp(val, "switch ", 7))
+    {
+        int slot = strtol(val + 7, NULL, 10);
+
+        if (errno == EINVAL)
+            goto out;
+
+        DEBUG("switch the keyboard/mouse to slot %d\n", slot);
+        dom0_driver_switch_controller(slot, DOM0_KEYBOARD);
+        dom0_driver_switch_controller(slot, DOM0_MOUSE);
+    }
+    else if (!strncmp(val, "keyboard ", 9))
+    {
+        int slot = strtol(val + 9, NULL, 10);
+
+        if (errno == EINVAL)
+            goto out;
+
+        DEBUG("switch the keyboard to slot %d\n", slot);
+        dom0_driver_switch_controller(slot, DOM0_KEYBOARD);
+    }
+out:
+    free(val);
+}
+
 static void dom0_driver_blank_done(void)
 {
     struct dom0_driver_xs_info  info;
@@ -574,13 +641,13 @@ static void dom0_driver_blank_done(void)
     }
 }
 
-void dom0_driver_state_change(const char *str)
+static void dom0_driver_state_change(const char *path, void *opaque)
 {
-    if (!strcmp(str, "dom0_driver_keyboard_state"))
+    if (strstr(path, "/keyboard/state"))
         dom0_driver_slots(DOM0_KEYBOARD);
-    if (!strcmp(str, "dom0_driver_mouse_state"))
+    if (strstr(path, "/mouse/state"))
         dom0_driver_slots(DOM0_MOUSE);
-    if (!strcmp(str, "dom0_driver_blank_done"))
+    if (strstr(path, "/blank"))
         dom0_driver_blank_done();
 }
 
index 03ce13b0044c4705d475fbd8f87fcc6ede275357..047f698572fc138e6eff44215d9273a1dc6ba214 100644 (file)
@@ -44,9 +44,9 @@ void handle_buffered_pio(void);
 #endif
 
 /* xenstore.c */
-typedef void (*xenstore_callback) (const char *token, void *opaque);
+typedef void (*xenstore_callback) (const char *path, void *opaque);
 int xenstore_watch_screenshot_node(DisplayState *ds);
-void xenstore_watch_callback(const char *token, xenstore_callback fptr, void *opaque);
+int xenstore_watch_new_callback(const char *path, xenstore_callback fptr, void *opaque);
 void xenstore_parse_domain_config(int domid);
 int xenstore_fd(void);
 void xenstore_process_event(void *opaque);
@@ -76,6 +76,15 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
                                              const char *devtype,
                                              const char *inst,
                                              const char *token);
+char *xenstore_read_dom0_driver(const char *key);
+int xenstore_write_dom0_driver(const char *key, const char *str);
+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque);
+
+char *xenstore_dom_read(int domid, char *key, unsigned int *len);
+int xenstore_dom_write(int domid, char *key, char *value);
+
+int *xenstore_get_domids(int *len);
+char *xenstore_read(const char *path);
 
  /* `danger' means that this parameter, variable or function refers to
   * an area of xenstore which is writeable by the guest and thus must
index e8782d543e6654e28ccfa6801c55dd92d0f824f2..c6da4b3a05d94ed0580be072ab76f8a37233260f 100644 (file)
@@ -46,10 +46,3 @@ extern struct BlockDriver bdrv_vbd;
 struct CharDriverState;
 void xenstore_store_serial_port_info(int i, struct CharDriverState *chr,
                                     const char *devname);
-char *xenstore_read_dom0_driver(const char *key);
-int xenstore_write_dom0_driver(const char *key, int val);
-
-char *xenstore_dom_read(int domid, char *key, unsigned int *len);
-int xenstore_dom_write(int domid, char *key, char *value);
-
-int *xenstore_get_domids(int *len);
index 1f0655513719729f4a49ae530f7e9f77aa2070c4..260fbcb887e96d4e5c5efabe2f33e9d37e72f747 100644 (file)
@@ -43,32 +43,39 @@ static QEMUTimer *insert_timer = NULL;
 
 struct xenstore_watch_cb_t
 {
-    char                *token;
+    char                *path;
     xenstore_callback   cb;
     void                *opaque;
 };
 
 static struct xenstore_watch_cb_t *xenstore_watch_callbacks = NULL;
 
-void xenstore_watch_callback(const char *token, xenstore_callback fptr, void *opaque)
+int xenstore_watch_new_callback(const char          *path,
+                                xenstore_callback   fptr,
+                                void                *opaque)
 {
-    int         i = 0;
+    int         i = 0, ret = 0;
+
+    ret = xs_watch(xsh, path, path);
+    if (ret == 0)
+        return 0;
 
     if (!xenstore_watch_callbacks)
     {
         xenstore_watch_callbacks = malloc(sizeof (struct xenstore_watch_cb_t));
-        xenstore_watch_callbacks[0].token = NULL;
+        xenstore_watch_callbacks[0].path = NULL;
     }
 
-    while (xenstore_watch_callbacks[i].token)
+    while (xenstore_watch_callbacks[i].path)
         i++;
 
     xenstore_watch_callbacks = realloc(xenstore_watch_callbacks,
                                        (i + 2) * sizeof (struct xenstore_watch_cb_t));
-    xenstore_watch_callbacks[i].token = strdup(token);
+    xenstore_watch_callbacks[i].path = strdup(path);
     xenstore_watch_callbacks[i].cb = fptr;
     xenstore_watch_callbacks[i].opaque = opaque;
-    xenstore_watch_callbacks[i + 1].token = NULL;
+    xenstore_watch_callbacks[i + 1].path = NULL;
+    return ret;
 }
 
 static int pasprintf(char **buf, const char *fmt, ...)
@@ -829,10 +836,13 @@ void xenstore_process_event(void *opaque)
     if (!vec)
         return;
 
-    for (i = 0; xenstore_watch_callbacks &&  xenstore_watch_callbacks[i].token; i++)
-        if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].token))
+    for (i = 0; xenstore_watch_callbacks &&  xenstore_watch_callbacks[i].path; i++)
+        if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path))
+        {
+            fprintf(stderr, "xenstore_callback: call %s\n", vec[XS_WATCH_TOKEN]);
             xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
                                            xenstore_watch_callbacks[i].opaque);
+        }
 
     if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
         xenstore_process_logdirty_event();
@@ -844,14 +854,6 @@ void xenstore_process_event(void *opaque)
         goto out;
     }
     
-    if (!strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_keyboard_state") ||
-        !strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_mouse_state") ||
-        !strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_blank_done"))
-    {
-        dom0_driver_state_change(vec[XS_WATCH_TOKEN]);
-        goto out;
-    }
-
     if (!strcmp(vec[XS_WATCH_TOKEN], "acadapterstatechangeevt")) {
         acpi_ac_adapter_state_changed();
         goto out;
@@ -1417,7 +1419,7 @@ char *xenstore_read_dom0_driver(const char *key)
     return val;
 }
 
-int xenstore_watch_dom0_driver(const char *key, const char *token)
+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque)
 {
     const char *path = "/local/domain/0/dom0_driver";
     char *buf = NULL;
@@ -1425,22 +1427,20 @@ int xenstore_watch_dom0_driver(const char *key, const char *token)
     
     if (pasprintf(&buf, "%s/%s", path, key) == -1)
         return 0;
-    ret = xs_watch(xsh, buf, token);
+    xenstore_watch_new_callback(buf, fptr, opaque);
     free(buf);
     return ret;
 }
 
-int xenstore_write_dom0_driver(const char *key, int val)
+int xenstore_write_dom0_driver(const char *key, const char *str)
 {
     const char *path = "/local/domain/0/dom0_driver";
     char *buf = NULL;
     int len = 0;
-    char str[10];
     int ret = 0;
     
     if (pasprintf(&buf, "%s/%s", path, key) == -1)
         return 0;
-    sprintf(str, "%d", val);
     ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str));
     free(buf);
     return ret;
@@ -1517,9 +1517,6 @@ int *xenstore_get_domids(int *len)
     return tab;
 }
 
-
-/* Advertise through xenstore that the device model is up and the
-   domain can be started. */
 void xenstore_dm_finished_startup(void)
 {
     char *path;
@@ -1583,11 +1580,22 @@ int xenstore_watch_screenshot_node(DisplayState *ds)
         fprintf(logfile, "pasprintf failed to get path.\n");
         goto out;
     }
-    xenstore_watch_callback("screenshot", xenstore_screenshot, ds);
     fprintf(stderr, "screenshot watch node %s\n", buf);
-    ret = xs_watch(xsh, buf, "screenshot");
+    ret = xenstore_watch_new_callback(buf, xenstore_screenshot, ds);
  out:
     free(buf);
     free(path);
     return ret;
 }
+
+char *xenstore_read(const char *path)
+{
+    char *value = NULL;
+    unsigned int len;
+
+    if (xsh == NULL)
+        return NULL;
+    return xs_read(xsh, XBT_NULL, path, &len);
+}
+
+