]> xenbits.xen.org Git - xenclient/ioemu-pq.git/commitdiff
Introduce new switching and input handling code.
authorJean Guyader <jean.guyader@eu.citrix.com>
Tue, 27 Oct 2009 16:22:24 +0000 (16:22 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Tue, 27 Oct 2009 16:22:24 +0000 (16:22 +0000)
master/dom0-driver [deleted file]
master/fix-drop-mouse-keyboard [deleted file]
master/intel
master/new-input-code [deleted file]
master/series
master/switcher [new file with mode: 0644]

diff --git a/master/dom0-driver b/master/dom0-driver
deleted file mode 100644 (file)
index 747acca..0000000
+++ /dev/null
@@ -1,1441 +0,0 @@
-diff --git a/console.h b/console.h
-index 14b42f3..97214c0 100644
---- a/console.h
-+++ b/console.h
-@@ -341,4 +341,19 @@ const char *readline_get_history(unsigned int index);
- void readline_start(const char *prompt, int is_password,
-                     ReadLineFunc *readline_func, void *opaque);
-+/* get_time */
-+char *get_time(void);
-+
-+/* dom0_driver.c */
-+void dom0_driver_init(const char *position);
-+
-+/* hid_linux.c */
-+void hid_linux_init(void);
-+int  hid_linux_grab_keyboard(int grab);
-+int  hid_linux_grab_mouse(int grab);
-+void hid_linux_secure_keyboard(void (*)(int));
-+void hid_linux_add_binding(const int *, void (*)(void*), void *);
-+void hid_linux_reset_keyboard(void);
-+void hid_linux_probe(int grab);
-+
- #endif
-diff --git a/dom0_driver.c b/dom0_driver.c
-new file mode 100644
-index 0000000..92f6b17
---- /dev/null
-+++ b/dom0_driver.c
-@@ -0,0 +1,709 @@
-+/*
-+ * QEMU dom0_driver
-+ *
-+ * Copyright (c) 2009 Citrix Systems
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+
-+#include "qemu-common.h"
-+#include "console.h"
-+#include "qemu-timer.h"
-+#include "qemu-xen.h"
-+
-+#include <sys/types.h>
-+#include <linux/input.h>
-+#include <linux/kd.h>
-+#include <dirent.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <assert.h>
-+#include <time.h>
-+
-+extern int vga_passthrough;
-+
-+static void dom0_driver_state_change(const char *path, void *opaque);
-+static void dom0_driver_command(const char *path, void *opaque);
-+static void dom0_driver_leave_done(void);
-+
-+#define DEBUG_DOM0_DRIVER             1
-+#define XS_REFRESH_INTERVAL           1000
-+#define DOM0_DRIVER_SWITCH_TIMEOUT    2
-+
-+#define DOM0_MOUSE              1
-+#define DOM0_KEYBOARD           2
-+
-+#if DEBUG_DOM0_DRIVER
-+# define DEBUG(_format_, args...)    \
-+    do { \
-+      char *__str = get_time();       \
-+    fprintf(stderr, "[%s] dom0_driver(%d):%d: " _format_, __str, domid, __LINE__, ## args);\
-+      free(__str); \
-+    } while (false)
-+#else
-+# define DEBUG(_format_, args...) (void)0
-+#endif
-+
-+#define NB_SLOTS        10
-+
-+static void             dom0_read(void *opaque);
-+static void             dom0_driver_reset_keyboard(void);
-+static void             dom0_read_secure(void *opaque);
-+struct dom0_driver
-+{
-+    QEMUTimer *xs_timer;
-+    int secure_fd;
-+    int (*enter)(void);
-+    int (*leave)(void);
-+};
-+
-+struct dom0_driver_handler
-+{
-+    void (*init)(void);
-+    void (*probe)(int);
-+    int  (*grab_keyboard)(int);
-+    int  (*grab_mouse)(int);
-+    void (*secure_keyboard)(void (*)(int));
-+    void (*reset_keyboard)(void);
-+    void (*add_binding)(const int *, void (*)(void *), void *);
-+};
-+
-+struct dom0_driver_xs_info
-+{
-+    int state;
-+    int domid;
-+    int new_slot;
-+    int timestamp;
-+    int pre;
-+};
-+
-+static struct dom0_driver_handler dom0_driver_hid_linux =
-+{
-+    .init = hid_linux_init,
-+    .probe = hid_linux_probe,
-+    .grab_keyboard = hid_linux_grab_keyboard,
-+    .grab_mouse = hid_linux_grab_mouse,
-+    .secure_keyboard = hid_linux_secure_keyboard,
-+    .reset_keyboard = hid_linux_reset_keyboard,
-+    .add_binding = hid_linux_add_binding,
-+};
-+
-+static struct dom0_driver driver;
-+static struct dom0_driver_handler *dom0_driver_handler = NULL;
-+
-+static int dom0_driver_xs_read_dom0(const char *key)
-+{
-+    char        *str = NULL;
-+
-+    if (!(str = xenstore_read_dom0_driver(key)))
-+    {
-+      fprintf(stderr, "dom0_driver: fatal the node %s don't exits\n", key);
-+      exit(2);
-+    }
-+    return strtol(str, NULL, 10);
-+}
-+
-+static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info,
-+                                   int                        controller)
-+{
-+    char        *str = NULL;
-+    char        path[128];
-+    int         val[10];
-+    const char  *key[] = {"state", "domid", "new-slot", "timestamp", "pre"};
-+
-+    memset(info, -1, sizeof (struct dom0_driver_xs_info));
-+    for (int i = 0; i < sizeof (key) / sizeof (key[0]); i++)
-+    {
-+      if (controller == DOM0_MOUSE)
-+          sprintf(path, "mouse/%s", key[i]);
-+      else if (controller == DOM0_KEYBOARD)
-+          sprintf(path, "keyboard/%s", key[i]);
-+      else
-+      {
-+          fprintf(stderr, "dom0_driver unknown controller type\n");
-+          exit(2);
-+      }
-+
-+      val[i] = -1;
-+      if ((str = xenstore_read_dom0_driver(path)))
-+      {
-+          val[i] = strtol(str, NULL, 10);
-+          free(str);
-+      }
-+    }
-+
-+    info->state = val[0];
-+    info->domid = val[1];
-+    info->new_slot = val[2];
-+    info->timestamp = val[3];
-+    info->pre = val[4];
-+}
-+
-+static void dom0_driver_xs_write(const char *key, int val, int controller)
-+{
-+    char        path[256], str[20];
-+
-+    if (controller == DOM0_MOUSE)
-+      sprintf(path, "mouse/%s", key);
-+    else if (controller == DOM0_KEYBOARD)
-+      sprintf(path, "keyboard/%s", key);
-+    else
-+    {
-+      DEBUG("unknown controller type\n");
-+      exit(2);
-+    }
-+
-+    sprintf(str, "%d", val);
-+    DEBUG("write %s=%d\n", path, val);
-+    xenstore_write_dom0_driver(path, str);
-+}
-+
-+/*
-+** Blanker fonctions
-+*/
-+static void dom0_driver_blank_changed(void)
-+{
-+    char *str;
-+    int blank;
-+
-+    if (!(str = xenstore_read_dom0_driver("blank")))
-+      return;
-+    blank = strtol(str, NULL, 10);
-+    free(str);
-+    if (blank == 2)
-+    {
-+      usleep(100 * 1000); /* 100 ms */
-+      dom0_driver_leave_done();
-+    }
-+}
-+static int dom0_driver_blank(void)
-+{
-+    xenstore_write_dom0_driver("blank", "1");
-+    return 0;
-+}
-+static int dom0_driver_unblank(void)
-+{
-+    xenstore_write_dom0_driver("blank", "0");
-+    return 0;
-+}
-+
-+static void dom0_driver_key_switch(int new_slot)
-+{
-+    struct dom0_driver_xs_info  info;
-+    char                        buff[128];
-+
-+    dom0_driver_read_xs_info(&info, DOM0_MOUSE);
-+    assert(info.state == 1);
-+
-+    sprintf(buff, "switch %d", new_slot);
-+
-+    DEBUG("Write \"%s\" into xenstore\n", buff);
-+    xenstore_write_dom0_driver("command", buff);
-+}
-+
-+static void dom0_driver_read_secure(int ascii)
-+{
-+    int write_sz;
-+
-+    if (ascii)
-+    {
-+      DEBUG("Send %d to xenmgr\n", ascii);
-+      write_sz = write(driver.secure_fd, &ascii, 1);
-+      if (ascii == -1 || ascii == 27 || write_sz != 1)
-+      {
-+          dom0_driver_handler->reset_keyboard();
-+          dom0_driver_handler->secure_keyboard(NULL);
-+          return;
-+      }
-+    }
-+}
-+
-+static void dom0_driver_detect_secure_auth(void* opaque)
-+{
-+    struct stat s;
-+    int sas_ascii = 1, ret = 0;;
-+
-+    DEBUG("Received SAS keystroke\n");
-+    if ((driver.secure_fd = open("/var/lib/xenmgr/keys", O_WRONLY)) > 0)
-+    {
-+      DEBUG("write SAS ascii code\n");
-+      if ((ret = write(driver.secure_fd, &sas_ascii, 1)) == 1)
-+      {
-+          DEBUG("Redirect fds to secure callback\n");
-+          dom0_driver_handler->secure_keyboard(dom0_driver_read_secure);
-+      }
-+      DEBUG("writing SAS ret %d\n", ret);
-+
-+    }
-+    else
-+      DEBUG("xenmgr file is not there\n");
-+}
-+
-+static void dom0_get_positions(int *positions)
-+{
-+    int *domids = NULL;
-+    int num;
-+    char *tmp;
-+    unsigned int len;
-+    int pos = 0;
-+
-+    for (int i = 0; i < NB_SLOTS; i++)
-+      positions[i] = 0;
-+
-+    /* Get all the positions */
-+    domids = xenstore_get_domids(&num);
-+    for (int i = 0; i < num; i++)
-+      if (domids[i])
-+      {
-+          if (!(tmp = xenstore_dom_read(domids[i], "dom0_input/pos", &len)))
-+              continue;
-+          pos = strtol(tmp, NULL, 10);
-+          free(tmp);
-+
-+          positions[pos] = domids[i];
-+      }
-+    free(domids);
-+}
-+
-+static void dom0_gr_devices(int grab, int controller)
-+{
-+    if (controller == DOM0_MOUSE)
-+    {
-+      DEBUG("%s mouse\n", grab ? "Grab" : "Release");
-+      assert(dom0_driver_handler->grab_mouse(grab));
-+    }
-+    if (controller == DOM0_KEYBOARD)
-+    {
-+      DEBUG("%s keyboard\n", grab ? "Grab" : "Release");
-+      assert(dom0_driver_handler->grab_keyboard(grab));
-+    }
-+
-+    dom0_driver_handler->reset_keyboard();
-+    if (!grab)
-+      dom0_driver_xs_write("pre", domid, controller);
-+    dom0_driver_xs_write("domid", domid, controller);
-+    dom0_driver_xs_write("state", grab ? 1 : 2, controller);
-+}
-+
-+static int dom0_dom_alive(int id)
-+{
-+    xc_dominfo_t info;
-+    int rc;
-+
-+    rc = xc_domain_getinfo(xc_handle, id, 1, &info);
-+    return rc == 1 && info.domid == id;
-+}
-+
-+
-+static int dom0_driver_failover_switch(void *opaque)
-+{
-+    int                         ret = 1;
-+    uint32_t                  t = time(NULL);
-+    struct dom0_driver_xs_info        mouse, keyboard;
-+
-+    dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
-+    dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
-+    if (mouse.domid == domid)
-+      dom0_driver_handler->probe(1);
-+    else
-+      dom0_driver_handler->probe(0);
-+
-+    if (!vga_passthrough)
-+      return 0;
-+
-+    if (mouse.state == -1)
-+    {
-+      DEBUG("No state grab the device\n");
-+      dom0_gr_devices(1, DOM0_KEYBOARD);
-+      dom0_gr_devices(1, DOM0_MOUSE);
-+      driver.enter();
-+      goto out;
-+    }
-+
-+    /* The domain which has the focus crash */
-+    if (!dom0_dom_alive(mouse.domid))
-+    {
-+      DEBUG("steal the focus from %d\n", mouse.domid);
-+      dom0_driver_xs_write("pre", -1, DOM0_KEYBOARD);
-+      dom0_driver_xs_write("pre", -1, DOM0_MOUSE);
-+      dom0_gr_devices(1, DOM0_KEYBOARD);
-+      dom0_gr_devices(1, DOM0_MOUSE);
-+      driver.enter();
-+      goto out;
-+    }
-+
-+    if ( keyboard.state == 2 &&
-+          (t - keyboard.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT)
-+    {
-+      DEBUG("Keyboard in state 2 for to long, take it back\n");
-+      dom0_gr_devices(1, DOM0_KEYBOARD);
-+    }
-+
-+    if (mouse.state == 2 &&
-+          (t - mouse.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT)
-+    {
-+      DEBUG("Mouse in state 2 for to long, take it back\n");
-+      dom0_gr_devices(1, DOM0_MOUSE);
-+      DEBUG("Get the focus now !\n");
-+      driver.enter();
-+      goto out;
-+    }
-+
-+    ret = 0;
-+out:
-+    qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
-+    return ret;
-+}
-+
-+static void dom0_driver_dom_command(const char *path, void *opaque)
-+{
-+    unsigned int len;
-+    char *str;
-+    char buff[256];
-+    int       positions[NB_SLOTS];
-+    int natif_domid;
-+    int i;
-+    struct dom0_driver_xs_info mouse;
-+
-+    if (!(str = xenstore_read(path)) || !*str)
-+      return;
-+
-+    DEBUG("Received private command %s\n", path);
-+    dom0_get_positions(positions);
-+    natif_domid = dom0_driver_xs_read_dom0("natif");
-+
-+    dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
-+    for (i = 0; i < NB_SLOTS; ++i)
-+    {
-+        if (!strcmp("switch", str) && positions[i] == domid)
-+            break;
-+      if (!strcmp("take", str) && positions[i] == domid)
-+          break;
-+      if (!strcmp("release", str) && positions[i] == natif_domid)
-+          break;
-+    }
-+    if (i == NB_SLOTS)
-+    {
-+      DEBUG("Try to %s on a bad slot\n", str);
-+      free(str);
-+      return;
-+    }
-+
-+    if (!strcmp("switch", str))
-+        sprintf(buff, "switch %d", i);
-+    else
-+    {
-+        if (mouse.domid != natif_domid)
-+        {
-+            DEBUG("Natif should have the focus for that.\n");
-+            return;
-+        }
-+        sprintf(buff, "keyboard %d", i);
-+    }
-+
-+    DEBUG("Write \"%s\" into xenstore\n", buff);
-+    xenstore_write_dom0_driver("command", buff);
-+    free(str);
-+}
-+
-+static void dom0_driver_event_init(const char *str_arg)
-+{
-+    int                 positions[NB_SLOTS];
-+    char                str[20];
-+    int                 pos = 0;
-+    int                 i = 0;
-+
-+    pos = strtol(str_arg, NULL, 10);
-+    dom0_get_positions(positions);
-+    if (positions[pos])
-+    {
-+      DEBUG("There is already a vm at this slot\n");
-+      exit(1);
-+    }
-+    else
-+    {
-+      snprintf(str, 9, "%d", pos);
-+      xenstore_dom_write(domid, "dom0_input/pos", str);
-+    }
-+
-+    if (vga_passthrough)
-+    {
-+      sprintf(str, "%d", domid);
-+      xenstore_write_dom0_driver("natif", str);
-+      xenstore_dom_chmod(0, "dom0_driver/natif", "r0");
-+      xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
-+      xenstore_dom_chmod(0, "dom0_driver/command", "w0");
-+    } 
-+    else
-+    {
-+        xenstore_dom_write(domid, "dom0_input/command", "");
-+        sprintf(str, "w%d", domid);
-+        xenstore_dom_chmod(domid, "dom0_input/command", str);
-+        xenstore_dom_watch(domid, "dom0_input/command", dom0_driver_dom_command, NULL);
-+    }
-+
-+    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("leave", dom0_driver_state_change, NULL);
-+    xenstore_watch_dom0_driver("blank", dom0_driver_state_change, NULL);
-+
-+    /* Register the failover switch */
-+    driver.xs_timer = qemu_new_timer(rt_clock,
-+                                   (void (*)(void *))dom0_driver_failover_switch,
-+                                   NULL);
-+    qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
-+}
-+
-+static void dom0_driver_slots(int controller)
-+{
-+    struct dom0_driver_xs_info  info;
-+    int                         next_domid;
-+    int                         positions[NB_SLOTS];
-+
-+    if (dom0_driver_failover_switch(NULL))
-+      return;
-+
-+    dom0_driver_read_xs_info(&info, controller);
-+
-+    if (info.new_slot != -1)
-+    {
-+      dom0_get_positions(positions);
-+      if (positions[info.new_slot] != 0)
-+      {
-+          if (info.state == 0 && info.domid == domid)
-+          {
-+              dom0_gr_devices(0, controller);
-+              return;
-+          }
-+
-+          if (info.state == 2 && positions[info.new_slot] == domid)
-+          {
-+              dom0_gr_devices(1, controller);
-+              return;
-+          }
-+
-+      }
-+    }
-+}
-+
-+static void dom0_driver_switch_controller(int slot, int controller)
-+{
-+    int       positions[NB_SLOTS];
-+    char *str;
-+    int len;
-+    int ready;
-+    struct dom0_driver_xs_info info;
-+
-+    dom0_get_positions(positions);
-+    if (positions[slot] == 0)
-+    {
-+      DEBUG("Cannot switch controller %d to %d slot empty\n", controller, slot);
-+      return;
-+    }
-+
-+    str = xenstore_dom_read(positions[slot], "dom0_input/ready", &len);
-+    ready = strtol(str, NULL, 10);
-+    free(str);
-+    if (ready != 1)
-+    {
-+      DEBUG("Cannot switch controller %d to %d slot not ready\n", controller, slot);
-+      return;
-+    }
-+
-+    dom0_driver_read_xs_info(&info, controller);
-+    if (info.state != 1)
-+    {
-+      DEBUG("Cannot switch controller %d to %d, unstable state\n", controller, slot);
-+      return;
-+    }
-+
-+    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);
-+      xenstore_write(path, "done");
-+    }
-+    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);
-+      xenstore_write(path, "done");
-+    }
-+out:
-+    free(val);
-+}
-+
-+static void dom0_driver_leave_done(void)
-+{
-+    char *str;
-+    int id;
-+
-+    if (!(str = xenstore_read_dom0_driver("leave")))
-+      return;
-+    id = strtol(str, NULL, 10);
-+    free(str);
-+    if (id == 1)
-+      xenstore_write_dom0_driver("leave", "2");
-+}
-+
-+static void dom0_driver_leave_changed(void)
-+{
-+    char *str;
-+    int id;
-+    struct dom0_driver_xs_info mouse;
-+
-+    if (!(str = xenstore_read_dom0_driver("leave")))
-+      return;
-+    id = strtol(str, NULL, 10);
-+    free(str);
-+    dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
-+    if (id == 2 && mouse.domid == domid)
-+    {
-+      xenstore_write_dom0_driver("leave", "0");
-+      driver.enter();
-+    }
-+}
-+
-+static void dom0_driver_state_change(const char *path, void *opaque)
-+{
-+
-+    if (strstr(path, "/keyboard/state"))
-+      dom0_driver_slots(DOM0_KEYBOARD);
-+    if (strstr(path, "/mouse/state"))
-+      dom0_driver_slots(DOM0_MOUSE);
-+    if (strstr(path, "/leave"))
-+      dom0_driver_leave_changed();
-+    else if (strstr(path, "/blank"))
-+      dom0_driver_blank_changed();
-+    else
-+    {
-+      struct dom0_driver_xs_info  mouse, keyboard;
-+
-+      dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
-+      dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
-+
-+      if (mouse.state == 1 && keyboard.state == 1)
-+          if (mouse.pre != -1 && mouse.pre == domid)
-+          {
-+              xenstore_write_dom0_driver("leave", "1");
-+              if (driver.leave())
-+                  dom0_driver_leave_done();
-+          }
-+    }
-+}
-+
-+static void dom0_driver_switch(void *slot_arg)
-+{
-+    int slot = (int)slot_arg;
-+    char buff[64];
-+
-+    DEBUG("%d pressed switch to slot %d\n", slot, slot);
-+    sprintf(buff, "switch %d", slot);
-+    xenstore_write_dom0_driver("command", buff);
-+}
-+
-+static void dom0_driver_switch_bind(void)
-+{
-+    int               i = 0;
-+    int               binds[4];
-+
-+    for (i = 0; i < 4; i++)
-+      binds[i] = -1;
-+
-+    for (i = 0; i < 9; i++)
-+    {
-+      binds[0] = KEY_LEFTCTRL;
-+      binds[1] = KEY_1 + i;
-+      dom0_driver_handler->add_binding(binds, dom0_driver_switch, (void*)(i + 1));
-+    }
-+    binds[1] = KEY_0;
-+    dom0_driver_handler->add_binding(binds, dom0_driver_switch, (void*)(0));
-+
-+    binds[0] = KEY_LEFTCTRL;
-+    binds[1] = KEY_LEFTALT;
-+    binds[2] = KEY_BACKSPACE;
-+    binds[3] = -1;
-+    dom0_driver_handler->add_binding(binds, dom0_driver_detect_secure_auth, NULL);
-+}
-+
-+static int dom0_driver_dummy_enter_leave(void)
-+{
-+  return 1;
-+}
-+
-+void dom0_driver_init(const char *position)
-+{
-+    memset(&driver, 0, sizeof (driver));
-+
-+    dom0_driver_handler = &dom0_driver_hid_linux;
-+    dom0_driver_handler->init();
-+
-+    if (vga_passthrough)
-+    {
-+      driver.enter = dom0_driver_unblank;
-+      driver.leave = dom0_driver_blank;
-+    }
-+    else if (intel)
-+    {
-+        driver.enter = intel_enter;
-+        driver.leave = intel_leave;
-+    }
-+    else
-+    {
-+      driver.enter = dom0_driver_dummy_enter_leave;
-+      driver.leave = dom0_driver_dummy_enter_leave;
-+    }
-+
-+    dom0_driver_switch_bind();
-+    dom0_driver_event_init(position);
-+    dom0_driver_failover_switch(NULL);
-+
-+    DEBUG("done\n");
-+    xenstore_dom_write(domid, "dom0_input/ready", "1");
-+}
-diff --git a/hid-linux.c b/hid-linux.c
-new file mode 100644
-index 0000000..59dfec8
---- /dev/null
-+++ b/hid-linux.c
-@@ -0,0 +1,527 @@
-+/*
-+ * QEMU hid-linux /dev/input driver
-+ *
-+ * Copyright (c) 2008 Citrix Systems
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+
-+#include "qemu-common.h"
-+#include "console.h"
-+#include "qemu-timer.h"
-+#include "qemu-xen.h"
-+
-+#include <sys/types.h>
-+#include <linux/input.h>
-+#include <linux/kd.h>
-+#include <dirent.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <assert.h>
-+#include <time.h>
-+#include <sys/time.h>
-+
-+#define HID_LINUX_XS_PATH             "/local/domain/0/hid_linux"
-+#define ABS(x)                        ((x) > 0 ? (x) : -(x))
-+#define EVENT_PATH                            "/dev/input/event"
-+#define HID_LINUX_MAX_DEV             16
-+
-+#define DEBUG_HID_LINUX
-+
-+#ifdef DEBUG_HID_LINUX
-+# define DEBUG(_format_, args...)     \
-+    do \
-+{ \
-+    char *__str = get_time(); \
-+    fprintf(stderr, "[%s] hid-linux(%d):%d: " _format_, (__str), domid, __LINE__, ## args);\
-+    free(__str);\
-+} \
-+while (0);
-+#else
-+# define DEBUG(_format_, args...) (void)0
-+#endif
-+
-+static struct hid_linux_driver
-+{
-+    int               keyboard_fds[HID_LINUX_MAX_DEV / 2];
-+    int               mouse_fds[HID_LINUX_MAX_DEV / 2];
-+    char      *controller_paths[HID_LINUX_MAX_DEV];
-+    int               mouse_button_state;
-+    int               key_status[256];
-+    void      (*secure_key)(int ascii);
-+} hid_linux_driver;
-+
-+struct hid_linux_binding
-+{
-+    int       *binding;
-+    void      (*cb)(void *);
-+    void      *payload;
-+};
-+
-+static struct hid_linux_binding *hid_linux_binding = NULL;
-+
-+static const int ascii2keycode_table[] =
-+{
-+    KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
-+    KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
-+    KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
-+};
-+
-+static char keycode2ascii(int keycode)
-+{
-+    int i = 0;
-+
-+    switch (keycode)
-+    {
-+      case KEY_ESC: return 27;
-+      case KEY_BACKSPACE: return 8;
-+      case KEY_ENTER: return 10;
-+      case KEY_LEFT: return 17;
-+      case KEY_RIGHT: return 18;
-+      case KEY_DELETE: return 127;
-+      case KEY_HOME: return 2;
-+      case KEY_END: return 3;
-+      case KEY_INSERT: return 19;
-+      case KEY_SPACE: return 20;
-+      default:
-+              for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
-+                  if (ascii2keycode_table[i] == keycode)
-+                      return i + 'a';
-+    }
-+    return 0;
-+}
-+
-+static int ascii2keycode(char ascii)
-+{
-+    return ascii2keycode_table[ascii - 'a'];
-+}
-+
-+static char *hid_linux_xs_read(const char *key)
-+{
-+    char *path = NULL;
-+    char *ret;
-+
-+    if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1)
-+      return NULL;
-+    ret = xenstore_read(path);
-+    free(path);
-+    return ret;
-+}
-+
-+void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload)
-+{
-+    int i = 0, j = 0;
-+
-+    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
-+      ;
-+    hid_linux_binding = realloc(hid_linux_binding,
-+                              (i + 2) * sizeof (struct hid_linux_binding));
-+    hid_linux_binding[i + 1].cb = NULL;
-+    hid_linux_binding[i].cb = cb;
-+    hid_linux_binding[i].payload = payload;
-+    hid_linux_binding[i].binding = NULL;
-+
-+    j = 0;
-+    do
-+    {
-+      hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding,
-+                                             (j + 1) * sizeof (int));
-+      hid_linux_binding[i].binding[j] = tab[j];
-+    }
-+    while (tab[j++] != -1);
-+}
-+
-+static int hid_linux_detect_binding(void)
-+{
-+    int i, j;
-+
-+    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
-+    {
-+      int *tab = hid_linux_binding[i].binding;
-+
-+      for (j = 0; tab[j] != -1; j++)
-+          if (hid_linux_driver.key_status[tab[j]] == 0)
-+              break;
-+      if (tab[j] != -1)
-+          continue;
-+      else /* We match a binding */
-+      {
-+          DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload));
-+          hid_linux_binding[i].cb(hid_linux_binding[i].payload);
-+          hid_linux_reset_keyboard();
-+          return 1;
-+      }
-+    }
-+    return 0;
-+}
-+
-+static void hid_linux_key_inject(int code, uint32_t keycode)
-+{
-+    int first = 0;
-+
-+    switch (keycode)
-+    {
-+      case KEY_F11:       keycode = 0X57; break; /* F11 */
-+      case KEY_F12:       keycode = 0X58; break; /* F12 */
-+      case KEY_INSERT:    keycode = 0X52; break;
-+      case KEY_HOME:      keycode = 0X47; break;
-+      case KEY_PAGEUP:    keycode = 0X49; break;
-+      case KEY_DELETE:    keycode = 0X53; break;
-+      case KEY_END:       keycode = 0X4F; break;
-+      case KEY_PAGEDOWN:  keycode = 0x51; break;
-+      case KEY_UP:        keycode = 0X48; break;
-+      case KEY_LEFT:      keycode = 0X4B; break;
-+      case KEY_DOWN:      keycode = 0X50; break;
-+      case KEY_RIGHT:     keycode = 0X4D; break;
-+      case KEY_RIGHTALT:  keycode = 0x38; first = 0xe0; break;
-+      case KEY_LEFTMETA:  keycode = 0x5B; first = 0xe0; break;
-+      case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break;
-+    }
-+
-+    if (first)
-+      kbd_put_keycode(first);
-+
-+    if (code == 0)
-+      kbd_put_keycode(keycode | 0x80);
-+    else
-+      kbd_put_keycode(keycode & 0x7f);
-+}
-+
-+
-+
-+static void hid_linux_key_event(int code, uint32_t keycode)
-+{
-+    if (code == 1)
-+      if (hid_linux_detect_binding())
-+          return;
-+    hid_linux_key_inject(code, keycode);
-+}
-+
-+static void hid_linux_read(void *opaque)
-+{
-+    struct input_event  event[5];
-+    int                 i = 0;
-+    int                 read_sz = 0;
-+    int                 fd = *(int *)opaque;
-+
-+    read_sz = read(fd, event, sizeof (event));
-+    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
-+    {
-+      if (event[i].type == EV_KEY)
-+      {
-+          if (event[i].code >= BTN_MOUSE)
-+          {
-+              /* Mouse Key */
-+              int     type = 0;
-+
-+              switch(event[i].code)
-+              {
-+                  case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
-+                  case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
-+                  case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break;
-+              }
-+
-+              if (event[i].value)
-+                  hid_linux_driver.mouse_button_state |= type;
-+              else
-+                  hid_linux_driver.mouse_button_state &= ~type;
-+              kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state);
-+          }
-+          else
-+          {
-+              hid_linux_driver.key_status[event[i].code] = event[i].value;
-+              hid_linux_key_event(event[i].value, event[i].code);
-+          }
-+      }
-+
-+      if (event[i].type == EV_REL || event[i].type == EV_ABS)
-+      {
-+          /* Mouse motion */
-+          int x = 0, y = 0, z = 0;
-+
-+          if (event[i].type == EV_REL)
-+              switch (event[i].code)
-+              {
-+                  case REL_X : x = event[i].value; break;
-+                  case REL_Y : y = event[i].value; break;
-+                  case REL_WHEEL : z = -event[i].value; break;
-+              }
-+          if (event[i].type == EV_ABS)
-+          {
-+              static int last_x = 1, last_y = 1;
-+              int px = 0, py = 0, l = 50;
-+              double div = 1;
-+              char *str = NULL;
-+
-+              str = hid_linux_xs_read("touchpad-limit");
-+              if (str)
-+                  l = strtol(str, NULL, 10);
-+              str = hid_linux_xs_read("touchpad-div");
-+              if (str)
-+                  div = strtol(str, NULL, 10) / 1000.;
-+
-+              switch (event[i].code)
-+              {
-+                  case ABS_X : x = event[i].value; break;
-+                  case ABS_Y : y = event[i].value; break;
-+              }
-+
-+              if (x)
-+              {
-+                  px = x - last_x;
-+                  last_x = x;
-+              }
-+              if (y)
-+              {
-+                  py = y - last_y;
-+                  last_y = y;
-+              }
-+
-+              x = (ABS(px) < l ? px : 0) / div;
-+              y = (ABS(py) < l ? py : 0) / div;
-+          }
-+
-+          kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state);
-+      }
-+    }
-+}
-+
-+void hid_linux_reset_keyboard(void)
-+{
-+    int i = 0;
-+
-+    for (i = 0; i < 256; i++)
-+      if (hid_linux_driver.key_status[i])
-+      {
-+          hid_linux_key_inject(0, i);
-+          hid_linux_driver.key_status[i] = 0;
-+      }
-+}
-+
-+
-+
-+static void hid_linux_redirect_fds(int *fd, IOHandler *cb)
-+{
-+    assert(fd != NULL);
-+
-+    while (*fd != -1)
-+    {
-+      qemu_set_fd_handler(*fd, cb, NULL, fd);
-+      fd++;
-+    }
-+}
-+
-+static void hid_linux_secure_read(void *opaque)
-+{
-+    struct input_event  event[5];
-+    int                 i = 0;
-+    int                 read_sz = 0;
-+    int                 fd = *(int *)opaque;
-+
-+    assert(hid_linux_driver.secure_key);
-+
-+    read_sz = read(fd, event, sizeof (event));
-+    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
-+      if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
-+              event[i].value > 0)
-+          hid_linux_driver.secure_key(keycode2ascii(event[i].code));
-+}
-+
-+
-+void hid_linux_secure_keyboard(void (*cb)(int ascii))
-+{
-+    hid_linux_driver.secure_key = cb;
-+    if (cb)
-+      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
-+              hid_linux_secure_read);
-+    else
-+      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
-+              hid_linux_read);
-+}
-+
-+static int hid_linux_grab_devices(int grab, int *fd)
-+{
-+    int rc = 0;
-+    int try = 10;
-+
-+    assert(fd != NULL && *fd != -1);
-+    for (; *fd != -1; fd++)
-+    {
-+      while (try--)
-+      {
-+          if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1)
-+          {
-+              char *er;
-+
-+              if (errno == EBUSY)
-+                  continue;
-+              er = strerror(errno);
-+              DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er);
-+              return 0;
-+          }
-+          else
-+              break;
-+      }
-+      assert(try);
-+
-+      DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd);
-+
-+      if (grab)
-+          qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd);
-+      else
-+          qemu_set_fd_handler(*fd, NULL, NULL, fd);
-+    }
-+    return 1;
-+}
-+
-+int hid_linux_grab_keyboard(int grab)
-+{
-+    return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds);
-+}
-+
-+int hid_linux_grab_mouse(int grab)
-+{
-+    return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds);
-+}
-+
-+static int hid_linux_open_timeout(const char *path, int flags)
-+{
-+   int        try = 10;
-+   int  fd = 0;
-+
-+   while (try-- && ((fd = open(path, flags)) == -1))
-+       usleep(100000); /* 10 ms */
-+   if (try == 0)
-+       return 0;
-+   return fd == -1 ? 0 : fd;
-+}
-+
-+static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2)
-+{
-+   int        try = 10;
-+
-+   while (try-- && ioctl(fd, arg1, arg2) == -1)
-+       usleep(100000); /* 10 ms */
-+   if (try == 0)
-+       return 0;
-+   return 1;
-+}
-+
-+void hid_linux_probe(int grab)
-+{
-+    int                 i = 0, j = 0, c = 0;
-+    int                 fd = -1;
-+    int                 keyboard = 0, mouse = 0;
-+    char                path[strlen(EVENT_PATH) + 3];
-+    char                name[128];
-+    int                       *controllers;
-+    struct input_id     id;
-+    struct stat       st;
-+
-+    while (1)
-+    {
-+        if (fd != -1)
-+            close(fd);
-+
-+      sprintf(path, "%s%i", EVENT_PATH, i++);
-+
-+      if (stat(path, &st) == -1)
-+          break;
-+
-+      for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++)
-+          if (!strcmp(hid_linux_driver.controller_paths[c], path))
-+              break;
-+      assert(c != HID_LINUX_MAX_DEV);
-+      if (hid_linux_driver.controller_paths[c])
-+          continue;
-+
-+      if ((fd = open(path, O_RDONLY)) == -1)
-+          break;
-+
-+      if (ioctl(fd, EVIOCGNAME(128), name) == -1)
-+      {
-+          DEBUG("Input get name failed on %s\n", path);
-+            break;
-+      }
-+
-+        if (ioctl(fd, EVIOCGID, &id) == -1)
-+      {
-+          DEBUG("Input get id failed on %s\n", path);
-+            continue;
-+      }
-+
-+        /* Only get devices on usb and i8042 */
-+        if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
-+            continue;
-+
-+        if (strcasestr(name, "keyboard"))
-+        {
-+            DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype);
-+            controllers = hid_linux_driver.keyboard_fds;
-+        }
-+        else
-+        {
-+            DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype);
-+            controllers = hid_linux_driver.mouse_fds;
-+        }
-+
-+      for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++)
-+          ;
-+      assert(j != (HID_LINUX_MAX_DEV / 2));
-+
-+      controllers[j] = fd;
-+      controllers[j + 1] = -1;
-+
-+      if (grab)
-+      {
-+          if (!hid_linux_grab_devices(1, controllers + j))
-+          {
-+              DEBUG("Grabing failed, try next time...\n");
-+              controllers[j] = -1;
-+              break;
-+          }
-+      }
-+
-+      hid_linux_driver.controller_paths[c] = strdup(path);
-+      hid_linux_driver.controller_paths[c + 1] = NULL;
-+
-+      fd = -1;
-+    }
-+    if (fd != -1)
-+      close(fd);
-+}
-+
-+void hid_linux_init(void)
-+{
-+    hid_linux_driver.keyboard_fds[0] = -1;
-+    hid_linux_driver.mouse_fds[0] = -1;
-+    hid_linux_driver.controller_paths[0] = NULL;
-+
-+    while (hid_linux_driver.keyboard_fds[0] == -1)
-+    {
-+      hid_linux_probe(0);
-+      usleep(100000); /* 10 ms */
-+    }
-+}
-diff --git a/qemu-xen.h b/qemu-xen.h
-index 7883718..afe8f22 100644
---- a/qemu-xen.h
-+++ b/qemu-xen.h
-@@ -109,7 +109,13 @@ int xenstore_write(const char *path, const char *val);
- void xenstore_dm_finished_startup(void);
-- /* `danger' means that this parameter, variable or function refers to
-+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);
-+
-+int *xenstore_get_domids(int *len);
-+
-+/* `danger' means that this parameter, variable or function refers to
-   * an area of xenstore which is writeable by the guest and thus must
-   * not be trusted by qemu code.  For variables containing xenstore
-   * paths, `danger' can mean that both the path refers to a
-diff --git a/vl.c b/vl.c
-index 6d79072..adfa4f6 100644
---- a/vl.c
-+++ b/vl.c
-@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
- int win2k_install_hack = 0;
- int rtc_td_hack = 0;
- int vga_passthrough = 0;
-+const char *dom0_input = NULL;
- #endif
- int usb_enabled = 0;
- int smp_cpus = 1;
-@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16];
- #include "xen-vl-extra.c"
-+char *get_time(void)
-+{
-+
-+  char buff[128];
-+  char *str;
-+  struct timeval tv;
-+
-+  gettimeofday(&tv, NULL);
-+  str = malloc(256);
-+  strftime(buff, 128, "%T", localtime(&tv.tv_sec));
-+  sprintf(str, "%s:%06d", buff, (int)tv.tv_usec);
-+  return str;
-+}
-+
- /***********************************************************/
- /* x86 ISA bus support */
-@@ -4289,6 +4304,7 @@ enum {
-     QEMU_OPTION_acpi,
-     QEMU_OPTION_vcpus,
-     QEMU_OPTION_vga_passthrough,
-+    QEMU_OPTION_dom0_input,
-     /* Debug/Expert options: */
-     QEMU_OPTION_serial,
-@@ -4463,6 +4479,7 @@ static const QEMUOption qemu_options[] = {
-     { "vncunused", 0, QEMU_OPTION_vncunused },
-     { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
-     { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough },
-+    { "dom0-input", 1, QEMU_OPTION_dom0_input },
- #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
-     { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
-     { "xen-create", 0, QEMU_OPTION_xen_create },
-@@ -5299,6 +5316,9 @@ int main(int argc, char **argv, char **envp)
-             case QEMU_OPTION_vga_passthrough:
-                 vga_passthrough = 1;
-                 break;
-+            case QEMU_OPTION_dom0_input:
-+                dom0_input = optarg;
-+                break;
-             case QEMU_OPTION_direct_pci:
-                direct_pci = optarg;
-                 break;
-@@ -6067,6 +6087,9 @@ int main(int argc, char **argv, char **envp)
-         close(fd);
-     }
-+    if (dom0_input)
-+      dom0_driver_init(dom0_input);
-+
-     xenstore_dm_finished_startup();
- #ifndef CONFIG_STUBDOM
-diff --git a/xen-hooks.mak b/xen-hooks.mak
-index 799f80d..c0212a2 100644
---- a/xen-hooks.mak
-+++ b/xen-hooks.mak
-@@ -37,6 +37,8 @@ OBJS += helper2.o
- OBJS += battery_mgmt.o
- OBJS += xen_acpi_wmi.o
- OBJS += thermal_mgmt.o
-+OBJS += dom0_driver.o
-+OBJS += hid-linux.o
- CONFIG_AUDIO=1
-diff --git a/xenstore.c b/xenstore.c
-index 3cd2ba6..17136a3 100644
---- a/xenstore.c
-+++ b/xenstore.c
-@@ -1741,3 +1741,63 @@ void xenstore_dm_finished_startup(void)
-     free(buf);
-     free(path);
- }
-+
-+char *xenstore_read_dom0_driver(const char *key)
-+{
-+    const char *path = "/local/domain/0/dom0_driver";
-+    char *buf = NULL;
-+    int len = 0;
-+    char *val = NULL;
-+
-+    if (pasprintf(&buf, "%s/%s", path, key) == -1)
-+        return NULL;
-+    val = xs_read(xsh, XBT_NULL, buf, &len);
-+    free(buf);
-+    return val;
-+}
-+
-+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque)
-+{
-+    const char *path = "/local/domain/0/dom0_driver";
-+    char *buf = NULL;
-+    int ret = 0;
-+
-+    if (pasprintf(&buf, "%s/%s", path, key) == -1)
-+        return 0;
-+    xenstore_watch_new_callback(buf, fptr, opaque);
-+    free(buf);
-+    return ret;
-+}
-+
-+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;
-+    int ret = 0;
-+
-+    if (pasprintf(&buf, "%s/%s", path, key) == -1)
-+        return 0;
-+    ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str));
-+    free(buf);
-+    return ret;
-+}
-+
-+int *xenstore_get_domids(int *len)
-+{
-+    int *tab = NULL;
-+    char **e;
-+
-+    e = xs_directory(xsh, XBT_NULL, "/local/domain", len);
-+    if (e == NULL)
-+    {
-+        len = 0;
-+        return NULL;
-+    }
-+
-+    tab = malloc(*len * sizeof (int));
-+    for (int i = 0; i < *len; i++)
-+        tab[i] = strtol(e[i], NULL, 10);
-+    return tab;
-+}
-+
diff --git a/master/fix-drop-mouse-keyboard b/master/fix-drop-mouse-keyboard
deleted file mode 100644 (file)
index 4b8d5ba..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/hid-linux.c b/hid-linux.c
-index 59dfec8..f2e0bce 100644
---- a/hid-linux.c
-+++ b/hid-linux.c
-@@ -47,6 +47,7 @@
- #define ABS(x)                        ((x) > 0 ? (x) : -(x))
- #define EVENT_PATH                            "/dev/input/event"
- #define HID_LINUX_MAX_DEV             16
-+#define HID_LINUX_MAX_DEV_NO          64
- #define DEBUG_HID_LINUX
-@@ -447,8 +448,11 @@ void hid_linux_probe(int grab)
-       sprintf(path, "%s%i", EVENT_PATH, i++);
-+      if (i>=HID_LINUX_MAX_DEV_NO)
-+              break;
-+
-       if (stat(path, &st) == -1)
--          break;
-+              continue;
-       for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++)
-           if (!strcmp(hid_linux_driver.controller_paths[c], path))
index 3896eb3c580727d1506347978a6c2d7aa01da4fb..53f8e6c3ccff95c3dae86a0e3178eac0bca46359 100644 (file)
@@ -1,5 +1,5 @@
 diff --git a/console.h b/console.h
