From: Jean Guyader Date: Tue, 10 Mar 2009 18:17:56 +0000 (+0000) Subject: Introduction the new dom0_driver code: X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=0616573df60ae59b6e2b7bb7f8c3fb3a3a165317;p=xenclient%2Fioemu.git Introduction the new dom0_driver code: - Split hid linux part into a file. - Cleanup into the dom0 driver code. --- diff --git a/console.h b/console.h index 1e396413..5fbcf782 100644 --- 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 diff --git a/dom0_driver.c b/dom0_driver.c index 91c763f5..2f593b3a 100644 --- a/dom0_driver.c +++ b/dom0_driver.c @@ -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 index 00000000..7bfee81a --- /dev/null +++ b/hid-linux.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 b6294433..10c117db 100644 --- 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"); diff --git a/qemu-xen.h b/qemu-xen.h index 7dd89769..c756e049 100644 --- a/qemu-xen.h +++ b/qemu-xen.h @@ -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*/ diff --git a/xen-hooks.mak b/xen-hooks.mak index a9d5a040..9c7f044c 100644 --- a/xen-hooks.mak +++ b/xen-hooks.mak @@ -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) diff --git a/xenstore.c b/xenstore.c index b73c346b..aa676048 100644 --- a/xenstore.c +++ b/xenstore.c @@ -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;