--- /dev/null
+diff --git a/hid-linux.c b/hid-linux.c
+index f2e0bce..8cb3e30 100644
+--- a/hid-linux.c
++++ b/hid-linux.c
+@@ -43,11 +43,8 @@
+ #include <time.h>
+ #include <sys/time.h>
+
+-#define HID_LINUX_XS_PATH "/local/domain/0/hid_linux"
++#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 +61,592 @@ 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];
++ 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 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);
++ linux_hid_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;
+ }
+
+- 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);
++ if (code == 1)
++ if (linux_hid_detect_binding ())
++ return;
++ linux_hid_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));
++ if (read_sz <= 0)
++ return -1;
+
+- read_sz = read(fd, event, sizeof (event));
+- for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
++ 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 = linux_hid_xs_read ("touchpad-limit");
++ if (str)
++ l = strtol (str, NULL, 10);
++ str = linux_hid_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])
++ {
++ linux_hid_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);
++
++ 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 void hid_linux_redirect_fds(int *fd, IOHandler *cb)
++static int hid_linux_do_read (void *opaque)
+ {
+- assert(fd != NULL);
++ int result;
++ int slot = (int) opaque;
+
+- while (*fd != -1)
++ 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]);
++
++ 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;
+
+- 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
+- {
+- DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype);
+- controllers = hid_linux_driver.mouse_fds;
+- }
++ for (i = 0; i < N_DEVS; ++i)
++ {
+
+- for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++)
+- ;
+- assert(j != (HID_LINUX_MAX_DEV / 2));
++/* Do We already have this device open and working */
++ if (linux_hid_driver.fds[i] >= 0)
++ continue;
+
+- controllers[j] = fd;
+- controllers[j + 1] = -1;
++ sprintf (name, "/dev/input/event%d", i);
+
+- if (grab)
+- {
+- if (!hid_linux_grab_devices(1, controllers + j))
+- {
+- DEBUG("Grabing failed, try next time...\n");
+- controllers[j] = -1;
+- break;
+- }
+- }
++/* 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 */
+
+- hid_linux_driver.controller_paths[c] = strdup(path);
+- hid_linux_driver.controller_paths[c + 1] = NULL;
++/* Switch to NBIO*/
++ {
++ long arg;
++ 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))
++ {
++ close (linux_hid_driver.fds[i]);
++ linux_hid_driver.fds[i] = -1;
++ continue;
++ }
+
+- fd = -1;
+ }
+- if (fd != -1)
+- close(fd);
++
++/* Schedule ourselves */
++ qemu_mod_timer (linux_hid_driver.scan_timer, qemu_get_clock (rt_clock) + 2000);
++
+ }
+
+-void hid_linux_init(void)
++
++
++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;
++ int i;
+
+- while (hid_linux_driver.keyboard_fds[0] == -1)
+- {
+- hid_linux_probe(0);
+- usleep(100000); /* 10 ms */
+- }
++ 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;
++
++/* 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);
++
++ linux_hid_scan ();
+ }