]> xenbits.xensource.com Git - xenclient/ioemu.git/commitdiff
Introduction the new dom0_driver code:
authorJean Guyader <jean.guyader@eu.citrix.com>
Tue, 10 Mar 2009 18:17:56 +0000 (18:17 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Tue, 10 Mar 2009 18:19:53 +0000 (18:19 +0000)
- Split hid linux part into a file.
- Cleanup into the dom0 driver code.

console.h
dom0_driver.c
hid-linux.c [new file with mode: 0644]
intel.c
qemu-xen.h
xen-hooks.mak
xenstore.c

index 1e396413e4d46dd8a6bc3b9c00dd5eba18370f5a..5fbcf78215bf6d19d3775b64525366f56c54503f 100644 (file)
--- a/console.h
+++ b/console.h
@@ -179,5 +179,16 @@ extern int intel_output;
 extern uint32_t guest_framebuffer;
 void unset_vga_acc(void);
 void set_vga_acc(void);
+int intel_enter(void);
+int intel_leave(void);
+
+/* hid_linux */
+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
index 91c763f5a089daf04bd45febd2812dde5c06c190..2f593b3ae3875464973d69c2659ba90902e6b051 100644 (file)
@@ -47,9 +47,9 @@ extern int kbd_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 EVENT_PATH              "/dev/input/event"
 #define XS_REFRESH_INTERVAL     5000
 
 #define DOM0_MOUSE              1
@@ -57,40 +57,60 @@ static void dom0_driver_command(const char *path, void *opaque);
 
 #if DEBUG_DOM0_DRIVER
 # define DEBUG(_format_, args...)    \
-    fprintf(stderr, "dom0_driver(%d):%d: " _format_, domid, __LINE__, ## args)
+    do { \
+       char *str = get_time(); \
+    fprintf(stderr, "[%s] dom0_driver(%d):%d: " _format_, str, domid, __LINE__, ## args);\
+    } while (false)
 #else
 # define DEBUG(_format_, args...) (void)0
 #endif
 
 #define NB_SLOTS        10
 
-#define ABS(x)          ((x) > 0 ? (x) : -(x))
-
 static void             dom0_read(void *opaque);
 static void             dom0_driver_reset_keyboard(void);
 static void             dom0_read_secure(void *opaque);
-
 struct dom0_driver
 {
-    int keyboard_fds[4];
-    int mouse_fds[4];
-    int mouse_button_state;
     QEMUTimer *xs_timer;
-    uint8_t scroll_lock_count;
-    int key_status[256];
     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 leaving_dir;
-  int new_slot;
-  int timestamp;
+    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)
 {
@@ -98,70 +118,46 @@ static int dom0_driver_xs_read_dom0(const char *key)
 
     if (!(str = xenstore_read_dom0_driver(key)))
     {
-        fprintf(stderr, "dom0_driver: the node %s don't exits\n", key);
-        exit(2);
+       fprintf(stderr, "dom0_driver: fatal the node %s don't exits\n", key);
+       exit(2);
     }
     return strtol(str, NULL, 10);
 }
 
-static void dom0_driver_redirect_fds(IOHandler *callback)
-{
-    int *fd = 0;
-
-    DEBUG("Redirect fds\n");
-
-    fd = driver.keyboard_fds;
-    while (*fd != -1)
-    {
-        qemu_set_fd_handler(*fd, callback, NULL, fd);
-        fd++;
-    }
-    fd = driver.mouse_fds;
-    while (*fd != -1)
-    {
-        qemu_set_fd_handler(*fd, callback, NULL, fd);
-        fd++;
-    }
-    if (callback == dom0_read)
-    {
-        DEBUG("End of the secure mode\n");
-        close(driver.secure_fd);
-    }
-}
-
 static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info,
-                                     int                        controller)
+                                    int                        controller)
 {
     char        *str = NULL;
     char        path[128];
     int         val[10];
-    const char  *key[] = {"state", "domid", "new-slot", "timestamp"};
+    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);
-        }
+       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)
@@ -169,156 +165,101 @@ 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);
+       sprintf(path, "mouse/%s", key);
     else if (controller == DOM0_KEYBOARD)
-        sprintf(path, "keyboard/%s", key);
+       sprintf(path, "keyboard/%s", key);
     else
     {
-        DEBUG("unknown controller type\n");
-        exit(2);
+       DEBUG("unknown controller type\n");
+       exit(2);
     }
 
     sprintf(str, "%d", val);
-    xenstore_write_dom0_driver(path, str);
     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)