-index 97214c0..def586a 100644
+index 14b42f3..7f2fdaa 100644
 --- a/console.h
 +++ b/console.h
 @@ -70,6 +70,8 @@ void kbd_put_keysym(int keysym);
@@ -22,39 +22,15 @@ index 97214c0..def586a 100644
  int is_graphic_console(void);
  int is_fixedsize_console(void);
  CharDriverState *text_console_init(const char *p);
-@@ -356,4 +362,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *);
- void hid_linux_reset_keyboard(void);
void hid_linux_probe(int grab);
+@@ -341,4 +347,8 @@ const char *readline_get_history(unsigned int index);
+ void readline_start(const char *prompt, int is_password,
                    ReadLineFunc *readline_func, void *opaque);
  
 +/* intel.c */
 +int intel_enter(void);
 +int intel_leave(void);
 +void intel_display_init(DisplayState *ds);
  #endif
-diff --git a/dom0_driver.c b/dom0_driver.c
-index 92f6b17..7f735a9 100644
---- a/dom0_driver.c
-+++ b/dom0_driver.c
-@@ -43,6 +43,7 @@
- #include <time.h>
- extern int vga_passthrough;
-+extern int intel;
- static void dom0_driver_state_change(const char *path, void *opaque);
- static void dom0_driver_command(const char *path, void *opaque);
-@@ -694,6 +695,11 @@ void dom0_driver_init(const char *position)
-         driver.enter = intel_enter;
-         driver.leave = intel_leave;
-     }
-+    else if (intel)
-+    {
-+        driver.enter = intel_enter;
-+        driver.leave = intel_leave;
-+    }
-     else
-     {
-       driver.enter = dom0_driver_dummy_enter_leave;
 diff --git a/hw/vga.c b/hw/vga.c
 index 90bd544..e4e27a9 100644
 --- a/hw/vga.c
@@ -224,552 +200,50 @@ index 90bd544..e4e27a9 100644
      s->graphic_mode = -1;
      vga_update_display(s);
 diff --git a/intel.c b/intel.c
-new file mode 100644
-index 0000000..46949f6
---- /dev/null
+index 62701cc..d603e89 100644
+--- a/intel.c
 +++ b/intel.c
-@@ -0,0 +1,500 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <sys/mman.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <assert.h>
-+#include <signal.h>
-+#include <pci/pci.h>
-+
-+#include "qemu-common.h"
-+#include "qemu-timer.h"
-+#include "console.h"
-+#include "sysemu.h"
-+
-+#include "intel_reg.h"
-+#include "intel.h"
-+
-+#define INTEL_DEBUG(format, args...)                                    \
-+    fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args);
-+
-+extern int                      vga_passthrough;
-+uint32_t                        guest_framebuffer;
-+int                             intel_output = INTEL_OUTPUT_BLITTED;
-+static int                      display = 0;
-+
-+static int                      mmio_fd = -1;
-+static int                      mem_fd = -1;
-+static uint8_t                  *intel_mem = NULL;
-+static uint8_t                  *intel_mmio = NULL;
-+static int                      intel_force_full_update = 0;
-+static int                      intel_have_focus;
-+static int                      IntelPitch = 16;
-+static int                      IntelX = 1280;
-+static int                      IntelY = 1024;
-+static DisplayState             *lds = NULL;
-+static uint32_t                 intel_fb_base, intel_mmio_base;
-+static uint32_t                 map_s, map_d, map_size;
-+static int                      refresh;
-+static QEMUTimer                *check_linear_timer = NULL;
-+
-+static void set_data_pointer(DisplaySurface *surf);
-+static void intel_resize(DisplayState *ds);
-+
-+static inline unsigned int intel_get_reg(unsigned int reg)
-+{
-+    return *(unsigned int*)(intel_mmio + reg);
-+}
-+
-+static char surfaenabled(void)
-+{
-+    return !!(intel_get_reg(REG_DR_DSPACNTR) & (1 << 31));
-+}
-+
-+static inline unsigned int intel_get_surface(void)
-+{
-+    if (surfaenabled())
-+        return intel_get_reg(REG_DR_DSPASURF);
-+    else
-+        return intel_get_reg(REG_DR_DSPBSURF);
-+}
-+
-+static inline void intel_get_res(unsigned int   *x,
-+                                 unsigned int   *y,
-+                                 unsigned int   *pitch)
-+{
-+    if (surfaenabled())
-+    {
-+        INTEL_DEBUG("Get resolution from PIPEA\n")
-+        *pitch = intel_get_reg(REG_DR_DSPASTRIDE);
-+        *x = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1;
-+        *y = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1;
-+    }
-+    else
-+    {
-+        INTEL_DEBUG("Get resolution from PIPEB\n")
-+        *pitch = intel_get_reg(REG_DR_DSPBSTRIDE);
-+        *x = ((intel_get_reg(REG_DE_PIPEBSRC) >> 16) & 0xfff) + 1;
-+        *y = (intel_get_reg(REG_DE_PIPEBSRC) & 0xfff) + 1;
-+    }
-+}
-+
-+
-+
-+static void intel_force_linear(int linesize)
-+{
-+    unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
-+    unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF);
-+    unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF);
-+    unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
-+
-+    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
-+    unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF);
-+    unsigned int *dspbsurf = (unsigned int *)(intel_mmio + REG_DR_DSPBSURF);
-+    unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE);
-+    volatile unsigned int *fbc_ctl = (unsigned int *)(intel_mmio + REG_FBC_CONTROL);
-+
-+    unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0;
-+    char pipeaenabled = !!(*pipeaconf & (1 << 30));
-+    char pipebenabled = !!(*pipebconf & (1 << 30));
-+
-+    INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
-+
-+    if (pipeaenabled)
-+    {
-+        INTEL_DEBUG("PIPEACONF enabled.\n");
-+        /* Disable surface */
-+        pipea = *pipeaconf & (0x3 << 18);
-+        *pipeaconf &= ~(0x3 << 18);
-+        *dspacntr |= (1 << 31);
-+        /* Address of the surface to map to */
-+        surfa = *dspasurf;
-+        *dspasurf = 0x00000000;
-+        *dspacntr &= ~(1 << 31);
-+        *dspasurf = 0x00000000;
-+        *pipeaconf |= pipea;
-+    }
-+
-+    if (pipebenabled) {
-+        INTEL_DEBUG("PIPEBCONF enabled.\n");
-+
-+        /* Disable surface */
-+        pipeb = *pipebconf & (0x3 << 18);
-+        *pipebconf &= ~(0x3 << 18);
-+        *dspbcntr |= (1 << 31);
-+        /* Address of the surface to map to */
-+        surfb = *dspbsurf;
-+        *dspbsurf = 0x00000000;
-+        *dspbcntr &= ~(1 << 31);
-+        *dspbsurf = 0x00000000;
-+        *pipebconf |= pipeb;
-+    }
-+
-+    usleep(50 * 1000); /* 50 ms */
-+
-+    if (pipeaenabled)
-+    {
-+        *pipeaconf &= ~(0x3 << 18);
-+        /* Enable surface linear mode */
-+        *dspacntr &= ~(1 << 10);
-+        if (linesize) *dspastride = linesize;
-+        *dspasurf = surfa;
-+        *dspacntr |= (1 << 31);
-+        *pipeaconf |= pipea;
-+    }
-+
-+    if (pipebenabled) {
-+        *pipebconf &= ~(0x3 << 18);
-+        /* Enable surface linear mode */
-+        *dspbcntr &= ~(1 << 10);
-+        if (linesize) *dspbstride = linesize;
-+        *dspbsurf = surfb;
-+        *dspbcntr |= (1 << 31);
-+        *pipebconf |= pipeb;
-+    }
-+    if (linesize) IntelPitch = linesize;
-+
-+    usleep(50 * 1000); /* 50 ms */
-+
-+    /* Clear the compression bit */
-+    *fbc_ctl &= ~(1 << 31);
-+    /* Wait for the status register */
-+    while (intel_get_reg(REG_FBC_STATUS) & (1 << 31))
-+        ;
-+}
-+
-+static void set_fb_mapping(void)
-+{
-+    DisplaySurface *surf = lds->surface;
-+    int rc;
-+    unsigned long nr_pfn;
-+
-+    intel_output = INTEL_OUTPUT_MAPPED;
-+
-+    unset_vga_acc();
-+    INTEL_DEBUG("set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_surface()), guest_framebuffer);
-+    nr_pfn = (ds_get_linesize(lds) * ds_get_height(lds)) >> TARGET_PAGE_BITS;
-+
-+    rc = xc_domain_memory_mapping(xc_handle,
-+            domid,
-+            (guest_framebuffer >> TARGET_PAGE_BITS),
-+            ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS),
-+            nr_pfn,
-+            DPCI_ADD_MAPPING);
-+    if (rc) {
-+        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
-+        return;
-+    }
-+    memcpy((uint8_t *)(intel_mem + intel_get_surface()),
-+            ds_get_data(lds), ds_get_linesize(lds) * ds_get_height(lds));
-+    map_s = ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS);
-+    map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
-+    map_size = nr_pfn;
-+}
-+
-+static void unset_fb_mapping(void)
-+{
-+    int rc;
-+
-+    INTEL_DEBUG("unset_fb_mapping: %x %x\n", map_d, map_s);
-+
-+    rc = xc_domain_memory_mapping(xc_handle,
-+            domid,
-+            map_d,
-+            map_s,
-+            map_size,
-+            DPCI_REMOVE_MAPPING);
-+    if (rc) {
-+        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
-+        return;
-+    }
-+
-+    set_vga_acc();
-+    intel_output = INTEL_OUTPUT_BLITTED;
-+    memcpy(ds_get_data(lds),
-+            (uint8_t *) (intel_mem + intel_get_surface()),
-+            ds_get_linesize(lds) * ds_get_height(lds));
-+    map_s = 0;
-+    map_d = 0;
-+    map_size = 0;
-+}
-+
-+
-+static void intel_update(DisplayState *ds, int x, int y, int w, int h)
-+{
-+    /* do nothing */
-+    int i, bpp = ds_get_bytes_per_pixel(ds);
-+    unsigned char *s, *d;
-+
-+    if (!intel_have_focus || !is_buffer_shared(ds->surface))
-+        return;
-+
-+    if ((x > IntelX || y > IntelY))
-+        return;
-+    if ((x + w) > IntelX)
-+        w = IntelX - x;
-+    if ((y + h) > IntelY)
-+        h = IntelY - y;
-+
-+    s = ds_get_data(ds);
-+    d = (unsigned char *)(intel_mem + intel_get_surface());
-+    /* Center the screen */
-+    if (ds_get_width(ds) < IntelX && ds_get_height(ds) < IntelY)
-+        d += IntelPitch * ((IntelY - ds_get_height(ds)) / 2) +
-+            4 * ((IntelX - ds_get_width(ds)) / 2);
-+
-+    s += (ds_get_linesize(ds) * y) + bpp * x;
-+    d += (IntelPitch * y) + bpp * x;
-+    for (i = 0; i < h; i++) {
-+        memcpy(d, s, w * bpp);
-+        s += ds_get_linesize(ds);
-+        d += IntelPitch;
-+    }
-+}
-+
-+static void intel_resize(DisplayState *ds)
-+{
-+    INTEL_DEBUG("intel_resize: shared=%d, width=%d, height=%d, depth=%d\n",
-+            is_buffer_shared(ds->surface),
-+            ds_get_width(ds),
-+            ds_get_height(ds),
-+            ds_get_bytes_per_pixel(ds));
-+    if (intel_have_focus)
-+    {
-+        if (ds_get_width(ds) == IntelX && ds_get_height(ds) == IntelY &&
-+                is_buffer_shared(ds->surface))
-+        {
-+            if (!map_size)
-+            {
-+                intel_force_linear(ds_get_linesize(ds));
-+                set_fb_mapping();
-+            }
-+        }
-+        else
-+        {
-+            if (map_size)
-+                unset_fb_mapping();
-+            else
-+                intel_force_linear(0);
-+        }
-+    } else {
-+        if (map_size)
-+            unset_fb_mapping();
-+    }
-+}
-+
-+static void intel_setdata(DisplayState *ds)
-+{
-+    if (!map_size)
-+        return;
-+    unset_fb_mapping();
-+    set_fb_mapping();
-+}
-+
-+static void intel_refresh(DisplayState *ds)
-+{
-+    vga_hw_update();
-+}
-+
-+static void intel_init_mapping(void)
-+{
-+    struct pci_access   *pci_bus;
-+    struct pci_dev      *pci_dev;
-+
-+    mmio_fd = open("/dev/mem", O_RDWR);
-+    if (mmio_fd == -1)
-+    {
-+        perror("open");
-+        exit(1);
-+    }
-+    mem_fd = open("/dev/mem", O_RDWR);
-+    if (mem_fd == -1)
-+    {
-+        perror("open");
-+        exit(1);
-+    }
-+
-+    pci_bus = pci_alloc();
-+    pci_init(pci_bus);
-+    pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0);
-+    pci_fill_info(pci_dev, PCI_FILL_BASES);
-+    intel_fb_base = pci_dev->base_addr[2] & 0xfffff000;
-+    intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000;
-+    pci_free_dev(pci_dev);
-+    pci_cleanup(pci_bus);
-+
-+    INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base);
-+    intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED,
-+                     mem_fd, intel_fb_base);
-+    if (intel_mem == MAP_FAILED)
-+    {
-+        perror("mmap");
-+        exit(1);
-+    }
-+
-+    INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base);
-+    intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED,
-+                      mmio_fd, intel_mmio_base);
-+    if (intel_mmio == MAP_FAILED)
-+    {
-+        perror("mmap");
-+        exit(1);
-+    }
-+}
-+
-+static void set_data_pointer(DisplaySurface *surf)
-+{
-+    surf->data = (unsigned char *)(intel_mem + intel_get_surface());
-+    memset(surf->data, 0x00, surf->linesize * IntelY);
-+    surf->data = surf->data +
-+                surf->linesize * ((IntelY - surf->height) / 2) +
-+                4 * ((IntelX - surf->width) / 2);
-+}
-+
-+static int intel_getfocus(void)
-+{
-+    return intel_have_focus;
-+}
-+
-+static inline int is_linear(void)
-+{
-+    if (surfaenabled())
-+        return (intel_get_reg(REG_DR_DSPACNTR) & (1 << 10)) == 0;
-+    else
-+        return (intel_get_reg(REG_DR_DSPBCNTR) & (1 << 10)) == 0;
-+}
-+
-+static void intel_check_linear(void)
-+{
-+    if (!check_linear_timer)
-+        check_linear_timer = qemu_new_timer(rt_clock, intel_check_linear, NULL);
-+
-+    if (intel_have_focus && !is_linear())
-+    {
-+        intel_force_linear(0);
-+        vga_hw_invalidate();
-+        vga_hw_update();
-+    }
-+
-+    if (intel_have_focus)
-+        qemu_mod_timer(check_linear_timer,
-+                qemu_get_clock(rt_clock) + 4000);
-+}
-+
-+static void intel_focus(int focus)
-+{
-+    if (intel_have_focus == focus)
-+        return;
-+
-+    intel_have_focus = focus;
-+    if (intel_have_focus) {
-+        intel_get_res(&IntelX, &IntelY, &IntelPitch);
-+
-+        if (!guest_framebuffer)
-+            intel_force_linear(0);
-+        memset((uint8_t *)(intel_mem + intel_get_surface()), 0,
-+                IntelX * IntelY * 4);
-+    }
-+    vga_hw_invalidate();
-+    vga_hw_update();
-+    intel_check_linear();
-+
-+    INTEL_DEBUG("intel_focus %d, x=%d, y=%d, stride=%d\n",
-+            focus, IntelX, IntelY, IntelPitch);
-+}
-+
-+int intel_enter(void)
-+{
-+    intel_focus(1);
-+    return 1;
-+}
-+
-+int intel_leave(void)
-+{
-+    intel_focus(0);
-+    return 1;
-+}
-+
-+static DisplaySurface* intel_create_displaysurface(int width, int height)
-+{
-+    DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
-+    if (surface == NULL) {
-+        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
-+        exit(1);
-+    }
-+
-+    surface->width = width;
-+    surface->height = height;
-+
-+    INTEL_DEBUG("intel_create_displaysurface: focus=%d %d %d\n", intel_have_focus, width, height);
-+    if (intel_have_focus) {
-+        surface->pf = qemu_default_pixelformat(32);
-+        surface->flags = QEMU_ALLOCATED_FLAG | INTEL_MAPPED_FLAG;
-+        surface->linesize = IntelPitch;
-+        set_data_pointer(surface);
-+    } else {
-+        surface->data = qemu_mallocz(width * height * 4);
-+        surface->linesize = width * 4;
-+        surface->pf = qemu_default_pixelformat(32);
-+        surface->flags = QEMU_ALLOCATED_FLAG;
-+    }
-+
-+    return surface;
-+}
-+
-+static void intel_free_displaysurface(DisplaySurface *surface)
-+{
-+    if (surface == NULL)
+@@ -11,6 +11,7 @@
+ #include "qemu-common.h"
+ #include "qemu-timer.h"
++#include "qemu-xen.h"
+ #include "console.h"
+ #include "sysemu.h"
+@@ -405,24 +406,16 @@ static void intel_focus(int focus)
+             focus, IntelX, IntelY, IntelPitch);
+ }
+-int intel_enter(void)
+-{
+-    intel_focus(1);
+-    return 1;
+-}
+-
+-int intel_leave(void)
+-{
+-    intel_focus(0);
+-    return 1;
+-}
+-
+-void intel_enter_leave(const char *path, void *opaque)
++static void intel_enter_leave(const char *path, void *opaque)
+ {
++    char *tmp;
+     int state;
+     int enter = (int)opaque;
+-    state = xenstore_dom_read(domid, path, NULL);
++    if (!(tmp = xenstore_dom_read(domid, path, NULL)))
 +        return;
-+    if ((!(surface->flags & INTEL_MAPPED_FLAG)) && (surface->flags & QEMU_ALLOCATED_FLAG))
-+        qemu_free(surface->data);
-+    qemu_free(surface);
-+}
-+
-+static DisplaySurface* intel_resize_displaysurface(DisplaySurface *surface, int width, int height)
-+{
-+    intel_free_displaysurface(surface);
-+    if (map_size)
-+        unset_fb_mapping();
-+    return intel_create_displaysurface(width, height);
-+}
-+
-+void intel_display_init(DisplayState *ds)
-+{
-+    DisplayChangeListener *dcl;
-+    DisplayAllocator *da;
-+
-+    intel_init_mapping();
-+
-+    INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_surface());
-+
-+    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
-+    if (!dcl)
-+        exit(1);
-+    dcl->dpy_update = intel_update;
-+    dcl->dpy_resize = intel_resize;
-+    dcl->dpy_setdata = intel_setdata;
-+    dcl->dpy_refresh = intel_refresh;
-+    register_displaychangelistener(ds, dcl);
-+
-+    da = qemu_mallocz(sizeof(DisplayAllocator));
-+    if (!da)
-+        exit(1);
-+    da->create_displaysurface = intel_create_displaysurface;
-+    da->resize_displaysurface = intel_resize_displaysurface;
-+    da->free_displaysurface = intel_free_displaysurface;
-+    if (register_displayallocator(ds, da) != da) {
-+        fprintf(stderr, "intel_display_init: could not register DisplayAllocator\n");
-+        exit(1);
-+    } else {
-+        DisplaySurface *surf;
-+        surf = intel_create_displaysurface(ds_get_width(ds), ds_get_height(ds));
-+        defaultallocator_free_displaysurface(ds->surface);
-+        ds->surface = surf;
-+        dpy_resize(ds);
-+    }
-+
-+    lds = ds;
-+}
-diff --git a/intel.h b/intel.h
-new file mode 100644
-index 0000000..25086be
---- /dev/null
-+++ b/intel.h
-@@ -0,0 +1,5 @@
-+extern int intel_output;
-+#define INTEL_OUTPUT_UNDEF    0
-+#define INTEL_OUTPUT_MAPPED   1
-+#define INTEL_OUTPUT_BLITTED  2
-+
-diff --git a/intel_reg.h b/intel_reg.h
-new file mode 100644
-index 0000000..cd7855e
---- /dev/null
-+++ b/intel_reg.h
-@@ -0,0 +1,22 @@
-+
-+#define TileW           128
-+#define TileH           8
-+
-+#define REG_DR_DSPASURF         0x7019C
-+#define REG_DR_DSPACNTR         0x70180
-+#define REG_DR_DSPASTRIDE       0x70188
-+#define REG_DR_PIPEACONF        0x70008
-+
-+#define REG_DR_DSPBSURF         0x7119C
-+#define REG_DR_DSPBCNTR         0x71180
-+#define REG_DR_DSPBSTRIDE       0x71188
-+#define REG_DR_PIPEBCONF      0x71008
-+
-+#define REG_DE_PIPEASRC               0x6001c
-+#define REG_DE_PIPEBSRC               0x6101c
-+
-+#define REG_FBC_CONTROL         0x03208
-+#define REG_FBC_STATUS          0x03210
-+
-+
-+
++    state = strtol(tmp, NULL, 10);
++    free(tmp);
+     if (state == 1)
+     {
+         intel_focus(enter);
 diff --git a/vl.c b/vl.c
-index adfa4f6..a040403 100644
+index 6350384..cf7ad19 100644
 --- a/vl.c
 +++ b/vl.c
 @@ -235,6 +235,7 @@ int win2k_install_hack = 0;
@@ -796,7 +270,7 @@ index adfa4f6..a040403 100644
  #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
      { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
      { "xen-create", 0, QEMU_OPTION_xen_create },
-@@ -5319,6 +5322,9 @@ int main(int argc, char **argv, char **envp)
+@@ -5318,6 +5321,9 @@ int main(int argc, char **argv, char **envp)
              case QEMU_OPTION_dom0_input:
                  dom0_input = optarg;
                  break;
@@ -806,7 +280,7 @@ index adfa4f6..a040403 100644
              case QEMU_OPTION_direct_pci:
                 direct_pci = optarg;
                  break;
-@@ -5923,26 +5929,26 @@ int main(int argc, char **argv, char **envp)
+@@ -5922,26 +5928,26 @@ int main(int argc, char **argv, char **envp)
                  curses_display_init(ds, full_screen);
              } else
  #endif
@@ -851,13 +325,13 @@ index adfa4f6..a040403 100644
      dpy_resize(ds);
  
 diff --git a/xen-hooks.mak b/xen-hooks.mak
-index c0212a2..b90967d 100644
+index 1ed197f..88aff50 100644
 --- a/xen-hooks.mak
 +++ b/xen-hooks.mak
-@@ -39,6 +39,7 @@ OBJS += xen_acpi_wmi.o
+@@ -38,6 +38,7 @@ OBJS += battery_mgmt.o
+ OBJS += xen_acpi_wmi.o
  OBJS += thermal_mgmt.o
- OBJS += dom0_driver.o
- OBJS += hid-linux.o
+ OBJS += switcher.o
 +OBJS += intel.o
  
  CONFIG_AUDIO=1
diff --git a/master/new-input-code b/master/new-input-code
deleted file mode 100644 (file)
index 78b384b..0000000
+++ /dev/null
@@ -1,1030 +0,0 @@
-diff --git a/hid-linux.c b/hid-linux.c
-index f2e0bce..a4b0cd6 100644
---- a/hid-linux.c
-+++ b/hid-linux.c
-@@ -42,12 +42,11 @@
- #include <assert.h>
- #include <time.h>
- #include <sys/time.h>
-+#include <utime.h>
--#define HID_LINUX_XS_PATH             "/local/domain/0/hid_linux"
-+#define HID_LINUX_ACTIVITY_FILE         "/tmp/.qemu.hid-linux.stamp"
-+#define HID_LINUX_XS_PATH             "/local/domain/0/linux_hid_driver"
- #define ABS(x)                        ((x) > 0 ? (x) : -(x))
--#define EVENT_PATH                            "/dev/input/event"
--#define HID_LINUX_MAX_DEV             16
--#define HID_LINUX_MAX_DEV_NO          64
- #define DEBUG_HID_LINUX
-@@ -64,468 +63,649 @@ while (0);
- # define DEBUG(_format_, args...) (void)0
- #endif
--static struct hid_linux_driver
-+
-+#define N_DEVS 64
-+
-+#define HID_TYPE_KEYBOARD     1
-+#define HID_TYPE_MOUSE                2
-+
-+
-+static struct linux_hid_driver
- {
--    int               keyboard_fds[HID_LINUX_MAX_DEV / 2];
--    int               mouse_fds[HID_LINUX_MAX_DEV / 2];
--    char      *controller_paths[HID_LINUX_MAX_DEV];
--    int               mouse_button_state;
--    int               key_status[256];
--    void      (*secure_key)(int ascii);
--} hid_linux_driver;
--
--struct hid_linux_binding
-+  QEMUTimer *scan_timer;
-+  int keyboard_grabbed;
-+  int mouse_grabbed;
-+  int types[N_DEVS];
-+  int fds[N_DEVS];
-+  int mouse_button_state;
-+  int key_status[256];
-+  time_t last_activity;
-+  void (*secure_key) (int ascii);
-+} linux_hid_driver;
-+
-+struct linux_hid_binding
- {
--    int       *binding;
--    void      (*cb)(void *);
--    void      *payload;
-+  int *binding;
-+  void (*cb) (void *);
-+  void *payload;
- };
--static struct hid_linux_binding *hid_linux_binding = NULL;
-+static struct linux_hid_binding *linux_hid_binding = NULL;
--static const int ascii2keycode_table[] =
--{
--    KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
--    KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
--    KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
-+static const int ascii2keycode_table[] = {
-+  KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
-+  KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
-+  KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
- };
--static char keycode2ascii(int keycode)
-+static int hid_linux_detect_binding (void);
-+static void hid_linux_key_inject (int code, uint32_t keycode);
-+static char *hid_linux_xs_read (const char *key);
-+
-+
-+static char
-+keycode2ascii (int keycode)
- {
--    int i = 0;
-+  int i = 0;
--    switch (keycode)
-+  switch (keycode)
-     {
--      case KEY_ESC: return 27;
--      case KEY_BACKSPACE: return 8;
--      case KEY_ENTER: return 10;
--      case KEY_LEFT: return 17;
--      case KEY_RIGHT: return 18;
--      case KEY_DELETE: return 127;
--      case KEY_HOME: return 2;
--      case KEY_END: return 3;
--      case KEY_INSERT: return 19;
--      case KEY_SPACE: return 20;
--      default:
--              for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
--                  if (ascii2keycode_table[i] == keycode)
--                      return i + 'a';
-+    case KEY_ESC:
-+      return 27;
-+    case KEY_BACKSPACE:
-+      return 8;
-+    case KEY_ENTER:
-+      return 10;
-+    case KEY_LEFT:
-+      return 17;
-+    case KEY_RIGHT:
-+      return 18;
-+    case KEY_DELETE:
-+      return 127;
-+    case KEY_HOME:
-+      return 2;
-+    case KEY_END:
-+      return 3;
-+    case KEY_INSERT:
-+      return 19;
-+    case KEY_SPACE:
-+      return 20;
-+    default:
-+      for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
-+        if (ascii2keycode_table[i] == keycode)
-+          return i + 'a';
-     }
--    return 0;
-+  return 0;
- }
--static int ascii2keycode(char ascii)
-+static int
-+ascii2keycode (char ascii)
- {
--    return ascii2keycode_table[ascii - 'a'];
-+  return ascii2keycode_table[ascii - 'a'];
- }
--static char *hid_linux_xs_read(const char *key)
-+static char *
-+hid_linux_xs_read (const char *key)
- {
--    char *path = NULL;
--    char *ret;
--
--    if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1)
--      return NULL;
--    ret = xenstore_read(path);
--    free(path);
--    return ret;
-+  char *path = NULL;
-+  char *ret;
-+
-+  if (asprintf (&path, HID_LINUX_XS_PATH "/%s", key) == -1)
-+    return NULL;
-+  ret = xenstore_read (path);
-+  free (path);
-+  return ret;
- }
--void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload)
-+void
-+hid_linux_add_binding (const int *tab, void (*cb) (void *), void *payload)
- {
--    int i = 0, j = 0;
--
--    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
--      ;
--    hid_linux_binding = realloc(hid_linux_binding,
--                              (i + 2) * sizeof (struct hid_linux_binding));
--    hid_linux_binding[i + 1].cb = NULL;
--    hid_linux_binding[i].cb = cb;
--    hid_linux_binding[i].payload = payload;
--    hid_linux_binding[i].binding = NULL;
--
--    j = 0;
--    do
-+  int i = 0, j = 0;
-+
-+  for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++)
-+    ;
-+  linux_hid_binding = realloc (linux_hid_binding,
-+                               (i + 2) * sizeof (struct linux_hid_binding));
-+  linux_hid_binding[i + 1].cb = NULL;
-+  linux_hid_binding[i].cb = cb;
-+  linux_hid_binding[i].payload = payload;
-+  linux_hid_binding[i].binding = NULL;
-+
-+  j = 0;
-+  do
-     {
--      hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding,
--                                             (j + 1) * sizeof (int));
--      hid_linux_binding[i].binding[j] = tab[j];
-+      linux_hid_binding[i].binding = realloc (linux_hid_binding[i].binding,
-+                                              (j + 1) * sizeof (int));
-+      linux_hid_binding[i].binding[j] = tab[j];
-     }
--    while (tab[j++] != -1);
-+  while (tab[j++] != -1);
- }
--static int hid_linux_detect_binding(void)
-+static int
-+hid_linux_detect_binding (void)
- {
--    int i, j;
-+  int i, j;
--    for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
-+  for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++)
-     {
--      int *tab = hid_linux_binding[i].binding;
--
--      for (j = 0; tab[j] != -1; j++)
--          if (hid_linux_driver.key_status[tab[j]] == 0)
--              break;
--      if (tab[j] != -1)
--          continue;
--      else /* We match a binding */
--      {
--          DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload));
--          hid_linux_binding[i].cb(hid_linux_binding[i].payload);
--          hid_linux_reset_keyboard();
--          return 1;
--      }
-+      int *tab = linux_hid_binding[i].binding;
-+
-+      for (j = 0; tab[j] != -1; j++)
-+        if (linux_hid_driver.key_status[tab[j]] == 0)
-+          break;
-+      if (tab[j] != -1)
-+        continue;
-+      else                      /* We match a binding */
-+        {
-+          DEBUG ("binding payload %d\n",
-+                 (int) (linux_hid_binding[i].payload));
-+          linux_hid_binding[i].cb (linux_hid_binding[i].payload);
-+          hid_linux_reset_keyboard ();
-+          return 1;
-+        }
-     }
--    return 0;
-+  return 0;
- }
--static void hid_linux_key_inject(int code, uint32_t keycode)
-+static void
-+hid_linux_key_inject (int code, uint32_t keycode)
- {
--    int first = 0;
-+  int first = 0;
--    switch (keycode)
-+  switch (keycode)
-     {
--      case KEY_F11:       keycode = 0X57; break; /* F11 */
--      case KEY_F12:       keycode = 0X58; break; /* F12 */
--      case KEY_INSERT:    keycode = 0X52; break;
--      case KEY_HOME:      keycode = 0X47; break;
--      case KEY_PAGEUP:    keycode = 0X49; break;
--      case KEY_DELETE:    keycode = 0X53; break;
--      case KEY_END:       keycode = 0X4F; break;
--      case KEY_PAGEDOWN:  keycode = 0x51; break;
--      case KEY_UP:        keycode = 0X48; break;
--      case KEY_LEFT:      keycode = 0X4B; break;
--      case KEY_DOWN:      keycode = 0X50; break;
--      case KEY_RIGHT:     keycode = 0X4D; break;
--      case KEY_RIGHTALT:  keycode = 0x38; first = 0xe0; break;
--      case KEY_LEFTMETA:  keycode = 0x5B; first = 0xe0; break;
--      case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break;
-+    case KEY_F11:
-+      keycode = 0X57;
-+      break;                    /* F11 */
-+    case KEY_F12:
-+      keycode = 0X58;
-+      break;                    /* F12 */
-+    case KEY_INSERT:
-+      keycode = 0X52;
-+      break;
-+    case KEY_HOME:
-+      keycode = 0X47;
-+      break;
-+    case KEY_PAGEUP:
-+      keycode = 0X49;
-+      break;
-+    case KEY_DELETE:
-+      keycode = 0X53;
-+      break;
-+    case KEY_END:
-+      keycode = 0X4F;
-+      break;
-+    case KEY_PAGEDOWN:
-+      keycode = 0x51;
-+      break;
-+    case KEY_UP:
-+      keycode = 0X48;
-+      break;
-+    case KEY_LEFT:
-+      keycode = 0X4B;
-+      break;
-+    case KEY_DOWN:
-+      keycode = 0X50;
-+      break;
-+    case KEY_RIGHT:
-+      keycode = 0X4D;
-+      break;
-+    case KEY_RIGHTALT:
-+      keycode = 0x38;
-+      first = 0xe0;
-+      break;
-+    case KEY_LEFTMETA:
-+      keycode = 0x5B;
-+      first = 0xe0;
-+      break;
-+    case KEY_RIGHTMETA:
-+      keycode = 0x5C;
-+      first = 0xe0;
-+      break;
-+    case KEY_PROG1:
-+      keycode = 0x1;
-+      first = 0xe0;
-+      break;
-+    case KEY_SYSRQ:
-+      keycode = 0x37;
-+      first = 0xe0;
-+      break;
-+    case KEY_MUTE:
-+      keycode = 0x20;
-+      first = 0xe0;
-+      break;
-+    case KEY_VOLUMEDOWN:
-+      keycode = 0x2e;
-+      first = 0xe0;
-+      break;
-+    case KEY_VOLUMEUP:
-+      keycode = 0x30;
-+      first = 0xe0;
-+      break;
-     }
--    if (first)
--      kbd_put_keycode(first);
-+  if (first)
-+    kbd_put_keycode (first);
--    if (code == 0)
--      kbd_put_keycode(keycode | 0x80);
--    else
--      kbd_put_keycode(keycode & 0x7f);
-+  if (code == 0)
-+    kbd_put_keycode (keycode | 0x80);
-+  else
-+    kbd_put_keycode (keycode & 0x7f);
- }
--
--
--static void hid_linux_key_event(int code, uint32_t keycode)
-+static void
-+linux_hid_key_event (int code, uint32_t keycode)
- {
--    if (code == 1)
--      if (hid_linux_detect_binding())
--          return;
--    hid_linux_key_inject(code, keycode);
-+  int fd;
-+
-+  if (code == 1)
-+    if (hid_linux_detect_binding ())
-+      return;
-+  hid_linux_key_inject (code, keycode);
- }
--static void hid_linux_read(void *opaque)
-+
-+static int
-+hid_linux_read (int fd)
- {
--    struct input_event  event[5];
--    int                 i = 0;
--    int                 read_sz = 0;
--    int                 fd = *(int *)opaque;
-+  struct input_event event[5];
-+  int i = 0;
-+  int read_sz = 0;
--    read_sz = read(fd, event, sizeof (event));
--    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
-+  read_sz = read (fd, event, sizeof (event));
-+  if (read_sz <= 0)
-+    return -1;
-+
-+  close(creat(HID_LINUX_ACTIVITY_FILE, S_IRUSR | S_IRWXU));
-+  utime(HID_LINUX_ACTIVITY_FILE, NULL);
-+
-+  for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
-     {
--      if (event[i].type == EV_KEY)
--      {
--          if (event[i].code >= BTN_MOUSE)
--          {
--              /* Mouse Key */
--              int     type = 0;
--
--              switch(event[i].code)
--              {
--                  case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
--                  case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
--                  case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break;
--              }
--
--              if (event[i].value)
--                  hid_linux_driver.mouse_button_state |= type;
--              else
--                  hid_linux_driver.mouse_button_state &= ~type;
--              kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state);
--          }
--          else
--          {
--              hid_linux_driver.key_status[event[i].code] = event[i].value;
--              hid_linux_key_event(event[i].value, event[i].code);
--          }
--      }
--
--      if (event[i].type == EV_REL || event[i].type == EV_ABS)
--      {
--          /* Mouse motion */
--          int x = 0, y = 0, z = 0;
--
--          if (event[i].type == EV_REL)
--              switch (event[i].code)
--              {
--                  case REL_X : x = event[i].value; break;
--                  case REL_Y : y = event[i].value; break;
--                  case REL_WHEEL : z = -event[i].value; break;
--              }
--          if (event[i].type == EV_ABS)
--          {
--              static int last_x = 1, last_y = 1;
--              int px = 0, py = 0, l = 50;
--              double div = 1;
--              char *str = NULL;
--
--              str = hid_linux_xs_read("touchpad-limit");
--              if (str)
--                  l = strtol(str, NULL, 10);
--              str = hid_linux_xs_read("touchpad-div");
--              if (str)
--                  div = strtol(str, NULL, 10) / 1000.;
--
--              switch (event[i].code)
--              {
--                  case ABS_X : x = event[i].value; break;
--                  case ABS_Y : y = event[i].value; break;
--              }
--
--              if (x)
--              {
--                  px = x - last_x;
--                  last_x = x;
--              }
--              if (y)
--              {
--                  py = y - last_y;
--                  last_y = y;
--              }
--
--              x = (ABS(px) < l ? px : 0) / div;
--              y = (ABS(py) < l ? py : 0) / div;
--          }
--
--          kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state);
--      }
-+      if (event[i].type == EV_KEY)
-+        {
-+          if (event[i].code >= BTN_MOUSE)
-+            {
-+              /* Mouse Key */
-+              int type = 0;
-+
-+              switch (event[i].code)
-+                {
-+                case BTN_LEFT:
-+                  type = MOUSE_EVENT_LBUTTON;
-+                  break;
-+                case BTN_RIGHT:
-+                  type = MOUSE_EVENT_RBUTTON;
-+                  break;
-+                case BTN_MIDDLE:
-+                  type = MOUSE_EVENT_MBUTTON;
-+                  break;
-+                }
-+
-+              if (event[i].value)
-+                linux_hid_driver.mouse_button_state |= type;
-+              else
-+                linux_hid_driver.mouse_button_state &= ~type;
-+              kbd_mouse_event (0, 0, 0, linux_hid_driver.mouse_button_state);
-+            }
-+          else
-+            {
-+              linux_hid_driver.key_status[event[i].code] = event[i].value;
-+              linux_hid_key_event (event[i].value, event[i].code);
-+            }
-+        }
-+
-+      if (event[i].type == EV_REL || event[i].type == EV_ABS)
-+        {
-+          /* Mouse motion */
-+          int x = 0, y = 0, z = 0;
-+
-+          if (event[i].type == EV_REL)
-+            switch (event[i].code)
-+              {
-+              case REL_X:
-+                x = event[i].value;
-+                break;
-+              case REL_Y:
-+                y = event[i].value;
-+                break;
-+              case REL_WHEEL:
-+                z = -event[i].value;
-+                break;
-+              }
-+          if (event[i].type == EV_ABS)
-+            {
-+              static int last_x = 1, last_y = 1;
-+              int px = 0, py = 0, l = 50;
-+              double div = 1;
-+              char *str = NULL;
-+
-+              str = hid_linux_xs_read ("touchpad-limit");
-+              if (str)
-+                l = strtol (str, NULL, 10);
-+              str = hid_linux_xs_read ("touchpad-div");
-+              if (str)
-+                div = strtol (str, NULL, 10) / 1000.;
-+
-+              switch (event[i].code)
-+                {
-+                case ABS_X:
-+                  x = event[i].value;
-+                  break;
-+                case ABS_Y:
-+                  y = event[i].value;
-+                  break;
-+                }
-+
-+              if (x)
-+                {
-+                  px = x - last_x;
-+                  last_x = x;
-+                }
-+              if (y)
-+                {
-+                  py = y - last_y;
-+                  last_y = y;
-+                }
-+
-+              x = (ABS (px) < l ? px : 0) / div;
-+              y = (ABS (py) < l ? py : 0) / div;
-+            }
-+
-+          kbd_mouse_event (x, y, z, linux_hid_driver.mouse_button_state);
-+        }
-     }
-+  return 0;
- }
--void hid_linux_reset_keyboard(void)
-+void
-+hid_linux_reset_keyboard (void)
- {
--    int i = 0;
--
--    for (i = 0; i < 256; i++)
--      if (hid_linux_driver.key_status[i])
--      {
--          hid_linux_key_inject(0, i);
--          hid_linux_driver.key_status[i] = 0;
--      }
-+  int i = 0;
-+
-+  for (i = 0; i < 256; i++)
-+    if (linux_hid_driver.key_status[i])
-+      {
-+        hid_linux_key_inject (0, i);
-+        linux_hid_driver.key_status[i] = 0;
-+      }
- }
-+static int
-+hid_linux_secure_read (int fd)
-+{
-+  struct input_event event[5];
-+  int i = 0;
-+  int read_sz = 0;
-+
-+  assert (linux_hid_driver.secure_key);
--static void hid_linux_redirect_fds(int *fd, IOHandler *cb)
-+  read_sz = read (fd, event, sizeof (event));
-+
-+  if (read_sz <= 0)
-+    return -1;
-+
-+  for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
-+    if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
-+        event[i].value > 0)
-+      linux_hid_driver.secure_key (keycode2ascii (event[i].code));
-+
-+  return 0;
-+}
-+
-+
-+
-+static int
-+hid_linux_do_read (void *opaque)
- {
--    assert(fd != NULL);
-+  int result;
-+  int slot = (int) opaque;
-+
-+  if (slot < 0)
-+    return 0;
-+  if (slot >= N_DEVS)
-+    return 0;
-+
-+  if (linux_hid_driver.secure_key)
-+    result = hid_linux_secure_read (linux_hid_driver.fds[slot]);
-+  else
-+    result = hid_linux_read (linux_hid_driver.fds[slot]);
--    while (*fd != -1)
-+  if (result)
-     {
--      qemu_set_fd_handler(*fd, cb, NULL, fd);
--      fd++;
-+      /* The read failed - stop watching and close the fd */
-+
-+      fprintf (stderr,
-+               "read failed on /dev/input/event%d fd=%d dropping it\n", slot,
-+               linux_hid_driver.fds[slot]);
-+
-+      qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL);
-+      close (linux_hid_driver.fds[slot]);
-+      linux_hid_driver.fds[slot] = -1;
-     }
-+
-+  return 0;
- }
--static void hid_linux_secure_read(void *opaque)
-+
-+void
-+hid_linux_secure_keyboard (void (*cb) (int ascii))
- {
--    struct input_event  event[5];
--    int                 i = 0;
--    int                 read_sz = 0;
--    int                 fd = *(int *)opaque;
--
--    assert(hid_linux_driver.secure_key);
--
--    read_sz = read(fd, event, sizeof (event));
--    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
--      if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
--              event[i].value > 0)
--          hid_linux_driver.secure_key(keycode2ascii(event[i].code));
-+  linux_hid_driver.secure_key = cb;
- }
--void hid_linux_secure_keyboard(void (*cb)(int ascii))
-+
-+static void
-+set_handler (int slot, int onoff)
- {
--    hid_linux_driver.secure_key = cb;
--    if (cb)
--      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
--              hid_linux_secure_read);
--    else
--      hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
--              hid_linux_read);
-+
-+  if (onoff)
-+    qemu_set_fd_handler (linux_hid_driver.fds[slot], hid_linux_do_read, NULL,
-+                         (void *) slot);
-+  else
-+    qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL);
-+
- }
--static int hid_linux_grab_devices(int grab, int *fd)
-+
-+static int
-+try_to_grab (int fd, int grab)
- {
--    int rc = 0;
--    int try = 10;
-+  int try = 10;
--    assert(fd != NULL && *fd != -1);
--    for (; *fd != -1; fd++)
-+  while (try--)
-     {
--      while (try--)
--      {
--          if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1)
--          {
--              char *er;
--
--              if (errno == EBUSY)
--                  continue;
--              er = strerror(errno);
--              DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er);
--              return 0;
--          }
--          else
--              break;
--      }
--      assert(try);
--
--      DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd);
--
--      if (grab)
--          qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd);
--      else
--          qemu_set_fd_handler(*fd, NULL, NULL, fd);
-+      char *er;
-+      if (!ioctl (fd, EVIOCGRAB, grab))
-+        return 0;
-+
-+      if (errno != EBUSY)
-+        {
-+          er = strerror (errno);
-+          DEBUG ("ioctl(%d, EVOCGRAB) failed, %s\n", fd, er);
-+          return -1;
-+        }
-+
-+      /*FIXME -- backoff */
-     }
--    return 1;
-+
-+  return -1;
- }
--int hid_linux_grab_keyboard(int grab)
-+
-+static int
-+do_grab (int type, int grab)
- {
--    return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds);
-+  int i;
-+  int fail = 0;
-+
-+  for (i = 0; i < N_DEVS; ++i)
-+    {
-+      if (linux_hid_driver.fds[i] < 0)
-+        continue;
-+      if (linux_hid_driver.types[i] != type)
-+        continue;
-+
-+      if (try_to_grab (linux_hid_driver.fds[i], grab))
-+        {
-+          fail++;
-+          fprintf (stderr, "Failed to grab /dev/input/event%d\n", i);
-+        }
-+
-+      set_handler (i, grab);
-+
-+    }
-+
-+  return fail ? 0 : 1;
- }
--int hid_linux_grab_mouse(int grab)
-+int
-+hid_linux_grab_keyboard (int grab)
- {
--    return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds);
-+  linux_hid_driver.keyboard_grabbed = grab; /*So new devices know which mode to be in */
-+  return do_grab (HID_TYPE_KEYBOARD, grab);
- }
--static int hid_linux_open_timeout(const char *path, int flags)
-+int
-+hid_linux_grab_mouse (int grab)
- {
--   int        try = 10;
--   int  fd = 0;
--
--   while (try-- && ((fd = open(path, flags)) == -1))
--       usleep(100000); /* 10 ms */
--   if (try == 0)
--       return 0;
--   return fd == -1 ? 0 : fd;
-+  linux_hid_driver.mouse_grabbed = grab; /*So new devices know which mode to be in */
-+  return do_grab (HID_TYPE_MOUSE, grab);
- }
--static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2)
-+
-+static int
-+consider_device (int slot)
- {
--   int        try = 10;
-+  int fd = linux_hid_driver.fds[slot];
--   while (try-- && ioctl(fd, arg1, arg2) == -1)
--       usleep(100000); /* 10 ms */
--   if (try == 0)
--       return 0;
--   return 1;
--}
-+  char name[128] = { 0 };
-+  struct input_id id;
--void hid_linux_probe(int grab)
--{
--    int                 i = 0, j = 0, c = 0;
--    int                 fd = -1;
--    int                 keyboard = 0, mouse = 0;
--    char                path[strlen(EVENT_PATH) + 3];
--    char                name[128];
--    int                       *controllers;
--    struct input_id     id;
--    struct stat       st;
--
--    while (1)
-+  if (ioctl (fd, EVIOCGNAME (sizeof (name)), name) == -1)
-+    return -1;
-+  if (ioctl (fd, EVIOCGID, &id) == -1)
-+    return -1;
-+
-+  if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
-+    return -1;
-+
-+  name[sizeof (name) - 1] = 0;
-+
-+
-+
-+  if (strcasestr (name, "keyboard"))
-+    {
-+      fprintf (stderr, "/dev/input/event%d added keyboard on fd %d (%s)\n",
-+               slot, fd, name);
-+      linux_hid_driver.types[slot] = HID_TYPE_KEYBOARD;
-+
-+      set_handler (slot, linux_hid_driver.keyboard_grabbed);
-+
-+    }
-+  else
-     {
--        if (fd != -1)
--            close(fd);
-+      fprintf (stderr, "/dev/input/event%d added mouse on fd %d (%s)\n",
-+               slot, fd, name);
-+      linux_hid_driver.types[slot] = HID_TYPE_MOUSE;
-+      set_handler (slot, linux_hid_driver.mouse_grabbed);
-+    }
--      sprintf(path, "%s%i", EVENT_PATH, i++);
--      if (i>=HID_LINUX_MAX_DEV_NO)
--              break;
-+  return 0;
-+}
--      if (stat(path, &st) == -1)
--              continue;
--      for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++)
--          if (!strcmp(hid_linux_driver.controller_paths[c], path))
--              break;
--      assert(c != HID_LINUX_MAX_DEV);
--      if (hid_linux_driver.controller_paths[c])
--          continue;
--      if ((fd = open(path, O_RDONLY)) == -1)
--          break;
--      if (ioctl(fd, EVIOCGNAME(128), name) == -1)
--      {
--          DEBUG("Input get name failed on %s\n", path);
--            break;
--      }
-+static void
-+hid_linux_scan (void *opaque)
-+{
-+  char name[128];
-+  int i;
-+  struct stat s;
--        if (ioctl(fd, EVIOCGID, &id) == -1)
--      {
--          DEBUG("Input get id failed on %s\n", path);
--            continue;
--      }
-+//  fprintf (stderr, "hid_linux_scan()\n");
--        /* Only get devices on usb and i8042 */
--        if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
--            continue;
--        if (strcasestr(name, "keyboard"))
--        {
--            DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype);
--            controllers = hid_linux_driver.keyboard_fds;
--        }
--        else
-+  for (i = 0; i < N_DEVS; ++i)
-+    {
-+
-+/* Do We already have this device open and working */
-+      if (linux_hid_driver.fds[i] >= 0)
-+        continue;
-+
-+      sprintf (name, "/dev/input/event%d", i);
-+
-+/* Check to see if we can open it */
-+      linux_hid_driver.fds[i] = open (name, O_RDONLY);
-+      if (linux_hid_driver.fds[i] < 0)
-+        continue;               /* No */
-+
-+/* Switch to NBIO*/
-+      {
-+        long arg = 0;
-+        arg = fcntl (linux_hid_driver.fds[i], F_GETFL, arg);
-+        arg |= O_NONBLOCK;
-+        fcntl (linux_hid_driver.fds[i], F_SETFL, arg);
-+      }
-+
-+/* See if we like it and set up input notify if we do*/
-+      if (consider_device (i))
-         {
--            DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype);
--            controllers = hid_linux_driver.mouse_fds;
-+          close (linux_hid_driver.fds[i]);
-+          linux_hid_driver.fds[i] = -1;
-+          continue;
-         }
--      for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++)
--          ;
--      assert(j != (HID_LINUX_MAX_DEV / 2));
-+    }
--      controllers[j] = fd;
--      controllers[j + 1] = -1;
-+/* Check the activity file */
-+  if (!linux_hid_driver.mouse_grabbed)
-+  {
-+    if (stat(HID_LINUX_ACTIVITY_FILE, &s) == -1)
-+    {
-+        fprintf (stderr, "cannot stat %s\n", HID_LINUX_ACTIVITY_FILE);
-+        return;
-+    }
-+    if (linux_hid_driver.last_activity &&
-+        s.st_mtime > linux_hid_driver.last_activity)
-+    {
-+        /* simulated a key press (down and up) on LEFTCTRL */
-+        linux_hid_key_event(1, KEY_LEFTCTRL);
-+        linux_hid_key_event(0, KEY_LEFTCTRL);
-+    }
-+    linux_hid_driver.last_activity = s.st_mtime;
-+  }
--      if (grab)
--      {
--          if (!hid_linux_grab_devices(1, controllers + j))
--          {
--              DEBUG("Grabing failed, try next time...\n");
--              controllers[j] = -1;
--              break;
--          }
--      }
-+/* Kick off the periodic scan for devices */
-+  if (!linux_hid_driver.scan_timer)
-+    linux_hid_driver.scan_timer =
-+      qemu_new_timer (rt_clock, hid_linux_scan, NULL);
--      hid_linux_driver.controller_paths[c] = strdup(path);
--      hid_linux_driver.controller_paths[c + 1] = NULL;
-+/* Schedule ourselves */
-+  qemu_mod_timer (linux_hid_driver.scan_timer,
-+                  qemu_get_clock (rt_clock) + 4000);
--      fd = -1;
--    }
--    if (fd != -1)
--      close(fd);
- }
--void hid_linux_init(void)
-+
-+void
-+hid_linux_probe (int grab)
- {
--    hid_linux_driver.keyboard_fds[0] = -1;
--    hid_linux_driver.mouse_fds[0] = -1;
--    hid_linux_driver.controller_paths[0] = NULL;
-+  hid_linux_scan (NULL);
-+}
--    while (hid_linux_driver.keyboard_fds[0] == -1)
--    {
--      hid_linux_probe(0);
--      usleep(100000); /* 10 ms */
--    }
-+
-+void
-+hid_linux_init (void)
-+{
-+  int i;
-+  for (i = 0; i < N_DEVS; ++i)
-+    linux_hid_driver.fds[i] = -1;
-+  linux_hid_driver.keyboard_grabbed = 0;
-+  linux_hid_driver.mouse_grabbed = 0;
-+  linux_hid_driver.last_activity = 0;
-+  hid_linux_scan (NULL);
- }
index 73ebb45621081f2cbbc3d6976ef1a72f2eeb59f6..01318086c668407d76cf9d87ac2b7df7879d267c 100644 (file)
@@ -18,11 +18,9 @@ thermal-management
 
 
 vga-passthrough
