#endif
diff --git a/dom0_driver.c b/dom0_driver.c
new file mode 100644
-index 0000000..bdfe37c
+index 0000000..fdd24ab
--- /dev/null
+++ b/dom0_driver.c
-@@ -0,0 +1,718 @@
+@@ -0,0 +1,697 @@
+/*
+ * QEMU dom0_driver
+ *
+ }
+}
+
-+static void dom0_driver_detect_alt_tab(void *opaque)
-+{
-+ struct dom0_driver_xs_info mouse_info;
-+
-+ dom0_driver_read_xs_info(&mouse_info, DOM0_MOUSE);
-+
-+ printf("Got alt-tab !!!! domid: %d, mouse.domid: %d\n", domid, mouse_info.domid);
-+ if (domid != mouse_info.domid)
-+ return;
-+ kbd_put_keycode(KEY_LEFTALT);
-+ kbd_put_keycode(KEY_TAB);
-+}
-+
+static void dom0_driver_detect_secure_auth(void* opaque)
+{
+ struct stat s;
+ binds[2] = KEY_BACKSPACE;
+ binds[3] = -1;
+ dom0_driver_handler->add_binding(binds, dom0_driver_detect_secure_auth, NULL);
-+
-+#if 0
-+ binds[0] = KEY_LEFTALT;
-+ binds[1] = KEY_TAB;
-+ binds[2] = -1;
-+ binds[3] = -1;
-+ dom0_driver_handler->add_binding(binds, dom0_driver_detect_alt_tab, NULL);
-+#endif
+}
+
+static int dom0_driver_dummy_enter_leave(void)
+}
diff --git a/hid-linux.c b/hid-linux.c
new file mode 100644
-index 0000000..00790b5
+index 0000000..59dfec8
--- /dev/null
+++ b/hid-linux.c
-@@ -0,0 +1,501 @@
+@@ -0,0 +1,527 @@
+/*
+ * QEMU hid-linux /dev/input driver
+ *
+#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 32
++#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);
++# 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 evdev_fds[HID_LINUX_MAX_DEV];
++ 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);
-+ int has_keyboard;
-+ int has_mouse;
+} hid_linux_driver;
+
+struct hid_linux_binding
+ return ret;
+}
+
-+static void hid_linux_xs_read_int(const char *key, int *value)
-+{
-+ char *path = NULL;
-+ char *ret;
-+
-+ if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1)
-+ return NULL;
-+ ret = xenstore_read(path);
-+ free(path);
-+
-+ if (!ret)
-+ return;
-+
-+ *value = strtol(ret, NULL, 10);
-+ free(ret);
-+}
-+
+void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload)
+{
+ int i = 0, j = 0;
+ 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;
-+
-+ if (hid_linux_driver.has_keyboard || // We have the keyboard
-+ (hid_linux_driver.has_mouse && // We have the mouse and track Alt...
-+ (hid_linux_driver.key_status[KEY_LEFTALT] || keycode == KEY_LEFTALT)))
-+ hid_linux_key_inject(code, keycode);
++ hid_linux_key_inject(code, keycode);
+}
+
-+static void hid_linux_keyboard_read(void *opaque)
++static void hid_linux_read(void *opaque)
+{
-+ if (hid_linux_driver.secure_key && hid_linux_driver.has_keyboard)
-+ {
-+ hid_linux_driver.secure_key(opaque);
-+ return;
-+ }
-+
+ 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++)
+ {
-+ if (event[i].type == EV_KEY &&
-+ event[i].code < BTN_MOUSE)
-+ {
++ 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);
++ }
+ }
-+ }
-+}
-+
-+static void hid_linux_mouse_click(struct input_event *event)
-+{
-+ int type = 0;
-+
-+ switch(event->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->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);
-+}
-+
-+static void hid_linux_mouse_motion(struct input_event *event)
-+{
-+ int x = 0, y = 0, z = 0;
-+
-+ if (event->type == EV_REL)
-+ switch (event->code)
-+ {
-+ case REL_X : x = event->value; break;
-+ case REL_Y : y = event->value; break;
-+ case REL_WHEEL : z = -event->value; break;
-+ }
-+ else if (event->type == EV_ABS)
-+ {
-+ static int last_x = 1, last_y = 1;
-+ int px = 0, py = 0, l = 50;
-+ double div = 1;
-+ char *str = NULL;
-+
-+ hid_linux_xs_read_int("touchpad-limit", &l);
-+ hid_linux_xs_read_int("touchpad-div", &div);
-+ div /= 1000.;
+
-+ switch (event->code)
-+ {
-+ case ABS_X : x = event->value; break;
-+ case ABS_Y : y = event->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);
-+}
-+
-+static void hid_linux_mouse_read(void *opaque)
-+{
-+ struct input_event event[5];
-+ int i = 0;
-+ int read_sz = 0;
-+ int fd = *(int *)opaque;
++ 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;
++ }
+
-+ 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 && hid_linux_driver.has_mouse)
-+ hid_linux_mouse_click(event + i);
-+ else if ((event[i].type == EV_REL || event[i].type == EV_ABS) &&
-+ hid_linux_driver.has_mouse)
-+ hid_linux_mouse_motion(event + i);
++ kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state);
++ }
+ }
+}
+
+ }
+}
+
++
++
+static void hid_linux_redirect_fds(int *fd, IOHandler *cb)
+{
+ assert(fd != NULL);
+ 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);
+}
+
-+int hid_linux_grab_keyboard(int grab)
++static int hid_linux_grab_devices(int grab, int *fd)
+{
-+ hid_linux_driver.has_keyboard = grab;
++ 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)
+{
-+ hid_linux_driver.has_mouse = grab;
-+ return 1;
++ return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds);
+}
+
+static int hid_linux_open_timeout(const char *path, int flags)
+ return 1;
+}
+
-+void hid_linux_probe(int grab __attribute__((unused)))
++void hid_linux_probe(int grab)
+{
-+ for (int i = 0; i < HID_LINUX_MAX_DEV; i++)
++ 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)
+ {
-+ int fd;
-+ char path[sizeof (EVENT_PATH) + 3];
-+ char name[128];
-+ struct input_id id;
-+ struct stat st;
++ if (fd != -1)
++ close(fd);
+
-+ if (hid_linux_driver.evdev_fds[i] >= 0)
-+ continue;
++ sprintf(path, "%s%i", EVENT_PATH, i++);
+
-+ snprintf(path, sizeof (path), "%s%i", EVENT_PATH, i + 1);
+ 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)
-+ continue;
++ break;
+
-+ if (ioctl(fd, EVIOCGNAME(sizeof (name)), name) == -1)
++ if (ioctl(fd, EVIOCGNAME(128), name) == -1)
+ {
+ DEBUG("Input get name failed on %s\n", path);
-+ close(fd);
-+ continue;
++ break;
+ }
+
+ if (ioctl(fd, EVIOCGID, &id) == -1)
+ {
+ DEBUG("Input get id failed on %s\n", path);
-+ close(fd);
+ continue;
+ }
+
+ /* Only get devices on usb and i8042 */
+ if (id.bustype != BUS_I8042 && id.bustype != BUS_USB)
-+ {
-+ close(fd);
+ continue;
-+ }
-+
-+ hid_linux_driver.evdev_fds[i] = fd;
+
+ if (strcasestr(name, "keyboard"))
+ {
+ DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype);
-+ qemu_set_fd_handler(fd, hid_linux_keyboard_read, NULL,
-+ hid_linux_driver.evdev_fds + i);
++ controllers = hid_linux_driver.keyboard_fds;
+ }
+ else
+ {
+ DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype);
-+ qemu_set_fd_handler(fd, hid_linux_mouse_read, NULL,
-+ hid_linux_driver.evdev_fds + i);
++ 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)
+{
-+ for (int *fd = hid_linux_driver.evdev_fds;
-+ fd != hid_linux_driver.evdev_fds + HID_LINUX_MAX_DEV;
-+ fd++)
-+ *fd = -1;
++ hid_linux_driver.keyboard_fds[0] = -1;
++ hid_linux_driver.mouse_fds[0] = -1;
++ hid_linux_driver.controller_paths[0] = NULL;
+
-+#if 0
+ while (hid_linux_driver.keyboard_fds[0] == -1)
+ {
+ hid_linux_probe(0);
+ usleep(100000); /* 10 ms */
+ }
-+#endif /* 0 */
+}
diff --git a/qemu-xen.h b/qemu-xen.h
-index 7883718..afe8f22 100644
+index 0cc5dd8..2646ec7 100644
--- a/qemu-xen.h
+++ b/qemu-xen.h
-@@ -109,7 +109,13 @@ int xenstore_write(const char *path, const char *val);
+@@ -107,7 +107,13 @@ int xenstore_write(const char *path, const char *val);
void xenstore_dm_finished_startup(void);
* 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 1738aa5..45e03c1 100644
+index e519705..0ffe1ec 100644
--- a/vl.c
+++ b/vl.c
@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
/***********************************************************/
/* x86 ISA bus support */
-@@ -4289,6 +4304,7 @@ enum {
+@@ -4277,6 +4292,7 @@ enum {
QEMU_OPTION_acpi,
QEMU_OPTION_vcpus,
QEMU_OPTION_vga_passthrough,
/* Debug/Expert options: */
QEMU_OPTION_serial,
-@@ -4463,6 +4479,7 @@ static const QEMUOption qemu_options[] = {
+@@ -4451,6 +4467,7 @@ static const QEMUOption qemu_options[] = {
{ "vncunused", 0, QEMU_OPTION_vncunused },
{ "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
{ "vga-passthrough", 0, QEMU_OPTION_vga_passthrough },
#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)
+@@ -5287,6 +5304,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_vga_passthrough:
vga_passthrough = 1;
break;
case QEMU_OPTION_direct_pci:
direct_pci = optarg;
break;
-@@ -6065,6 +6085,9 @@ int main(int argc, char **argv, char **envp)
+@@ -6053,6 +6073,9 @@ int main(int argc, char **argv, char **envp)
close(fd);
}
+
xenstore_dm_finished_startup();
- #ifndef CONFIG_STUBDOM
+ main_loop();
diff --git a/xen-hooks.mak b/xen-hooks.mak
-index 3b60724..8dc3885 100644
+index d171928..15ba4d1 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -37,6 +37,8 @@ OBJS += helper2.o
CONFIG_AUDIO=1
diff --git a/xenstore.c b/xenstore.c
-index 3cd2ba6..17136a3 100644
+index 01afcf0..20ca8cf 100644
--- a/xenstore.c
+++ b/xenstore.c
-@@ -1741,3 +1741,63 @@ void xenstore_dm_finished_startup(void)
+@@ -1727,3 +1727,63 @@ void xenstore_dm_finished_startup(void)
free(buf);
free(path);
}