+       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 int dom0_windows_key_switch(int code, int keycode)
+static void dom0_driver_key_switch(int new_slot)
 {
-    int                         new_slot = 0;
     struct dom0_driver_xs_info  info;
     char                        buff[128];
 
     dom0_driver_read_xs_info(&info, DOM0_MOUSE);
-    if (info.state == 0)
-        return 0;
+    assert(info.state == 1);
 
-    if (driver.key_status[KEY_LEFTCTRL] && keycode != KEY_LEFTCTRL)
-    {
-        switch (keycode)
-        {
-            case KEY_1:
-                DEBUG("1 pressed switch to new-slot 1\n");
-                new_slot = 1;
-                break;
-            case KEY_2:
-                DEBUG("2 pressed switch to new-slot 2\n");
-                new_slot = 2;
-                break;
-            case KEY_3:
-                DEBUG("3 pressed switch to new-slot 3\n");
-                new_slot = 3;
-                break;
-            case KEY_4:
-                DEBUG("4 pressed switch to new-slot 4\n");
-                new_slot = 4;
-                break;
-            default:
-                return 0;
-        }
-        sprintf(buff, "switch %d", new_slot);
-
-        DEBUG("Write \"%s\" into xenstore\n", buff);
-        xenstore_write_dom0_driver("command", buff);
-
-        return 1;
-    }
+    sprintf(buff, "switch %d", new_slot);
 
-    return 0;
+    DEBUG("Write \"%s\" into xenstore\n", buff);
+    xenstore_write_dom0_driver("command", buff);
 }
 
-static void dom0_key_inject(int code, uint32_t keycode)
+static void dom0_driver_key_switch_1(void)
 {
-    int first = 0;
-
-    driver.key_status[keycode] = code;
-
-    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);
+    dom0_driver_key_switch(1);
 }
 
-static void dom0_driver_detect_secure_auth(int keycode)
+static void dom0_driver_read_secure(int ascii)
 {
-    if ((driver.key_status[KEY_LEFTCTRL] || driver.key_status[KEY_RIGHTCTRL]) &&
-        (driver.key_status[KEY_LEFTALT] || driver.key_status[KEY_RIGHTALT]) &&
-        (driver.key_status[KEY_BACKSPACE]))
+    int write_sz;
+
+    if (ascii)
     {
-        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_redirect_fds(dom0_read_secure);
-            }
-            DEBUG("writing SAS ret %d\n", ret);
-
-        }
-        else
-            DEBUG("xenmgr file is not there\n");
+       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_key_event(int code, uint32_t keycode)
+static void dom0_driver_detect_secure_auth(void)
 {
-    int shift_keys = 0;
-    uint8_t esc = 0;
-    struct dom0_driver_xs_info keyboard;
+    struct stat s;
+    int sas_ascii = 1, ret = 0;;
 
-    if (code != 2)
+    DEBUG("Received SAS keystroke\n");
+    if ((driver.secure_fd = open("/var/lib/xenmgr/keys", O_WRONLY)) > 0)
     {
-        if (dom0_windows_key_switch(code, keycode))
-            return;
-        if (vga_passthrough)
-            dom0_driver_detect_secure_auth(keycode);
-    }
+       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);
 
-    dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
-    if (keyboard.state == 0)
-    {
-        dom0_driver_xs_write("state", 1, DOM0_KEYBOARD);
-        dom0_driver_xs_write("domid", domid, DOM0_KEYBOARD);
     }
-
-
-    dom0_key_inject(code, keycode);
-}
-
-static void dom0_driver_reset_keyboard(void)
-{
-    int i = 0;
-
-    for (i = 0; i < 256; i++)
-        if (driver.key_status[i])
-            dom0_key_inject(0, i);
+    else
+       DEBUG("xenmgr file is not there\n");
 }
 
 static void dom0_get_positions(int *positions)
@@ -330,224 +271,41 @@ static void dom0_get_positions(int *positions)
     int pos = 0;
 
     for (int i = 0; i < NB_SLOTS; i++)