-dom0-driver
+switcher
 intel
 
-fix-drop-mouse-keyboard
 fix-imobile-mouse
-new-input-code
 atapi-pass-through
 pv_driver_throttling_disabled
diff --git a/master/switcher b/master/switcher
new file mode 100644 (file)
index 0000000..cdadd98
--- /dev/null
@@ -0,0 +1,921 @@
+diff --git a/intel.c b/intel.c
+new file mode 100644
+index 0000000..62701cc
+--- /dev/null
++++ b/intel.c
+@@ -0,0 +1,515 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <assert.h>
++#include <signal.h>
++#include <pci/pci.h>
++
++#include "qemu-common.h"
++#include "qemu-timer.h"
++#include "console.h"
++#include "sysemu.h"
++
++#include "intel_reg.h"
++#include "intel.h"
++
++#define INTEL_DEBUG(format, args...)                                    \
++    fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args);
++
++extern int                      vga_passthrough;
++uint32_t                        guest_framebuffer;
++int                             intel_output = INTEL_OUTPUT_BLITTED;
++static int                      display = 0;
++
++static int                      mmio_fd = -1;
++static int                      mem_fd = -1;
++static uint8_t                  *intel_mem = NULL;
++static uint8_t                  *intel_mmio = NULL;
++static int                      intel_force_full_update = 0;
++static int                      intel_have_focus;
++static int                      IntelPitch = 16;
++static int                      IntelX = 1280;
++static int                      IntelY = 1024;
++static DisplayState             *lds = NULL;
++static uint32_t                 intel_fb_base, intel_mmio_base;
++static uint32_t                 map_s, map_d, map_size;
++static int                      refresh;
++static QEMUTimer                *check_linear_timer = NULL;
++
++static void set_data_pointer(DisplaySurface *surf);
++static void intel_resize(DisplayState *ds);
++
++static inline unsigned int intel_get_reg(unsigned int reg)
++{
++    return *(unsigned int*)(intel_mmio + reg);
++}
++
++static char surfaenabled(void)
++{
++    return !!(intel_get_reg(REG_DR_DSPACNTR) & (1 << 31));
++}
++
++static inline unsigned int intel_get_surface(void)
++{
++    if (surfaenabled())
++        return intel_get_reg(REG_DR_DSPASURF);
++    else
++        return intel_get_reg(REG_DR_DSPBSURF);
++}
++
++static inline void intel_get_res(unsigned int   *x,
++                                 unsigned int   *y,
++                                 unsigned int   *pitch)
++{
++    if (surfaenabled())
++    {
++        INTEL_DEBUG("Get resolution from PIPEA\n")
++        *pitch = intel_get_reg(REG_DR_DSPASTRIDE);
++        *x = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1;
++        *y = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1;
++    }
++    else
++    {
++        INTEL_DEBUG("Get resolution from PIPEB\n")
++        *pitch = intel_get_reg(REG_DR_DSPBSTRIDE);
++        *x = ((intel_get_reg(REG_DE_PIPEBSRC) >> 16) & 0xfff) + 1;
++        *y = (intel_get_reg(REG_DE_PIPEBSRC) & 0xfff) + 1;
++    }
++}
++
++
++
++static void intel_force_linear(int linesize)
++{
++    unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
++    unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF);
++    unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF);
++    unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
++
++    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
++    unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF);
++    unsigned int *dspbsurf = (unsigned int *)(intel_mmio + REG_DR_DSPBSURF);
++    unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE);
++    volatile unsigned int *fbc_ctl = (unsigned int *)(intel_mmio + REG_FBC_CONTROL);
++
++    unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0;
++    char pipeaenabled = !!(*pipeaconf & (1 << 30));
++    char pipebenabled = !!(*pipebconf & (1 << 30));
++
++    INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
++
++    if (pipeaenabled)
++    {
++        INTEL_DEBUG("PIPEACONF enabled.\n");
++        /* Disable surface */
++        pipea = *pipeaconf & (0x3 << 18);
++        *pipeaconf &= ~(0x3 << 18);
++        *dspacntr |= (1 << 31);
++        /* Address of the surface to map to */
++        surfa = *dspasurf;
++        *dspasurf = 0x00000000;
++        *dspacntr &= ~(1 << 31);
++        *dspasurf = 0x00000000;
++        *pipeaconf |= pipea;
++    }
++
++    if (pipebenabled) {
++        INTEL_DEBUG("PIPEBCONF enabled.\n");
++
++        /* Disable surface */
++        pipeb = *pipebconf & (0x3 << 18);
++        *pipebconf &= ~(0x3 << 18);
++        *dspbcntr |= (1 << 31);
++        /* Address of the surface to map to */
++        surfb = *dspbsurf;
++        *dspbsurf = 0x00000000;
++        *dspbcntr &= ~(1 << 31);
++        *dspbsurf = 0x00000000;
++        *pipebconf |= pipeb;
++    }
++
++    usleep(50 * 1000); /* 50 ms */
++
++    if (pipeaenabled)
++    {
++        *pipeaconf &= ~(0x3 << 18);
++        /* Enable surface linear mode */
++        *dspacntr &= ~(1 << 10);
++        if (linesize) *dspastride = linesize;
++        *dspasurf = surfa;
++        *dspacntr |= (1 << 31);
++        *pipeaconf |= pipea;
++    }
++
++    if (pipebenabled) {
++        *pipebconf &= ~(0x3 << 18);
++        /* Enable surface linear mode */
++        *dspbcntr &= ~(1 << 10);
++        if (linesize) *dspbstride = linesize;
++        *dspbsurf = surfb;
++        *dspbcntr |= (1 << 31);
++        *pipebconf |= pipeb;
++    }
++    if (linesize) IntelPitch = linesize;
++
++    usleep(50 * 1000); /* 50 ms */
++
++    /* Clear the compression bit */
++    *fbc_ctl &= ~(1 << 31);
++    /* Wait for the status register */
++    while (intel_get_reg(REG_FBC_STATUS) & (1 << 31))
++        ;
++}
++
++static void set_fb_mapping(void)
++{
++    DisplaySurface *surf = lds->surface;
++    int rc;
++    unsigned long nr_pfn;
++
++    intel_output = INTEL_OUTPUT_MAPPED;
++
++    unset_vga_acc();
++    INTEL_DEBUG("set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_surface()), guest_framebuffer);
++    nr_pfn = (ds_get_linesize(lds) * ds_get_height(lds)) >> TARGET_PAGE_BITS;
++
++    rc = xc_domain_memory_mapping(xc_handle,
++            domid,
++            (guest_framebuffer >> TARGET_PAGE_BITS),
++            ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS),
++            nr_pfn,
++            DPCI_ADD_MAPPING);
++    if (rc) {
++        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
++        return;
++    }
++    memcpy((uint8_t *)(intel_mem + intel_get_surface()),
++            ds_get_data(lds), ds_get_linesize(lds) * ds_get_height(lds));
++    map_s = ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS);
++    map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
++    map_size = nr_pfn;
++}
++
++static void unset_fb_mapping(void)
++{
++    int rc;
++
++    INTEL_DEBUG("unset_fb_mapping: %x %x\n", map_d, map_s);
++
++    rc = xc_domain_memory_mapping(xc_handle,
++            domid,
++            map_d,
++            map_s,
++            map_size,
++            DPCI_REMOVE_MAPPING);
++    if (rc) {
++        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
++        return;
++    }
++
++    set_vga_acc();
++    intel_output = INTEL_OUTPUT_BLITTED;
++    memcpy(ds_get_data(lds),
++            (uint8_t *) (intel_mem + intel_get_surface()),
++            ds_get_linesize(lds) * ds_get_height(lds));
++    map_s = 0;
++    map_d = 0;
++    map_size = 0;
++}
++
++
++static void intel_update(DisplayState *ds, int x, int y, int w, int h)
++{
++    /* do nothing */
++    int i, bpp = ds_get_bytes_per_pixel(ds);
++    unsigned char *s, *d;
++
++    if (!intel_have_focus || !is_buffer_shared(ds->surface))
++        return;
++
++    if ((x > IntelX || y > IntelY))
++        return;
++    if ((x + w) > IntelX)
++        w = IntelX - x;
++    if ((y + h) > IntelY)
++        h = IntelY - y;
++
++    s = ds_get_data(ds);
++    d = (unsigned char *)(intel_mem + intel_get_surface());
++    /* Center the screen */
++    if (ds_get_width(ds) < IntelX && ds_get_height(ds) < IntelY)
++        d += IntelPitch * ((IntelY - ds_get_height(ds)) / 2) +
++            4 * ((IntelX - ds_get_width(ds)) / 2);
++
++    s += (ds_get_linesize(ds) * y) + bpp * x;
++    d += (IntelPitch * y) + bpp * x;
++    for (i = 0; i < h; i++) {
++        memcpy(d, s, w * bpp);
++        s += ds_get_linesize(ds);
++        d += IntelPitch;
++    }
++}
++
++static void intel_resize(DisplayState *ds)
++{
++    INTEL_DEBUG("intel_resize: shared=%d, width=%d, height=%d, depth=%d\n",
++            is_buffer_shared(ds->surface),
++            ds_get_width(ds),
++            ds_get_height(ds),
++            ds_get_bytes_per_pixel(ds));
++    if (intel_have_focus)
++    {
++        if (ds_get_width(ds) == IntelX && ds_get_height(ds) == IntelY &&
++                is_buffer_shared(ds->surface))
++        {
++            if (!map_size)
++            {
++                intel_force_linear(ds_get_linesize(ds));
++                set_fb_mapping();
++            }
++        }
++        else
++        {
++            if (map_size)
++                unset_fb_mapping();
++            else
++                intel_force_linear(0);
++        }
++    } else {
++        if (map_size)
++            unset_fb_mapping();
++    }
++}
++
++static void intel_setdata(DisplayState *ds)
++{
++    if (!map_size)
++        return;
++    unset_fb_mapping();
++    set_fb_mapping();
++}
++
++static void intel_refresh(DisplayState *ds)
++{
++    vga_hw_update();
++}
++
++static void intel_init_mapping(void)
++{
++    struct pci_access   *pci_bus;
++    struct pci_dev      *pci_dev;
++
++    mmio_fd = open("/dev/mem", O_RDWR);
++    if (mmio_fd == -1)
++    {
++        perror("open");
++        exit(1);
++    }
++    mem_fd = open("/dev/mem", O_RDWR);
++    if (mem_fd == -1)
++    {
++        perror("open");
++        exit(1);
++    }
++
++    pci_bus = pci_alloc();
++    pci_init(pci_bus);
++    pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0);
++    pci_fill_info(pci_dev, PCI_FILL_BASES);
++    intel_fb_base = pci_dev->base_addr[2] & 0xfffff000;
++    intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000;
++    pci_free_dev(pci_dev);
++    pci_cleanup(pci_bus);
++
++    INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base);
++    intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED,
++                     mem_fd, intel_fb_base);
++    if (intel_mem == MAP_FAILED)
++    {
++        perror("mmap");
++        exit(1);
++    }
++
++    INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base);
++    intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED,
++                      mmio_fd, intel_mmio_base);
++    if (intel_mmio == MAP_FAILED)
++    {
++        perror("mmap");
++        exit(1);
++    }
++}
++
++static void set_data_pointer(DisplaySurface *surf)
++{
++    surf->data = (unsigned char *)(intel_mem + intel_get_surface());
++    memset(surf->data, 0x00, surf->linesize * IntelY);
++    surf->data = surf->data +
++                surf->linesize * ((IntelY - surf->height) / 2) +
++                4 * ((IntelX - surf->width) / 2);
++}
++
++static int intel_getfocus(void)
++{
++    return intel_have_focus;
++}
++
++static inline int is_linear(void)
++{
++    if (surfaenabled())
++        return (intel_get_reg(REG_DR_DSPACNTR) & (1 << 10)) == 0;
++    else
++        return (intel_get_reg(REG_DR_DSPBCNTR) & (1 << 10)) == 0;
++}
++
++static void intel_check_linear(void)
++{
++    if (!check_linear_timer)
++        check_linear_timer = qemu_new_timer(rt_clock, intel_check_linear, NULL);
++
++    if (intel_have_focus && !is_linear())
++    {
++        intel_force_linear(0);
++        vga_hw_invalidate();
++        vga_hw_update();
++    }
++
++    if (intel_have_focus)
++        qemu_mod_timer(check_linear_timer,
++                qemu_get_clock(rt_clock) + 4000);
++}
++
++static void intel_focus(int focus)
++{
++    if (intel_have_focus == focus)
++        return;
++
++    intel_have_focus = focus;
++    if (intel_have_focus) {
++        intel_get_res(&IntelX, &IntelY, &IntelPitch);
++
++        if (!guest_framebuffer)
++            intel_force_linear(0);
++        memset((uint8_t *)(intel_mem + intel_get_surface()), 0,
++                IntelX * IntelY * 4);
++    }
++    vga_hw_invalidate();
++    vga_hw_update();
++    intel_check_linear();
++
++    INTEL_DEBUG("intel_focus %d, x=%d, y=%d, stride=%d\n",
++            focus, IntelX, IntelY, IntelPitch);
++}
++
++int intel_enter(void)
++{
++    intel_focus(1);
++    return 1;
++}
++
++int intel_leave(void)
++{
++    intel_focus(0);
++    return 1;
++}
++
++void intel_enter_leave(const char *path, void *opaque)
++{
++    int state;
++    int enter = (int)opaque;
++
++    state = xenstore_dom_read(domid, path, NULL);
++    if (state == 1)
++    {
++        intel_focus(enter);
++        xenstore_dom_write(domid, path, "2");
++    }
++}
++
++static DisplaySurface* intel_create_displaysurface(int width, int height)
++{
++    DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
++    if (surface == NULL) {
++        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
++        exit(1);
++    }
++
++    surface->width = width;
++    surface->height = height;
++
++    INTEL_DEBUG("intel_create_displaysurface: focus=%d %d %d\n", intel_have_focus, width, height);
++    if (intel_have_focus) {
++        surface->pf = qemu_default_pixelformat(32);
++        surface->flags = QEMU_ALLOCATED_FLAG | INTEL_MAPPED_FLAG;
++        surface->linesize = IntelPitch;
++        set_data_pointer(surface);
++    } else {
++        surface->data = qemu_mallocz(width * height * 4);
++        surface->linesize = width * 4;
++        surface->pf = qemu_default_pixelformat(32);
++        surface->flags = QEMU_ALLOCATED_FLAG;
++    }
++
++    return surface;
++}
++
++static void intel_free_displaysurface(DisplaySurface *surface)
++{
++    if (surface == NULL)
++        return;
++    if ((!(surface->flags & INTEL_MAPPED_FLAG)) && (surface->flags & QEMU_ALLOCATED_FLAG))
++        qemu_free(surface->data);
++    qemu_free(surface);
++}
++
++static DisplaySurface* intel_resize_displaysurface(DisplaySurface *surface, int width, int height)
++{
++    intel_free_displaysurface(surface);
++    if (map_size)
++        unset_fb_mapping();
++    return intel_create_displaysurface(width, height);
++}
++
++void intel_display_init(DisplayState *ds)
++{
++    DisplayChangeListener *dcl;
++    DisplayAllocator *da;
++
++    intel_init_mapping();
++
++    INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_surface());
++
++    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
++    if (!dcl)
++        exit(1);
++    dcl->dpy_update = intel_update;
++    dcl->dpy_resize = intel_resize;
++    dcl->dpy_setdata = intel_setdata;
++    dcl->dpy_refresh = intel_refresh;
++    register_displaychangelistener(ds, dcl);
++
++    da = qemu_mallocz(sizeof(DisplayAllocator));
++    if (!da)
++        exit(1);
++    da->create_displaysurface = intel_create_displaysurface;
++    da->resize_displaysurface = intel_resize_displaysurface;
++    da->free_displaysurface = intel_free_displaysurface;
++    if (register_displayallocator(ds, da) != da) {
++        fprintf(stderr, "intel_display_init: could not register DisplayAllocator\n");
++        exit(1);
++    } else {
++        DisplaySurface *surf;
++        surf = intel_create_displaysurface(ds_get_width(ds), ds_get_height(ds));
++        defaultallocator_free_displaysurface(ds->surface);
++        ds->surface = surf;
++        dpy_resize(ds);
++    }
++
++    xenstore_dom_watch(domid, "switcher/enter", intel_enter_leave, (void*)0);
++    xenstore_dom_watch(domid, "switcher/leave", intel_enter_leave, (void*)1);
++    lds = ds;
++}
+diff --git a/intel.h b/intel.h
+new file mode 100644
+index 0000000..25086be
+--- /dev/null
++++ b/intel.h
+@@ -0,0 +1,5 @@
++extern int intel_output;
++#define INTEL_OUTPUT_UNDEF    0
++#define INTEL_OUTPUT_MAPPED   1
++#define INTEL_OUTPUT_BLITTED  2
++
+diff --git a/intel_reg.h b/intel_reg.h
+new file mode 100644
+index 0000000..cd7855e
+--- /dev/null
++++ b/intel_reg.h
+@@ -0,0 +1,22 @@
++
++#define TileW           128
++#define TileH           8
++
++#define REG_DR_DSPASURF         0x7019C
++#define REG_DR_DSPACNTR         0x70180
++#define REG_DR_DSPASTRIDE       0x70188
++#define REG_DR_PIPEACONF        0x70008
++
++#define REG_DR_DSPBSURF         0x7119C
++#define REG_DR_DSPBCNTR         0x71180
++#define REG_DR_DSPBSTRIDE       0x71188
++#define REG_DR_PIPEBCONF      0x71008
++
++#define REG_DE_PIPEASRC               0x6001c
++#define REG_DE_PIPEBSRC               0x6101c
++
++#define REG_FBC_CONTROL         0x03208
++#define REG_FBC_STATUS          0x03210
++
++
++
+diff --git a/qemu-xen.h b/qemu-xen.h
+index 7883718..0b6214c 100644
+--- a/qemu-xen.h
++++ b/qemu-xen.h
+@@ -148,4 +148,6 @@ int has_tpm_device_danger(void);
+ static void vga_dirty_log_start(void *s) { }
+ static void vga_dirty_log_stop(void *s) { }
++void switcher_init(const char *);
++
+ #endif /*QEMU_XEN_H*/
+diff --git a/switcher.c b/switcher.c
+new file mode 100644
+index 0000000..f352d08
+--- /dev/null
++++ b/switcher.c
+@@ -0,0 +1,263 @@
++/*
++ * QEMU dom0_driver
++ *
++ * Copyright (c) 2009 Citrix Systems
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++ * THE SOFTWARE.
++ */
++
++#include "qemu-common.h"
++#include "console.h"
++#include "qemu-timer.h"
++#include "qemu-xen.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <linux/input.h>
++#include <unistd.h>
++#include <time.h>
++
++extern int vga_passthrough;
++
++#define DOM0_INPUT_NONE           'N'
++#define DOM0_INPUT_DONE           'D'
++#define DOM0_INPUT_DOMID          'I'
++#define DOM0_INPUT_OPT            'O'
++
++#define DOM0_INPUT_SOCKET       "/tmp/input.socket"
++
++static int                      s;
++static struct sockaddr_un       remote;
++static int                      slot;
++
++static int switcher_init_socket(void);
++
++static void switcher_key_inject (int code, uint32_t keycode)
++{
++    int first = 0;
++
++    switch (keycode)
++    {
++        case KEY_F11:
++            keycode = 0X57;
++            break;                    /* F11 */
++        case KEY_F12:
++            keycode = 0X58;
++            break;                    /* F12 */
++        case KEY_INSERT:
++            keycode = 0X52;
++            break;
++        case KEY_HOME:
++            keycode = 0X47;
++            break;
++        case KEY_PAGEUP:
++            keycode = 0X49;
++            break;
++        case KEY_DELETE:
++            keycode = 0X53;
++            break;
++        case KEY_END:
++            keycode = 0X4F;
++            break;
++        case KEY_PAGEDOWN:
++            keycode = 0x51;
++            break;
++        case KEY_UP:
++            keycode = 0X48;
++            break;
++        case KEY_LEFT:
++            keycode = 0X4B;
++            break;
++        case KEY_DOWN:
++            keycode = 0X50;
++            break;
++        case KEY_RIGHT:
++            keycode = 0X4D;
++            break;
++        case KEY_RIGHTALT:
++            keycode = 0x38;
++            first = 0xe0;
++            break;
++        case KEY_LEFTMETA:
++            keycode = 0x5B;
++            first = 0xe0;
++            break;
++        case KEY_RIGHTMETA:
++            keycode = 0x5C;
++            first = 0xe0;
++            break;
++    }
++
++    if (first)
++        kbd_put_keycode (first);
++
++    if (code == 0)
++        kbd_put_keycode (keycode | 0x80);
++    else
++        kbd_put_keycode (keycode & 0x7f);
++}
++
++
++static void switcher_event(struct input_event *e)
++{
++    static int  mouse_button_state = 0;
++
++    if (e->type == EV_KEY)
++    {
++        if (e->code >= BTN_MOUSE)
++        {
++            int         type = 0;
++
++            switch (e->code)
++            {
++                case BTN_LEFT:
++                    type = MOUSE_EVENT_LBUTTON;
++                    break;
++                case BTN_RIGHT:
++                    type = MOUSE_EVENT_RBUTTON;
++                    break;
++                case BTN_MIDDLE:
++                    type = MOUSE_EVENT_MBUTTON;
++                    break;
++            }
++
++            if (e->value)
++                mouse_button_state |= type;
++            else
++                mouse_button_state &= ~type;
++            kbd_mouse_event (0, 0, 0, mouse_button_state);
++        }
++        else
++            switcher_key_inject(e->value, e->code);
++    }
++
++    if (e->type == EV_REL || e->type == EV_ABS)
++    {
++        /* Mouse motion */
++        int x = 0, y = 0, z = 0;
++        if (e->type == EV_REL)
++            switch (e->code)
++            {
++                case REL_X:
++                    x = e->value;
++                    break;
++                case REL_Y:
++                    y = e->value;
++                    break;
++                case REL_WHEEL:
++                    z = -e->value;
++                    break;
++            }
++        kbd_mouse_event (x, y, z, mouse_button_state);
++    }
++}
++
++static void switcher_send(const char *format, ...)
++{
++    char        buff[128];
++    va_list     arg;
++
++    va_start(arg, format);
++    vsnprintf(buff, 128, format, arg);
++    va_end(arg);
++
++    fprintf(stderr, "send: %s\n", buff);
++    send(s, buff, strlen(buff), 0);
++}
++
++static void switcher_recv(void *opaque)
++{
++    static int          left_over = 0;
++    static int          read_sz = 0;
++    static char         buff[128];
++    static char         *p = buff;
++    struct input_event  *e = NULL;
++    int                 ret;
++
++    memmove(buff, p, left_over);
++    if ((read_sz = recv(s, buff + left_over, 128, 0)) <= 0)
++    {
++        do
++        {
++            fprintf(stderr, "Trying to reconnect ...\n");
++            if (switcher_init_socket())
++                return;
++            ret = errno;
++            sleep(1);
++        }
++        while (ret == EAGAIN);
++    }
++    read_sz += left_over;
++    left_over = 0;
++    p = buff;
++
++    while (left_over == 0 && p - buff < read_sz)
++    {
++        if ((p - buff) + (int)sizeof (struct input_event) > read_sz)
++        {
++            left_over = read_sz - (p - buff);
++            break;
++        }
++        e = (struct input_event *)p;
++        p += sizeof (struct input_event);
++        switcher_event(e);
++    }
++}
++
++static int switcher_init_socket(void)
++{
++    struct stat st;
++
++    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
++    {
++        fprintf(stderr, "switcher: socket %s\n", strerror(errno));
++        errno = EAGAIN;
++        return 0;
++    }
++
++    memset(&remote, 0, sizeof (remote));
++    remote.sun_family = AF_UNIX;
++    strcpy(remote.sun_path, DOM0_INPUT_SOCKET);
++    if (connect(s, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1)
++    {
++        fprintf(stderr, "switcher: connect %s, %s\n", strerror(errno), remote.sun_path);
++        errno = EAGAIN;
++        return 0;
++    }
++
++    switcher_send("%c%d", DOM0_INPUT_DOMID, domid);
++    if (vga_passthrough)
++        switcher_send("%c%d", DOM0_INPUT_OPT, 1);
++
++    qemu_set_fd_handler(s, switcher_recv, NULL, NULL);
++    return 1;
++}
++
++void switcher_init(const char *str_slot)
++{
++    slot = strtol(str_slot, NULL, 10);
++    fprintf(stderr, "switcher_init: slot %d\n", slot);
++    xenstore_dom_write(domid, "switcher/slot", str_slot);
++    switcher_init_socket();
++}
+diff --git a/vl.c b/vl.c
+index a4b8bd8..6350384 100644
+--- a/vl.c
++++ b/vl.c
+@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
+ int win2k_install_hack = 0;
+ int rtc_td_hack = 0;
+ int vga_passthrough = 0;
++const char *dom0_input = NULL;
+ #endif
+ int usb_enabled = 0;
+ int smp_cpus = 1;
+@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16];
+ #include "xen-vl-extra.c"
++char *get_time(void)
++{
++
++  char buff[128];
++  char *str;
++  struct timeval tv;
++
++  gettimeofday(&tv, NULL);
++  str = malloc(256);
++  strftime(buff, 128, "%T", localtime(&tv.tv_sec));
++  sprintf(str, "%s:%06d", buff, (int)tv.tv_usec);
++  return str;
++}
++
+ /***********************************************************/
+ /* x86 ISA bus support */
+@@ -4289,6 +4304,7 @@ enum {
+     QEMU_OPTION_acpi,
+     QEMU_OPTION_vcpus,
+     QEMU_OPTION_vga_passthrough,
++    QEMU_OPTION_dom0_input,
+     /* Debug/Expert options: */
+     QEMU_OPTION_serial,
+@@ -4463,6 +4479,7 @@ static const QEMUOption qemu_options[] = {
+     { "vncunused", 0, QEMU_OPTION_vncunused },
+     { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
+     { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough },
++    { "dom0-input", 1, QEMU_OPTION_dom0_input },
+ #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
+     { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
+     { "xen-create", 0, QEMU_OPTION_xen_create },
+@@ -5298,6 +5315,9 @@ int main(int argc, char **argv, char **envp)
+                 cirrus_vga_enabled = 0;
+                 vmsvga_enabled = 0;
+                 break;
++            case QEMU_OPTION_dom0_input:
++                dom0_input = optarg;
++                break;
+             case QEMU_OPTION_direct_pci:
+                direct_pci = optarg;
+                 break;
+@@ -6066,6 +6086,9 @@ int main(int argc, char **argv, char **envp)
+         close(fd);
+     }
++    if (dom0_input)
++      switcher_init(dom0_input);
++
+     xenstore_dm_finished_startup();
+ #ifndef CONFIG_STUBDOM
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index 23f2bb7..1ed197f 100644
+--- a/xen-hooks.mak
++++ b/xen-hooks.mak
+@@ -37,6 +37,7 @@ OBJS += helper2.o
+ OBJS += battery_mgmt.o
+ OBJS += xen_acpi_wmi.o
+ OBJS += thermal_mgmt.o
++OBJS += switcher.o
+ CONFIG_AUDIO=1