+++ /dev/null
-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;
-+}
-+
+++ /dev/null
-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))
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);
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
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;
#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;
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
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
+++ /dev/null
-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);
- }
vga-passthrough
-dom0-driver
+switcher
intel
-fix-drop-mouse-keyboard
fix-imobile-mouse
-new-input-code
atapi-pass-through
pv_driver_throttling_disabled
--- /dev/null
+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
+