-        positions[i] = 0;
+       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 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;
-
-    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 void dom0_read_secure(void *opaque)
-{
-    int fd = *(int *)opaque;
-    struct input_event  event[5];
-    int read_sz, write_sz = 1, i;
-    char ascii = 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].value)
-        {
-            switch (event[i].code)
-            {
-                case KEY_ESC: ascii = 27; break;
-                case KEY_BACKSPACE: ascii = 8; break;
-                case KEY_ENTER: ascii = 10; break;
-                case KEY_LEFT: ascii = 17; break;
-                case KEY_RIGHT: ascii = 18; break;
-                case KEY_DELETE: ascii = 127; break;
-                case KEY_HOME: ascii = 2; break;
-                case KEY_END: ascii = 3; break;
-                case KEY_INSERT: ascii = 19; break;
-                case KEY_SPACE: ascii = 20; break;
-                default:
-                   ascii = keycode2ascii(event[i].code);
-            }
-            if (ascii)
-            {
-                DEBUG("Send %d to xenmgr (keycode was %d)\n", ascii, event[i].code);
-                write_sz = write(driver.secure_fd, &ascii, 1);
-                if (event[i].code == KEY_ESC || write_sz != 1)
-                    break;
-            }
-        }
-    if (read_sz <= 0 || event[i].code == KEY_ESC || write_sz != 1)
-    {
-        dom0_driver_reset_keyboard();
-        dom0_driver_redirect_fds(dom0_read);
-        return;
-    }
-}
-
-static void dom0_read(void *opaque)
-{
-    struct input_event  event[5];
-    int                 i = 0;
-    int                 read_sz = 0;
-    int                 fd = *(int *)opaque;
+       if (domids[i])
+       {
+           if (!(tmp = xenstore_dom_read(domids[i], "dom0_input/pos", &len)))
+               continue;
+           pos = strtol(tmp, NULL, 10);
+           free(tmp);
 
-    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;
-                struct dom0_driver_xs_info mouse;
-
-                dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
-                if (mouse.state == 0)
-                {
-                    dom0_driver_xs_write("state", 1, DOM0_MOUSE);
-                    dom0_driver_xs_write("domid", domid, DOM0_MOUSE);
-                }
-
-
-                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)
-                    driver.mouse_button_state |= type;
-                else
-                    driver.mouse_button_state &= ~type;
-                kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
-            }
-            else
-                dom0_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 = xenstore_read_dom0_driver("touchpad-limit");
-                if (str)
-                    l = strtol(str, NULL, 10);
-                str = xenstore_read_dom0_driver("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, driver.mouse_button_state);
-        }
-    }
+           positions[pos] = domids[i];
+       }
+    free(domids);
 }
 
-int pt_i8042_grab(int aux, int grab);
-int kbd_host_grab(int aux, int grab);
 static void dom0_gr_devices(int grab, int controller)
 {
-    int         st = 0;
-    int *fd = 0;
-
     if (controller == DOM0_MOUSE)
-        fd = driver.mouse_fds;
-    if (controller == DOM0_KEYBOARD)
-        fd = driver.keyboard_fds;
-    assert(fd != NULL);
-
-    while (*fd != -1)
     {
-        if (ioctl(*fd, EVIOCGRAB, grab) == -1)
-        {
-            DEBUG("Try to %s on %d\n", 1 ? "grab" : "release", *fd);
-            return;
-        }
-        DEBUG("%s succed %d\n", grab ? "grab" : "release", *fd);
-
-        if (grab)
-            qemu_set_fd_handler(*fd, dom0_read, NULL, fd);
-        else
-            qemu_set_fd_handler(*fd, NULL, NULL, fd);
-        fd++;
+       DEBUG("%s mouse\n", grab ? "Grab" : "Release");
+       assert(dom0_driver_handler->grab_mouse(grab));
     }
-
-    if (controller == DOM0_MOUSE && !vga_passthrough)
+    if (controller == DOM0_KEYBOARD)
     {
-        struct dom0_driver_xs_info  info;
-
-        dom0_driver_read_xs_info(&info, DOM0_MOUSE);
-        if (!vga_passthrough &&
-            dom0_driver_xs_read_dom0("natif") != info.domid)
-            intel_focus(!grab);
+       DEBUG("%s keyboard\n", grab ? "Grab" : "Release");
+       assert(dom0_driver_handler->grab_keyboard(grab));
     }
 
-    dom0_driver_reset_keyboard();
-    dom0_driver_xs_write("state", grab ? 1 : 2, controller);
+    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)
@@ -557,10 +315,10 @@ static int dom0_dom_alive(int id)
 
     domids = xenstore_get_domids(&len);
     if (domids == NULL)
-        return 0;
+       return 0;
     for (i = 0; i < len; i++)
-        if (domids[i] == id)
-            break;
+       if (domids[i] == id)
+           break;
     free(domids);
     return (i < len);
 }
@@ -568,31 +326,38 @@ static int dom0_dom_alive(int id)
 
 static int dom0_driver_failover_switch(void *opaque)
 {
-    struct dom0_driver_xs_info  mouse, keyboard;
     int                         ret = 1;
+    uint32_t                   t = time(NULL);
+    struct dom0_driver_xs_info mouse, keyboard;
 
     if (!vga_passthrough)
-        return 0;
+       return 0;
 
     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 (mouse.state == -1)
     {
-        DEBUG("No state grab the device\n");
-        dom0_gr_devices(1, DOM0_KEYBOARD);
-        dom0_gr_devices(1, DOM0_MOUSE);
-        goto out;
+       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_gr_devices(1, DOM0_KEYBOARD);
-        dom0_gr_devices(1, DOM0_MOUSE);
-        xenstore_write_dom0_driver("blank", "0");
-        goto out;
+       DEBUG("steal the focus from %d\n", mouse.domid);
+       dom0_gr_devices(1, DOM0_KEYBOARD);
+       dom0_gr_devices(1, DOM0_MOUSE);
+       driver.enter();
+       goto out;
     }
 
     ret = 0;
@@ -601,78 +366,48 @@ out:
     return ret;
 }
 
-
-static void dom0_driver_dev_init(void)
+static void dom0_driver_dom_command(const char *path, void *opaque)
 {
-    int         i = 0;
-    int         fd = 0;
-    int         keyboard = 0, mouse = 0;
-    char        path[strlen(EVENT_PATH) + 3];
-    char        name[128];
-
-    driver.keyboard_fds[0] = -1;
-    driver.mouse_fds[0] = -1;
-    while (1)
-    {
-        sprintf(path, "%s%i", EVENT_PATH, i++);
-        if (!(fd = open(path, O_RDONLY)))
-            break;
-        if (ioctl(fd, EVIOCGNAME(128), name) == -1)
-            break;
-
-        if (strcasestr(name, "keyboard"))
-        {
-            driver.keyboard_fds[keyboard] = fd;
-            driver.keyboard_fds[keyboard + 1] = -1;
-            keyboard++;
-            DEBUG("Use \"%s\" as a keyboard %d\n", name, fd);
-        }
-        else
-        {
-            driver.mouse_fds[mouse] = fd;
-            driver.mouse_fds[mouse + 1] = -1;
-            mouse++;
-            DEBUG("Use \"%s\" as a mouse %d\n", name, fd);
-        }
-    }
-    assert(driver.keyboard_fds[0] != -1);
-    assert(driver.mouse_fds[0] != -1);
-}
+    unsigned int len;
+    char *str;
+    char buff[256];
+    int        positions[NB_SLOTS];
+    int natif_domid;
+    int i;
+    struct dom0_driver_xs_info mouse;
 
-static void dom0_driver_dom_command(char *path, void *opaque)
-{
-       unsigned int len;
-       char *str;
-       char buff[256];
-       int     positions[NB_SLOTS];
-       int natif_domid;
-       int i;
-
-       if (!(str = xenstore_read(path)) || !*str)
-               return;
+    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");
+    DEBUG("Received private command %s\n", path);
+    dom0_get_positions(positions);
+    natif_domid = dom0_driver_xs_read_dom0("natif");
 
-       for (i = 0; i < NB_SLOTS; ++i)
-       {
-               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;
-       }
+    dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
+    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);
+    for (i = 0; i < NB_SLOTS; ++i)
+    {
+       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;
+    }
+
+    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)
@@ -682,48 +417,42 @@ static void dom0_driver_event_init(const char *str_arg)
     int                 pos = 0;
     int                 i = 0;
 
-    dom0_driver_dev_init();
-
     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);
+       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);
+       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);
+       sprintf(str, "%d", domid);
+       xenstore_write_dom0_driver("natif", str);
+       xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
+    }
+    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);
     }
-       else
-       {
-               xenstore_dom_write(domid, "dom0_input/command", "");
-               sprintf(str, "w%d", domid);
-               xenstore_dom_chmod(domid, "dom0_input/command", str);
-       }
 
     xenstore_watch_dom0_driver("mouse/state", dom0_driver_state_change, NULL);
     xenstore_watch_dom0_driver("keyboard/state", dom0_driver_state_change, NULL);
-
-    if (vga_passthrough)
-       {
-               xenstore_write_dom0_driver("blank", "0");
-        xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
-       }
-       else
-               xenstore_dom_watch(domid, "dom0_input/command", dom0_driver_dom_command, 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, dom0_driver_failover_switch, NULL);
+    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);
 }
 
@@ -734,38 +463,52 @@ static void dom0_driver_slots(int controller)
     int                         positions[NB_SLOTS];
 
     if (dom0_driver_failover_switch(NULL))
-        return;
+       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)
-            {
-                DEBUG("release devices\n");
-                dom0_gr_devices(0, controller);
-                return;
-            }
-
-            if (info.state == 2 && positions[info.new_slot] == domid)
-            {
-                DEBUG("grab devices\n");
-                dom0_gr_devices(1, controller);
-                return;
-            }
-
-        }
+       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)
 {
-    dom0_driver_xs_write("new-slot", slot, controller);
-    dom0_driver_xs_write("timestamp", time(NULL), controller);
-    dom0_driver_xs_write("state", 0, controller);
+    int        positions[NB_SLOTS];
+    char *str;
+    int len;
+
+    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);
+    if (strcmp(str, "1") == 0)
+    {
+       dom0_driver_xs_write("new-slot", slot, controller);
+       dom0_driver_xs_write("timestamp", time(NULL), controller);
+       dom0_driver_xs_write("state", 0, controller);
+    }
+    free(str);
 }
 
 void dom0_driver_command(const char *path, void *opaque)
@@ -774,47 +517,63 @@ void dom0_driver_command(const char *path, void *opaque)
 
     val = xenstore_read(path);
     if (val == NULL)
-        return;
+       return;
 
     if (!strncmp(val, "switch ", 7))
     {
-        int slot = strtol(val + 7, NULL, 10);
+       int slot = strtol(val + 7, NULL, 10);
 
-        if (errno == EINVAL)
-            goto out;
+       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");
+       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);
+       int slot = strtol(val + 9, NULL, 10);
 
-        if (errno == EINVAL)
-            goto out;
+       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");
+       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_blank_done(void)
+static void dom0_driver_leave_done(void)
 {
-    struct dom0_driver_xs_info  info;
-    int                         blank;
-
-    dom0_driver_read_xs_info(&info, DOM0_MOUSE);
-    blank = dom0_driver_xs_read_dom0("blank");
+    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");
+}
 
-    if (info.state == 1 && blank == 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)
     {
-        if (!vga_passthrough)
-            intel_focus(info.domid == domid);
+       xenstore_write_dom0_driver("leave", "0");
+       driver.enter();
     }
 }
 
@@ -822,38 +581,78 @@ static void dom0_driver_state_change(const char *path, void *opaque)
 {
 
     if (strstr(path, "/keyboard/state"))
-        dom0_driver_slots(DOM0_KEYBOARD);
+       dom0_driver_slots(DOM0_KEYBOARD);
     if (strstr(path, "/mouse/state"))
-        dom0_driver_slots(DOM0_MOUSE);
-    if (strstr(path, "/blank"))
-        dom0_driver_blank_done();
+       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)
-        {
-            char str[20];
-
-            if (!vga_passthrough && intel_getfocus()) {
-                intel_focus(0);
-                sprintf(str, "%d", !(mouse.domid == dom0_driver_xs_read_dom0("natif")));
-                xenstore_write_dom0_driver("blank", str);
-            } else if (vga_passthrough && mouse.domid != dom0_driver_xs_read_dom0("natif")) {
-                sprintf(str, "%d", !(mouse.domid == domid));
-                xenstore_write_dom0_driver("blank", str);
-            }
-        }
+       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();
+           }
+    }
+}
+
+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);
+}
+
+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));
     }
 }
 
 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
+    {
+       driver.enter = intel_enter;
+       driver.leave = intel_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 (file)
index 0000000..7bfee81
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * 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 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[4];
+    int                mouse_fds[4];
+    char       *controller_paths[8];
+    int                mouse_button_state;
+    int                key_status[256];
+} 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;
+    printf("binding payload %d\n", (int)(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);
+}
+
+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_key_event(int code, uint32_t keycode)
+{
+    if (code == 1)
+       if (hid_linux_detect_binding())
+           return;
+    hid_linux_key_inject(code, keycode);
+}
+
+void hid_linux_secure_keyboard(void (*cb)(int ascii))
+{
+}
+
+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_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);
+       }
+    }
+}
+
+static int hid_linux_grab_devices(int grab, int *fd)
+{      
+    assert(fd != NULL);
+    for (; *fd != -1; fd++)
+    {
+       if (ioctl(*fd, EVIOCGRAB, grab) == -1)
+           return 0;
+
+       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 stat        st;
+
+    while (1)
+    {
+       sprintf(path, "%s%i", EVENT_PATH, i++);
+
+       if ((fd = open(path, O_RDONLY)) == -1)
+           break;
+
+       for ( c = 0; c < 8 && hid_linux_driver.controller_paths[c]; c++)
+           if (!strcmp(hid_linux_driver.controller_paths[c], path))
+               break;
+       assert(c != 8);
+       if (hid_linux_driver.controller_paths[c])
+           continue;
+       
+       if (ioctl(fd, EVIOCGNAME(128), name) == -1)
+       {
+           DEBUG("Input get name failed on %s\n", path);
+           break;
+       }
+
+       if (strcasestr(name, "keyboard"))
+       {
+           DEBUG("Add %s as a keyboard\n", name);
+           controllers = hid_linux_driver.keyboard_fds;
+       }
+       else
+       {
+           DEBUG("Add %s as a mouse\n", name);
+           controllers = hid_linux_driver.mouse_fds;
+       }
+
+       for ( j = 0; j < 4 && controllers[j] != -1; j++)
+           ;
+       assert(j != 4);
+           
+       controllers[j] = fd;
+       controllers[j + 1] = -1;
+       hid_linux_driver.controller_paths[c] = strdup(path);
+       hid_linux_driver.controller_paths[c + 1] = NULL; 
+
+       if (grab)
+       {
+           DEBUG("Grab device %s\n", name);
+           hid_linux_grab_devices(0, controllers);
+       }
+       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/intel.c b/intel.c
index b629443365f4a19c3026c839c43405e0cb07b6c3..10c117db689fde484354edf788f60f4224037efd 100644 (file)
--- a/intel.c
+++ b/intel.c
@@ -472,6 +472,18 @@ void intel_take_screenshot(const char *filename)
     fclose(fd);
 }
 
+int intel_enter(void)
+{
+    intel_focus(1);
+    return 1;
+}
+
+int intel_leave(void)
+{
+    intel_focus(0);
+    return 1;
+}
+
 void intel_display_init(DisplayState *ds)
 {
     INTEL_DEBUG("\n");
index 7dd89769c99f95654022b7f13ec33a4ec16b3935..c756e04903cf8e9c8e6e027c5b68faa91d2ebbb7 100644 (file)
@@ -7,7 +7,7 @@
 #define MAPCACHE
 uint8_t *qemu_map_cache(target_phys_addr_t phys_addr);
 void     qemu_invalidate_map_cache(void);
-#else 
+#else
 #define qemu_invalidate_map_cache() ((void)0)
 #endif
 
@@ -124,4 +124,6 @@ int xenfb_connect_vfb(const char *path);
 
 int has_tpm_device_danger(void);
 
+char *get_time(void);
+
 #endif /*QEMU_XEN_H*/
index a9d5a0403167282599d2cecc3fbea177897ebec6..9c7f044c7f9f654f767c6d5a29df8bcf9c210dc4 100644 (file)
@@ -35,6 +35,7 @@ OBJS += pci_emulation.o
 OBJS += battery_mgmt.o
 OBJS += pt_pckbd.o
 OBJS += xen_acpi_wmi.o
+OBJS += hid-linux.o
 
 ifdef CONFIG_STUBDOM
 CPPFLAGS += $(TARGET_CPPFLAGS)
index b73c346b47853d57934dc7fc7b0da458c908f1b8..aa676048bf39f6ba2e8e8ff705659ec3e0c770b6 100644 (file)
@@ -67,7 +67,15 @@ int xenstore_watch_new_callback(const char          *path,
     }
 
     while (xenstore_watch_callbacks[i].path)
+    {
+       if (!strcmp(xenstore_watch_callbacks[i].path, path))
+       {
+           xenstore_watch_callbacks[i].cb = fptr;
+           xenstore_watch_callbacks[i].opaque = opaque;
+           return ret;
+       }
         i++;
+    }
 
     xenstore_watch_callbacks = realloc(xenstore_watch_callbacks,
                                        (i + 2) * sizeof (struct xenstore_watch_cb_t));
@@ -118,7 +126,7 @@ void xenstore_check_new_media_present(int timeout)
 }
 
 static void waitForDevice(char *fn)
-{ 
+{
     struct stat sbuf;
     int status;
     int uwait = UWAIT_MAX;
@@ -173,9 +181,9 @@ static int parse_drive_name(const char *dev, DriveInfo *out) {
 
     out->bus = ch / per_bus;
     out->unit = ch % per_bus;
-    
+
     return 0;
-}       
+}
 
 static int drive_name_to_index(const char *name) {
     DriveInfo tmp;
@@ -230,7 +238,7 @@ static void xenstore_get_backend_path(char **backend, const char *devtype,
 
     backend_dompath = xs_get_domain_path(xsh, domid_backend);
     if (!backend_dompath) goto out;
-    
+
     const char *expected_devtypes[3];
     const char **expected_devtype = expected_devtypes;
 
@@ -243,7 +251,7 @@ static void xenstore_get_backend_path(char **backend, const char *devtype,
     for (expected_devtype = expected_devtypes;
          *expected_devtype;
          expected_devtype++) {
-    
+
         if (pasprintf(&expected_backend, "%s/backend/%s/%lu/%s",
                       backend_dompath, *expected_devtype,
                       frontend_domid, inst_danger)
@@ -325,7 +333,7 @@ const char *xenstore_get_guest_uuid(void) {
  out:
     if (xch != -1)
         close(xch);
-    
+
     return 0;
 #endif
 }
@@ -377,7 +385,7 @@ void xenstore_parse_domain_config(int hvm_domid)
         xenstore_get_backend_path(&bpath, "vbd", danger_path, hvm_domid,
                                  e_danger[i]);
         if (bpath == NULL)
-            continue;    
+            continue;
         /* read the name of the device */
         if (pasprintf(&buf, "%s/dev", bpath) == -1)
             continue;
@@ -390,7 +398,7 @@ void xenstore_parse_domain_config(int hvm_domid)
             break;
         }
     }
-        
+
     for (i = 0; i < num; i++) {
        format = NULL; /* don't know what the format is yet */
         /* read the backend path */
@@ -460,9 +468,9 @@ void xenstore_parse_domain_config(int hvm_domid)
         * Hopefully if they are really needed for something
         * someone will shout and then we will find out what for.
         */
-        /* 
+        /*
          * check if device has a phantom vbd; the phantom is hooked
-         * to the frontend device (for ease of cleanup), so lookup 
+         * to the frontend device (for ease of cleanup), so lookup
          * the frontend device, and see if there is a phantom_vbd
          * if there is, we will use resolution as the filename
          */
@@ -478,8 +486,8 @@ void xenstore_parse_domain_config(int hvm_domid)
             DANGER DANGER params is supposedly trustworthy but here
                          we read it from untrusted part of xenstore
             if (params) {
-                /* 
-                 * wait for device, on timeout silently fail because we will 
+                /*
+                 * wait for device, on timeout silently fail because we will
                  * fail to open below
                  */
                 waitForDevice(params);
@@ -573,7 +581,7 @@ void xenstore_parse_domain_config(int hvm_domid)
     }
 
     /* Set a watch for suspend requests from the migration tools */
-    if (pasprintf(&buf, 
+    if (pasprintf(&buf,
                   "/local/domain/0/device-model/%u/command", domid) != -1) {
         xs_watch(xsh, buf, "dm-command");
         fprintf(logfile, "Watching %s\n", buf);
@@ -653,17 +661,17 @@ void xenstore_process_logdirty_event(void)
         int shmid;
 
         /* Find and map the shared memory segment for log-dirty bitmaps */
-        if (pasprintf(&path, 
-                      "/local/domain/0/device-model/%u/logdirty/key", 
+        if (pasprintf(&path,
+                      "/local/domain/0/device-model/%u/logdirty/key",
                       domid) == -1) {
             fprintf(logfile, "Log-dirty: out of memory\n");
             exit(1);
         }
-        
+
         key_ascii = xs_read(xsh, XBT_NULL, path, &len);
         free(path);
 
-        if (!key_ascii) 
+        if (!key_ascii)
             /* No key yet: wait for the next watch */
             return;
 
@@ -672,7 +680,7 @@ void xenstore_process_logdirty_event(void)
         key = (key_t) strtoull(key_terminated, NULL, 16);
 
         /* Figure out how bit the log-dirty bitmaps are */
-        logdirty_bitmap_size = xc_memory_op(xc_handle, 
+        logdirty_bitmap_size = xc_memory_op(xc_handle,
                                             XENMEM_maximum_gpfn, &domid) + 1;
         logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
                                 / HOST_LONG_BITS); /* longs */
@@ -699,7 +707,7 @@ void xenstore_process_logdirty_event(void)
 
         /* Double-check that the bitmaps are the size we expect */
         if (logdirty_bitmap_size != *(uint32_t *)seg) {
-            fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
+            fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
                     *(uint32_t *)seg, logdirty_bitmap_size);
             /* Stale key: wait for next watch */
             shmdt(seg);
@@ -708,13 +716,13 @@ void xenstore_process_logdirty_event(void)
         }
 
         /* Remember the paths for the next-active and active entries */
-        if (pasprintf(&active_path, 
+        if (pasprintf(&active_path,
                       "/local/domain/0/device-model/%u/logdirty/active",
                       domid) == -1) {
             fprintf(logfile, "Log-dirty: out of memory\n");
             exit(1);
         }
-        if (pasprintf(&next_active_path, 
+        if (pasprintf(&next_active_path,
                       "/local/domain/0/device-model/%u/logdirty/next-active",
                       domid) == -1) {
             fprintf(logfile, "Log-dirty: out of memory\n");
@@ -723,7 +731,7 @@ void xenstore_process_logdirty_event(void)
     }
 
     fprintf(logfile, "Triggered log-dirty buffer switch\n");
-    
+
     /* Read the required active buffer from the store */
     act = xs_read(xsh, XBT_NULL, next_active_path, &len);
     if (!act) {
@@ -752,7 +760,7 @@ static void xenstore_process_dm_command_event(void)
     char *path = NULL, *command = NULL, *par = NULL;
     unsigned int len;
 
-    if (pasprintf(&path, 
+    if (pasprintf(&path,
                   "/local/domain/0/device-model/%u/command", domid) == -1) {
         fprintf(logfile, "out of memory reading dm command\n");
         goto out;
@@ -760,7 +768,7 @@ static void xenstore_process_dm_command_event(void)
     command = xs_read(xsh, XBT_NULL, path, &len);
     if (!command)
         goto out;
-    
+
     if (!strncmp(command, "save", len)) {
         fprintf(logfile, "dm-command: pause and save state\n");
         xen_pause_requested = 1;
@@ -771,7 +779,7 @@ static void xenstore_process_dm_command_event(void)
     } else if (!strncmp(command, "pci-rem", len)) {
         fprintf(logfile, "dm-command: hot remove pass-through pci dev \n");
 
-        if (pasprintf(&path, 
+        if (pasprintf(&path,
                       "/local/domain/0/device-model/%u/parameter", domid) == -1) {
             fprintf(logfile, "out of memory reading dm command parameter\n");
             goto out;
@@ -785,7 +793,7 @@ static void xenstore_process_dm_command_event(void)
     } else if (!strncmp(command, "pci-ins", len)) {
         fprintf(logfile, "dm-command: hot insert pass-through pci dev \n");
 
-        if (pasprintf(&path, 
+        if (pasprintf(&path,
                       "/local/domain/0/device-model/%u/parameter", domid) == -1) {
             fprintf(logfile, "out of memory reading dm command parameter\n");
             goto out;
@@ -810,7 +818,7 @@ void xenstore_record_dm(char *subpath, char *state)
 {
     char *path = NULL;
 
-    if (pasprintf(&path, 
+    if (pasprintf(&path,
                   "/local/domain/0/device-model/%u/%s", domid, subpath) == -1) {
         fprintf(logfile, "out of memory recording dm \n");
         goto out;
@@ -837,7 +845,8 @@ void xenstore_process_event(void *opaque)
         return;
 
     for (i = 0; xenstore_watch_callbacks &&  xenstore_watch_callbacks[i].path; i++)
-        if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path))
+       if (xenstore_watch_callbacks[i].cb &&
+           !strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path))
             xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
                                            xenstore_watch_callbacks[i].opaque);
 
@@ -850,7 +859,7 @@ void xenstore_process_event(void *opaque)
         xenstore_process_dm_command_event();
         goto out;
     }
-    
+
     if (!strcmp(vec[XS_WATCH_TOKEN], "acadapterstatechangeevt")) {
         acpi_ac_adapter_state_changed();
         goto out;
@@ -947,7 +956,7 @@ void xenstore_write_vslots(char *vslots)
     char *path = NULL;
     int pci_devid = 0;
 
-    if (pasprintf(&path, 
+    if (pasprintf(&path,
                   "/local/domain/0/backend/pci/%u/%u/vslots", domid, pci_devid) == -1) {
         fprintf(logfile, "out of memory when updating vslots.\n");
         goto out;
@@ -1161,7 +1170,7 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
 static char *xenstore_vm_key_path(int domid, char *key) {
     const char *uuid;
     char *buf = NULL;
-    
+
     if (xsh == NULL)
         return NULL;
 
@@ -1226,7 +1235,7 @@ char *xenstore_device_model_read(int domid, char *key, unsigned int *len)
 char *xenstore_extended_power_mgmt_read(char *key, unsigned int *len)
 {
     char *path = NULL, *value = NULL;
-    
+
     if (pasprintf(&path, "/pm/%s", key) == -1)
         return NULL;
 
@@ -1242,7 +1251,7 @@ int xenstore_extended_power_mgmt_write(char * key, char * value)
 {
     int ret;
     char *path = NULL;
-    
+
     if (pasprintf(&path, "/pm/%s", key) == -1)
         return -1;
 
@@ -1255,7 +1264,7 @@ int xenstore_extended_power_mgmt_event_trigger(char *key, char * value)
 {
     int ret;
     char *path = NULL;
-    
+
     if (pasprintf(&path, "events/%s", key) == -1)
         return -1;
 
@@ -1266,7 +1275,7 @@ int xenstore_extended_power_mgmt_event_trigger(char *key, char * value)
 
 /*
  * Xen power management daemon stores battery generic information
- * like model, make, design volt, capacity etc. under /pm/bif and 
+ * like model, make, design volt, capacity etc. under /pm/bif and
  * battery status information like charging/discharging rate
  * under /pm/bst in xenstore.
  */
@@ -1282,7 +1291,7 @@ char *xenstore_read_battery_data(int battery_status)
  * We set /pm/events/refreshbatterystatus xenstore entry
  * to refresh battert status info stored under /pm/bst
  * Xen power management daemon watches for changes to this
- * entry and triggers a refresh.   
+ * entry and triggers a refresh.
  */
 int xenstore_refresh_battery_status(void)
 {
@@ -1423,7 +1432,7 @@ char *xenstore_read_dom0_driver(const char *key)
     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);
@@ -1436,7 +1445,7 @@ int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *op
     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);
@@ -1450,7 +1459,7 @@ int xenstore_write_dom0_driver(const char *key, const char *str)
     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));
@@ -1531,7 +1540,6 @@ void xenstore_dom_chmod(int domid, const char *key, const char *perms)
     free(buf);
 }
 
-
 int xenstore_dom_write(int domid, char *key, char *value)
 {
     char *buf = NULL, *path = NULL;