From: Jean Guyader Date: Tue, 27 Oct 2009 16:22:24 +0000 (+0000) Subject: Introduce new switching and input handling code. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=8489b09da11e160e552a96f10a614b630abc1696;p=xenclient%2Fioemu-pq.git Introduce new switching and input handling code. --- diff --git a/master/dom0-driver b/master/dom0-driver deleted file mode 100644 index 747acca..0000000 --- a/master/dom0-driver +++ /dev/null @@ -1,1441 +0,0 @@ -diff --git a/console.h b/console.h -index 14b42f3..97214c0 100644 ---- a/console.h -+++ b/console.h -@@ -341,4 +341,19 @@ const char *readline_get_history(unsigned int index); - void readline_start(const char *prompt, int is_password, - ReadLineFunc *readline_func, void *opaque); - -+/* get_time */ -+char *get_time(void); -+ -+/* dom0_driver.c */ -+void dom0_driver_init(const char *position); -+ -+/* hid_linux.c */ -+void hid_linux_init(void); -+int hid_linux_grab_keyboard(int grab); -+int hid_linux_grab_mouse(int grab); -+void hid_linux_secure_keyboard(void (*)(int)); -+void hid_linux_add_binding(const int *, void (*)(void*), void *); -+void hid_linux_reset_keyboard(void); -+void hid_linux_probe(int grab); -+ - #endif -diff --git a/dom0_driver.c b/dom0_driver.c -new file mode 100644 -index 0000000..92f6b17 ---- /dev/null -+++ b/dom0_driver.c -@@ -0,0 +1,709 @@ -+/* -+ * QEMU dom0_driver -+ * -+ * Copyright (c) 2009 Citrix Systems -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu-common.h" -+#include "console.h" -+#include "qemu-timer.h" -+#include "qemu-xen.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern int vga_passthrough; -+ -+static void dom0_driver_state_change(const char *path, void *opaque); -+static void dom0_driver_command(const char *path, void *opaque); -+static void dom0_driver_leave_done(void); -+ -+#define DEBUG_DOM0_DRIVER 1 -+#define XS_REFRESH_INTERVAL 1000 -+#define DOM0_DRIVER_SWITCH_TIMEOUT 2 -+ -+#define DOM0_MOUSE 1 -+#define DOM0_KEYBOARD 2 -+ -+#if DEBUG_DOM0_DRIVER -+# define DEBUG(_format_, args...) \ -+ do { \ -+ char *__str = get_time(); \ -+ fprintf(stderr, "[%s] dom0_driver(%d):%d: " _format_, __str, domid, __LINE__, ## args);\ -+ free(__str); \ -+ } while (false) -+#else -+# define DEBUG(_format_, args...) (void)0 -+#endif -+ -+#define NB_SLOTS 10 -+ -+static void dom0_read(void *opaque); -+static void dom0_driver_reset_keyboard(void); -+static void dom0_read_secure(void *opaque); -+struct dom0_driver -+{ -+ QEMUTimer *xs_timer; -+ int secure_fd; -+ int (*enter)(void); -+ int (*leave)(void); -+}; -+ -+struct dom0_driver_handler -+{ -+ void (*init)(void); -+ void (*probe)(int); -+ int (*grab_keyboard)(int); -+ int (*grab_mouse)(int); -+ void (*secure_keyboard)(void (*)(int)); -+ void (*reset_keyboard)(void); -+ void (*add_binding)(const int *, void (*)(void *), void *); -+}; -+ -+struct dom0_driver_xs_info -+{ -+ int state; -+ int domid; -+ int new_slot; -+ int timestamp; -+ int pre; -+}; -+ -+static struct dom0_driver_handler dom0_driver_hid_linux = -+{ -+ .init = hid_linux_init, -+ .probe = hid_linux_probe, -+ .grab_keyboard = hid_linux_grab_keyboard, -+ .grab_mouse = hid_linux_grab_mouse, -+ .secure_keyboard = hid_linux_secure_keyboard, -+ .reset_keyboard = hid_linux_reset_keyboard, -+ .add_binding = hid_linux_add_binding, -+}; -+ -+static struct dom0_driver driver; -+static struct dom0_driver_handler *dom0_driver_handler = NULL; -+ -+static int dom0_driver_xs_read_dom0(const char *key) -+{ -+ char *str = NULL; -+ -+ if (!(str = xenstore_read_dom0_driver(key))) -+ { -+ fprintf(stderr, "dom0_driver: fatal the node %s don't exits\n", key); -+ exit(2); -+ } -+ return strtol(str, NULL, 10); -+} -+ -+static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info, -+ int controller) -+{ -+ char *str = NULL; -+ char path[128]; -+ int val[10]; -+ const char *key[] = {"state", "domid", "new-slot", "timestamp", "pre"}; -+ -+ memset(info, -1, sizeof (struct dom0_driver_xs_info)); -+ for (int i = 0; i < sizeof (key) / sizeof (key[0]); i++) -+ { -+ if (controller == DOM0_MOUSE) -+ sprintf(path, "mouse/%s", key[i]); -+ else if (controller == DOM0_KEYBOARD) -+ sprintf(path, "keyboard/%s", key[i]); -+ else -+ { -+ fprintf(stderr, "dom0_driver unknown controller type\n"); -+ exit(2); -+ } -+ -+ val[i] = -1; -+ if ((str = xenstore_read_dom0_driver(path))) -+ { -+ val[i] = strtol(str, NULL, 10); -+ free(str); -+ } -+ } -+ -+ info->state = val[0]; -+ info->domid = val[1]; -+ info->new_slot = val[2]; -+ info->timestamp = val[3]; -+ info->pre = val[4]; -+} -+ -+static void dom0_driver_xs_write(const char *key, int val, int controller) -+{ -+ char path[256], str[20]; -+ -+ if (controller == DOM0_MOUSE) -+ sprintf(path, "mouse/%s", key); -+ else if (controller == DOM0_KEYBOARD) -+ sprintf(path, "keyboard/%s", key); -+ else -+ { -+ DEBUG("unknown controller type\n"); -+ exit(2); -+ } -+ -+ sprintf(str, "%d", val); -+ DEBUG("write %s=%d\n", path, val); -+ xenstore_write_dom0_driver(path, str); -+} -+ -+/* -+** Blanker fonctions -+*/ -+static void dom0_driver_blank_changed(void) -+{ -+ char *str; -+ int blank; -+ -+ if (!(str = xenstore_read_dom0_driver("blank"))) -+ return; -+ blank = strtol(str, NULL, 10); -+ free(str); -+ if (blank == 2) -+ { -+ usleep(100 * 1000); /* 100 ms */ -+ dom0_driver_leave_done(); -+ } -+} -+static int dom0_driver_blank(void) -+{ -+ xenstore_write_dom0_driver("blank", "1"); -+ return 0; -+} -+static int dom0_driver_unblank(void) -+{ -+ xenstore_write_dom0_driver("blank", "0"); -+ return 0; -+} -+ -+static void dom0_driver_key_switch(int new_slot) -+{ -+ struct dom0_driver_xs_info info; -+ char buff[128]; -+ -+ dom0_driver_read_xs_info(&info, DOM0_MOUSE); -+ assert(info.state == 1); -+ -+ sprintf(buff, "switch %d", new_slot); -+ -+ DEBUG("Write \"%s\" into xenstore\n", buff); -+ xenstore_write_dom0_driver("command", buff); -+} -+ -+static void dom0_driver_read_secure(int ascii) -+{ -+ int write_sz; -+ -+ if (ascii) -+ { -+ DEBUG("Send %d to xenmgr\n", ascii); -+ write_sz = write(driver.secure_fd, &ascii, 1); -+ if (ascii == -1 || ascii == 27 || write_sz != 1) -+ { -+ dom0_driver_handler->reset_keyboard(); -+ dom0_driver_handler->secure_keyboard(NULL); -+ return; -+ } -+ } -+} -+ -+static void dom0_driver_detect_secure_auth(void* opaque) -+{ -+ struct stat s; -+ int sas_ascii = 1, ret = 0;; -+ -+ DEBUG("Received SAS keystroke\n"); -+ if ((driver.secure_fd = open("/var/lib/xenmgr/keys", O_WRONLY)) > 0) -+ { -+ DEBUG("write SAS ascii code\n"); -+ if ((ret = write(driver.secure_fd, &sas_ascii, 1)) == 1) -+ { -+ DEBUG("Redirect fds to secure callback\n"); -+ dom0_driver_handler->secure_keyboard(dom0_driver_read_secure); -+ } -+ DEBUG("writing SAS ret %d\n", ret); -+ -+ } -+ else -+ DEBUG("xenmgr file is not there\n"); -+} -+ -+static void dom0_get_positions(int *positions) -+{ -+ int *domids = NULL; -+ int num; -+ char *tmp; -+ unsigned int len; -+ int pos = 0; -+ -+ for (int i = 0; i < NB_SLOTS; i++) -+ positions[i] = 0; -+ -+ /* Get all the positions */ -+ domids = xenstore_get_domids(&num); -+ for (int i = 0; i < num; i++) -+ if (domids[i]) -+ { -+ if (!(tmp = xenstore_dom_read(domids[i], "dom0_input/pos", &len))) -+ continue; -+ pos = strtol(tmp, NULL, 10); -+ free(tmp); -+ -+ positions[pos] = domids[i]; -+ } -+ free(domids); -+} -+ -+static void dom0_gr_devices(int grab, int controller) -+{ -+ if (controller == DOM0_MOUSE) -+ { -+ DEBUG("%s mouse\n", grab ? "Grab" : "Release"); -+ assert(dom0_driver_handler->grab_mouse(grab)); -+ } -+ if (controller == DOM0_KEYBOARD) -+ { -+ DEBUG("%s keyboard\n", grab ? "Grab" : "Release"); -+ assert(dom0_driver_handler->grab_keyboard(grab)); -+ } -+ -+ dom0_driver_handler->reset_keyboard(); -+ if (!grab) -+ dom0_driver_xs_write("pre", domid, controller); -+ dom0_driver_xs_write("domid", domid, controller); -+ dom0_driver_xs_write("state", grab ? 1 : 2, controller); -+} -+ -+static int dom0_dom_alive(int id) -+{ -+ xc_dominfo_t info; -+ int rc; -+ -+ rc = xc_domain_getinfo(xc_handle, id, 1, &info); -+ return rc == 1 && info.domid == id; -+} -+ -+ -+static int dom0_driver_failover_switch(void *opaque) -+{ -+ int ret = 1; -+ uint32_t t = time(NULL); -+ struct dom0_driver_xs_info mouse, keyboard; -+ -+ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE); -+ dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD); -+ if (mouse.domid == domid) -+ dom0_driver_handler->probe(1); -+ else -+ dom0_driver_handler->probe(0); -+ -+ if (!vga_passthrough) -+ return 0; -+ -+ if (mouse.state == -1) -+ { -+ DEBUG("No state grab the device\n"); -+ dom0_gr_devices(1, DOM0_KEYBOARD); -+ dom0_gr_devices(1, DOM0_MOUSE); -+ driver.enter(); -+ goto out; -+ } -+ -+ /* The domain which has the focus crash */ -+ if (!dom0_dom_alive(mouse.domid)) -+ { -+ DEBUG("steal the focus from %d\n", mouse.domid); -+ dom0_driver_xs_write("pre", -1, DOM0_KEYBOARD); -+ dom0_driver_xs_write("pre", -1, DOM0_MOUSE); -+ dom0_gr_devices(1, DOM0_KEYBOARD); -+ dom0_gr_devices(1, DOM0_MOUSE); -+ driver.enter(); -+ goto out; -+ } -+ -+ if ( keyboard.state == 2 && -+ (t - keyboard.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT) -+ { -+ DEBUG("Keyboard in state 2 for to long, take it back\n"); -+ dom0_gr_devices(1, DOM0_KEYBOARD); -+ } -+ -+ if (mouse.state == 2 && -+ (t - mouse.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT) -+ { -+ DEBUG("Mouse in state 2 for to long, take it back\n"); -+ dom0_gr_devices(1, DOM0_MOUSE); -+ DEBUG("Get the focus now !\n"); -+ driver.enter(); -+ goto out; -+ } -+ -+ ret = 0; -+out: -+ qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL); -+ return ret; -+} -+ -+static void dom0_driver_dom_command(const char *path, void *opaque) -+{ -+ unsigned int len; -+ char *str; -+ char buff[256]; -+ int positions[NB_SLOTS]; -+ int natif_domid; -+ int i; -+ struct dom0_driver_xs_info mouse; -+ -+ if (!(str = xenstore_read(path)) || !*str) -+ return; -+ -+ DEBUG("Received private command %s\n", path); -+ dom0_get_positions(positions); -+ natif_domid = dom0_driver_xs_read_dom0("natif"); -+ -+ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE); -+ for (i = 0; i < NB_SLOTS; ++i) -+ { -+ if (!strcmp("switch", str) && positions[i] == domid) -+ break; -+ if (!strcmp("take", str) && positions[i] == domid) -+ break; -+ if (!strcmp("release", str) && positions[i] == natif_domid) -+ break; -+ } -+ if (i == NB_SLOTS) -+ { -+ DEBUG("Try to %s on a bad slot\n", str); -+ free(str); -+ return; -+ } -+ -+ if (!strcmp("switch", str)) -+ sprintf(buff, "switch %d", i); -+ else -+ { -+ if (mouse.domid != natif_domid) -+ { -+ DEBUG("Natif should have the focus for that.\n"); -+ return; -+ } -+ sprintf(buff, "keyboard %d", i); -+ } -+ -+ DEBUG("Write \"%s\" into xenstore\n", buff); -+ xenstore_write_dom0_driver("command", buff); -+ free(str); -+} -+ -+static void dom0_driver_event_init(const char *str_arg) -+{ -+ int positions[NB_SLOTS]; -+ char str[20]; -+ int pos = 0; -+ int i = 0; -+ -+ pos = strtol(str_arg, NULL, 10); -+ dom0_get_positions(positions); -+ if (positions[pos]) -+ { -+ DEBUG("There is already a vm at this slot\n"); -+ exit(1); -+ } -+ else -+ { -+ snprintf(str, 9, "%d", pos); -+ xenstore_dom_write(domid, "dom0_input/pos", str); -+ } -+ -+ if (vga_passthrough) -+ { -+ sprintf(str, "%d", domid); -+ xenstore_write_dom0_driver("natif", str); -+ xenstore_dom_chmod(0, "dom0_driver/natif", "r0"); -+ xenstore_watch_dom0_driver("command", dom0_driver_command, NULL); -+ xenstore_dom_chmod(0, "dom0_driver/command", "w0"); -+ } -+ else -+ { -+ xenstore_dom_write(domid, "dom0_input/command", ""); -+ sprintf(str, "w%d", domid); -+ xenstore_dom_chmod(domid, "dom0_input/command", str); -+ xenstore_dom_watch(domid, "dom0_input/command", dom0_driver_dom_command, NULL); -+ } -+ -+ xenstore_watch_dom0_driver("mouse/state", dom0_driver_state_change, NULL); -+ xenstore_watch_dom0_driver("keyboard/state", dom0_driver_state_change, NULL); -+ xenstore_watch_dom0_driver("leave", dom0_driver_state_change, NULL); -+ xenstore_watch_dom0_driver("blank", dom0_driver_state_change, NULL); -+ -+ /* Register the failover switch */ -+ driver.xs_timer = qemu_new_timer(rt_clock, -+ (void (*)(void *))dom0_driver_failover_switch, -+ NULL); -+ qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL); -+} -+ -+static void dom0_driver_slots(int controller) -+{ -+ struct dom0_driver_xs_info info; -+ int next_domid; -+ int positions[NB_SLOTS]; -+ -+ if (dom0_driver_failover_switch(NULL)) -+ return; -+ -+ dom0_driver_read_xs_info(&info, controller); -+ -+ if (info.new_slot != -1) -+ { -+ dom0_get_positions(positions); -+ if (positions[info.new_slot] != 0) -+ { -+ if (info.state == 0 && info.domid == domid) -+ { -+ dom0_gr_devices(0, controller); -+ return; -+ } -+ -+ if (info.state == 2 && positions[info.new_slot] == domid) -+ { -+ dom0_gr_devices(1, controller); -+ return; -+ } -+ -+ } -+ } -+} -+ -+static void dom0_driver_switch_controller(int slot, int controller) -+{ -+ int positions[NB_SLOTS]; -+ char *str; -+ int len; -+ int ready; -+ struct dom0_driver_xs_info info; -+ -+ dom0_get_positions(positions); -+ if (positions[slot] == 0) -+ { -+ DEBUG("Cannot switch controller %d to %d slot empty\n", controller, slot); -+ return; -+ } -+ -+ str = xenstore_dom_read(positions[slot], "dom0_input/ready", &len); -+ ready = strtol(str, NULL, 10); -+ free(str); -+ if (ready != 1) -+ { -+ DEBUG("Cannot switch controller %d to %d slot not ready\n", controller, slot); -+ return; -+ } -+ -+ dom0_driver_read_xs_info(&info, controller); -+ if (info.state != 1) -+ { -+ DEBUG("Cannot switch controller %d to %d, unstable state\n", controller, slot); -+ return; -+ } -+ -+ dom0_driver_xs_write("new-slot", slot, controller); -+ dom0_driver_xs_write("timestamp", time(NULL), controller); -+ dom0_driver_xs_write("state", 0, controller); -+} -+ -+void dom0_driver_command(const char *path, void *opaque) -+{ -+ char *val = NULL; -+ -+ val = xenstore_read(path); -+ if (val == NULL) -+ return; -+ -+ if (!strncmp(val, "switch ", 7)) -+ { -+ int slot = strtol(val + 7, NULL, 10); -+ -+ if (errno == EINVAL) -+ goto out; -+ -+ DEBUG("switch the keyboard/mouse to slot %d\n", slot); -+ dom0_driver_switch_controller(slot, DOM0_KEYBOARD); -+ dom0_driver_switch_controller(slot, DOM0_MOUSE); -+ xenstore_write(path, "done"); -+ } -+ else if (!strncmp(val, "keyboard ", 9)) -+ { -+ int slot = strtol(val + 9, NULL, 10); -+ -+ if (errno == EINVAL) -+ goto out; -+ -+ DEBUG("switch the keyboard to slot %d\n", slot); -+ dom0_driver_switch_controller(slot, DOM0_KEYBOARD); -+ xenstore_write(path, "done"); -+ } -+out: -+ free(val); -+} -+ -+static void dom0_driver_leave_done(void) -+{ -+ char *str; -+ int id; -+ -+ if (!(str = xenstore_read_dom0_driver("leave"))) -+ return; -+ id = strtol(str, NULL, 10); -+ free(str); -+ if (id == 1) -+ xenstore_write_dom0_driver("leave", "2"); -+} -+ -+static void dom0_driver_leave_changed(void) -+{ -+ char *str; -+ int id; -+ struct dom0_driver_xs_info mouse; -+ -+ if (!(str = xenstore_read_dom0_driver("leave"))) -+ return; -+ id = strtol(str, NULL, 10); -+ free(str); -+ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE); -+ if (id == 2 && mouse.domid == domid) -+ { -+ xenstore_write_dom0_driver("leave", "0"); -+ driver.enter(); -+ } -+} -+ -+static void dom0_driver_state_change(const char *path, void *opaque) -+{ -+ -+ if (strstr(path, "/keyboard/state")) -+ dom0_driver_slots(DOM0_KEYBOARD); -+ if (strstr(path, "/mouse/state")) -+ dom0_driver_slots(DOM0_MOUSE); -+ if (strstr(path, "/leave")) -+ dom0_driver_leave_changed(); -+ else if (strstr(path, "/blank")) -+ dom0_driver_blank_changed(); -+ else -+ { -+ struct dom0_driver_xs_info mouse, keyboard; -+ -+ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE); -+ dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD); -+ -+ if (mouse.state == 1 && keyboard.state == 1) -+ if (mouse.pre != -1 && mouse.pre == domid) -+ { -+ xenstore_write_dom0_driver("leave", "1"); -+ if (driver.leave()) -+ dom0_driver_leave_done(); -+ } -+ } -+} -+ -+static void dom0_driver_switch(void *slot_arg) -+{ -+ int slot = (int)slot_arg; -+ char buff[64]; -+ -+ DEBUG("%d pressed switch to slot %d\n", slot, slot); -+ sprintf(buff, "switch %d", slot); -+ xenstore_write_dom0_driver("command", buff); -+} -+ -+static void dom0_driver_switch_bind(void) -+{ -+ int i = 0; -+ int binds[4]; -+ -+ for (i = 0; i < 4; i++) -+ binds[i] = -1; -+ -+ for (i = 0; i < 9; i++) -+ { -+ binds[0] = KEY_LEFTCTRL; -+ binds[1] = KEY_1 + i; -+ dom0_driver_handler->add_binding(binds, dom0_driver_switch, (void*)(i + 1)); -+ } -+ binds[1] = KEY_0; -+ dom0_driver_handler->add_binding(binds, dom0_driver_switch, (void*)(0)); -+ -+ binds[0] = KEY_LEFTCTRL; -+ binds[1] = KEY_LEFTALT; -+ binds[2] = KEY_BACKSPACE; -+ binds[3] = -1; -+ dom0_driver_handler->add_binding(binds, dom0_driver_detect_secure_auth, NULL); -+} -+ -+static int dom0_driver_dummy_enter_leave(void) -+{ -+ return 1; -+} -+ -+void dom0_driver_init(const char *position) -+{ -+ memset(&driver, 0, sizeof (driver)); -+ -+ dom0_driver_handler = &dom0_driver_hid_linux; -+ dom0_driver_handler->init(); -+ -+ if (vga_passthrough) -+ { -+ driver.enter = dom0_driver_unblank; -+ driver.leave = dom0_driver_blank; -+ } -+ else if (intel) -+ { -+ driver.enter = intel_enter; -+ driver.leave = intel_leave; -+ } -+ else -+ { -+ driver.enter = dom0_driver_dummy_enter_leave; -+ driver.leave = dom0_driver_dummy_enter_leave; -+ } -+ -+ dom0_driver_switch_bind(); -+ dom0_driver_event_init(position); -+ dom0_driver_failover_switch(NULL); -+ -+ DEBUG("done\n"); -+ xenstore_dom_write(domid, "dom0_input/ready", "1"); -+} -diff --git a/hid-linux.c b/hid-linux.c -new file mode 100644 -index 0000000..59dfec8 ---- /dev/null -+++ b/hid-linux.c -@@ -0,0 +1,527 @@ -+/* -+ * QEMU hid-linux /dev/input driver -+ * -+ * Copyright (c) 2008 Citrix Systems -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu-common.h" -+#include "console.h" -+#include "qemu-timer.h" -+#include "qemu-xen.h" -+ -+#include -+#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 HID_LINUX_MAX_DEV 16 -+ -+#define DEBUG_HID_LINUX -+ -+#ifdef DEBUG_HID_LINUX -+# define DEBUG(_format_, args...) \ -+ do \ -+{ \ -+ char *__str = get_time(); \ -+ fprintf(stderr, "[%s] hid-linux(%d):%d: " _format_, (__str), domid, __LINE__, ## args);\ -+ free(__str);\ -+} \ -+while (0); -+#else -+# define DEBUG(_format_, args...) (void)0 -+#endif -+ -+static struct hid_linux_driver -+{ -+ int keyboard_fds[HID_LINUX_MAX_DEV / 2]; -+ int mouse_fds[HID_LINUX_MAX_DEV / 2]; -+ char *controller_paths[HID_LINUX_MAX_DEV]; -+ int mouse_button_state; -+ int key_status[256]; -+ void (*secure_key)(int ascii); -+} hid_linux_driver; -+ -+struct hid_linux_binding -+{ -+ int *binding; -+ void (*cb)(void *); -+ void *payload; -+}; -+ -+static struct hid_linux_binding *hid_linux_binding = NULL; -+ -+static const int ascii2keycode_table[] = -+{ -+ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, -+ KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, -+ KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z -+}; -+ -+static char keycode2ascii(int keycode) -+{ -+ int i = 0; -+ -+ switch (keycode) -+ { -+ case KEY_ESC: return 27; -+ case KEY_BACKSPACE: return 8; -+ case KEY_ENTER: return 10; -+ case KEY_LEFT: return 17; -+ case KEY_RIGHT: return 18; -+ case KEY_DELETE: return 127; -+ case KEY_HOME: return 2; -+ case KEY_END: return 3; -+ case KEY_INSERT: return 19; -+ case KEY_SPACE: return 20; -+ default: -+ for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++) -+ if (ascii2keycode_table[i] == keycode) -+ return i + 'a'; -+ } -+ return 0; -+} -+ -+static int ascii2keycode(char ascii) -+{ -+ return ascii2keycode_table[ascii - 'a']; -+} -+ -+static char *hid_linux_xs_read(const char *key) -+{ -+ char *path = NULL; -+ char *ret; -+ -+ if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1) -+ return NULL; -+ ret = xenstore_read(path); -+ free(path); -+ return ret; -+} -+ -+void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload) -+{ -+ int i = 0, j = 0; -+ -+ for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++) -+ ; -+ hid_linux_binding = realloc(hid_linux_binding, -+ (i + 2) * sizeof (struct hid_linux_binding)); -+ hid_linux_binding[i + 1].cb = NULL; -+ hid_linux_binding[i].cb = cb; -+ hid_linux_binding[i].payload = payload; -+ hid_linux_binding[i].binding = NULL; -+ -+ j = 0; -+ do -+ { -+ hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding, -+ (j + 1) * sizeof (int)); -+ hid_linux_binding[i].binding[j] = tab[j]; -+ } -+ while (tab[j++] != -1); -+} -+ -+static int hid_linux_detect_binding(void) -+{ -+ int i, j; -+ -+ for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++) -+ { -+ int *tab = hid_linux_binding[i].binding; -+ -+ for (j = 0; tab[j] != -1; j++) -+ if (hid_linux_driver.key_status[tab[j]] == 0) -+ break; -+ if (tab[j] != -1) -+ continue; -+ else /* We match a binding */ -+ { -+ DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload)); -+ hid_linux_binding[i].cb(hid_linux_binding[i].payload); -+ hid_linux_reset_keyboard(); -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+static void hid_linux_key_inject(int code, uint32_t keycode) -+{ -+ int first = 0; -+ -+ switch (keycode) -+ { -+ case KEY_F11: keycode = 0X57; break; /* F11 */ -+ case KEY_F12: keycode = 0X58; break; /* F12 */ -+ case KEY_INSERT: keycode = 0X52; break; -+ case KEY_HOME: keycode = 0X47; break; -+ case KEY_PAGEUP: keycode = 0X49; break; -+ case KEY_DELETE: keycode = 0X53; break; -+ case KEY_END: keycode = 0X4F; break; -+ case KEY_PAGEDOWN: keycode = 0x51; break; -+ case KEY_UP: keycode = 0X48; break; -+ case KEY_LEFT: keycode = 0X4B; break; -+ case KEY_DOWN: keycode = 0X50; break; -+ case KEY_RIGHT: keycode = 0X4D; break; -+ case KEY_RIGHTALT: keycode = 0x38; first = 0xe0; break; -+ case KEY_LEFTMETA: keycode = 0x5B; first = 0xe0; break; -+ case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break; -+ } -+ -+ if (first) -+ kbd_put_keycode(first); -+ -+ if (code == 0) -+ kbd_put_keycode(keycode | 0x80); -+ else -+ kbd_put_keycode(keycode & 0x7f); -+} -+ -+ -+ -+static void hid_linux_key_event(int code, uint32_t keycode) -+{ -+ if (code == 1) -+ if (hid_linux_detect_binding()) -+ return; -+ hid_linux_key_inject(code, keycode); -+} -+ -+static void hid_linux_read(void *opaque) -+{ -+ struct input_event event[5]; -+ int i = 0; -+ int read_sz = 0; -+ int fd = *(int *)opaque; -+ -+ read_sz = read(fd, event, sizeof (event)); -+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) -+ { -+ if (event[i].type == EV_KEY) -+ { -+ if (event[i].code >= BTN_MOUSE) -+ { -+ /* Mouse Key */ -+ int type = 0; -+ -+ switch(event[i].code) -+ { -+ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break; -+ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break; -+ case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break; -+ } -+ -+ if (event[i].value) -+ hid_linux_driver.mouse_button_state |= type; -+ else -+ hid_linux_driver.mouse_button_state &= ~type; -+ kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state); -+ } -+ else -+ { -+ hid_linux_driver.key_status[event[i].code] = event[i].value; -+ hid_linux_key_event(event[i].value, event[i].code); -+ } -+ } -+ -+ if (event[i].type == EV_REL || event[i].type == EV_ABS) -+ { -+ /* Mouse motion */ -+ int x = 0, y = 0, z = 0; -+ -+ if (event[i].type == EV_REL) -+ switch (event[i].code) -+ { -+ case REL_X : x = event[i].value; break; -+ case REL_Y : y = event[i].value; break; -+ case REL_WHEEL : z = -event[i].value; break; -+ } -+ if (event[i].type == EV_ABS) -+ { -+ static int last_x = 1, last_y = 1; -+ int px = 0, py = 0, l = 50; -+ double div = 1; -+ char *str = NULL; -+ -+ str = hid_linux_xs_read("touchpad-limit"); -+ if (str) -+ l = strtol(str, NULL, 10); -+ str = hid_linux_xs_read("touchpad-div"); -+ if (str) -+ div = strtol(str, NULL, 10) / 1000.; -+ -+ switch (event[i].code) -+ { -+ case ABS_X : x = event[i].value; break; -+ case ABS_Y : y = event[i].value; break; -+ } -+ -+ if (x) -+ { -+ px = x - last_x; -+ last_x = x; -+ } -+ if (y) -+ { -+ py = y - last_y; -+ last_y = y; -+ } -+ -+ x = (ABS(px) < l ? px : 0) / div; -+ y = (ABS(py) < l ? py : 0) / div; -+ } -+ -+ kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state); -+ } -+ } -+} -+ -+void hid_linux_reset_keyboard(void) -+{ -+ int i = 0; -+ -+ for (i = 0; i < 256; i++) -+ if (hid_linux_driver.key_status[i]) -+ { -+ hid_linux_key_inject(0, i); -+ hid_linux_driver.key_status[i] = 0; -+ } -+} -+ -+ -+ -+static void hid_linux_redirect_fds(int *fd, IOHandler *cb) -+{ -+ assert(fd != NULL); -+ -+ while (*fd != -1) -+ { -+ qemu_set_fd_handler(*fd, cb, NULL, fd); -+ fd++; -+ } -+} -+ -+static void hid_linux_secure_read(void *opaque) -+{ -+ struct input_event event[5]; -+ int i = 0; -+ int read_sz = 0; -+ int fd = *(int *)opaque; -+ -+ assert(hid_linux_driver.secure_key); -+ -+ read_sz = read(fd, event, sizeof (event)); -+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) -+ if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE && -+ event[i].value > 0) -+ hid_linux_driver.secure_key(keycode2ascii(event[i].code)); -+} -+ -+ -+void hid_linux_secure_keyboard(void (*cb)(int ascii)) -+{ -+ hid_linux_driver.secure_key = cb; -+ if (cb) -+ hid_linux_redirect_fds(hid_linux_driver.keyboard_fds, -+ hid_linux_secure_read); -+ else -+ hid_linux_redirect_fds(hid_linux_driver.keyboard_fds, -+ hid_linux_read); -+} -+ -+static int hid_linux_grab_devices(int grab, int *fd) -+{ -+ int rc = 0; -+ int try = 10; -+ -+ assert(fd != NULL && *fd != -1); -+ for (; *fd != -1; fd++) -+ { -+ while (try--) -+ { -+ if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1) -+ { -+ char *er; -+ -+ if (errno == EBUSY) -+ continue; -+ er = strerror(errno); -+ DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er); -+ return 0; -+ } -+ else -+ break; -+ } -+ assert(try); -+ -+ DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd); -+ -+ if (grab) -+ qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd); -+ else -+ qemu_set_fd_handler(*fd, NULL, NULL, fd); -+ } -+ return 1; -+} -+ -+int hid_linux_grab_keyboard(int grab) -+{ -+ return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds); -+} -+ -+int hid_linux_grab_mouse(int grab) -+{ -+ return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds); -+} -+ -+static int hid_linux_open_timeout(const char *path, int flags) -+{ -+ int try = 10; -+ int fd = 0; -+ -+ while (try-- && ((fd = open(path, flags)) == -1)) -+ usleep(100000); /* 10 ms */ -+ if (try == 0) -+ return 0; -+ return fd == -1 ? 0 : fd; -+} -+ -+static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2) -+{ -+ int try = 10; -+ -+ while (try-- && ioctl(fd, arg1, arg2) == -1) -+ usleep(100000); /* 10 ms */ -+ if (try == 0) -+ return 0; -+ return 1; -+} -+ -+void hid_linux_probe(int grab) -+{ -+ int i = 0, j = 0, c = 0; -+ int fd = -1; -+ int keyboard = 0, mouse = 0; -+ char path[strlen(EVENT_PATH) + 3]; -+ char name[128]; -+ int *controllers; -+ struct input_id id; -+ struct stat st; -+ -+ while (1) -+ { -+ if (fd != -1) -+ close(fd); -+ -+ sprintf(path, "%s%i", EVENT_PATH, i++); -+ -+ if (stat(path, &st) == -1) -+ break; -+ -+ for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++) -+ if (!strcmp(hid_linux_driver.controller_paths[c], path)) -+ break; -+ assert(c != HID_LINUX_MAX_DEV); -+ if (hid_linux_driver.controller_paths[c]) -+ continue; -+ -+ if ((fd = open(path, O_RDONLY)) == -1) -+ break; -+ -+ if (ioctl(fd, EVIOCGNAME(128), name) == -1) -+ { -+ DEBUG("Input get name failed on %s\n", path); -+ break; -+ } -+ -+ if (ioctl(fd, EVIOCGID, &id) == -1) -+ { -+ DEBUG("Input get id failed on %s\n", path); -+ continue; -+ } -+ -+ /* Only get devices on usb and i8042 */ -+ if (id.bustype != BUS_I8042 && id.bustype != BUS_USB) -+ continue; -+ -+ if (strcasestr(name, "keyboard")) -+ { -+ DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype); -+ controllers = hid_linux_driver.keyboard_fds; -+ } -+ else -+ { -+ DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype); -+ controllers = hid_linux_driver.mouse_fds; -+ } -+ -+ for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++) -+ ; -+ assert(j != (HID_LINUX_MAX_DEV / 2)); -+ -+ controllers[j] = fd; -+ controllers[j + 1] = -1; -+ -+ if (grab) -+ { -+ if (!hid_linux_grab_devices(1, controllers + j)) -+ { -+ DEBUG("Grabing failed, try next time...\n"); -+ controllers[j] = -1; -+ break; -+ } -+ } -+ -+ hid_linux_driver.controller_paths[c] = strdup(path); -+ hid_linux_driver.controller_paths[c + 1] = NULL; -+ -+ fd = -1; -+ } -+ if (fd != -1) -+ close(fd); -+} -+ -+void hid_linux_init(void) -+{ -+ hid_linux_driver.keyboard_fds[0] = -1; -+ hid_linux_driver.mouse_fds[0] = -1; -+ hid_linux_driver.controller_paths[0] = NULL; -+ -+ while (hid_linux_driver.keyboard_fds[0] == -1) -+ { -+ hid_linux_probe(0); -+ usleep(100000); /* 10 ms */ -+ } -+} -diff --git a/qemu-xen.h b/qemu-xen.h -index 7883718..afe8f22 100644 ---- a/qemu-xen.h -+++ b/qemu-xen.h -@@ -109,7 +109,13 @@ int xenstore_write(const char *path, const char *val); - - void xenstore_dm_finished_startup(void); - -- /* `danger' means that this parameter, variable or function refers to -+char *xenstore_read_dom0_driver(const char *key); -+int xenstore_write_dom0_driver(const char *key, const char *str); -+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque); -+ -+int *xenstore_get_domids(int *len); -+ -+/* `danger' means that this parameter, variable or function refers to - * an area of xenstore which is writeable by the guest and thus must - * not be trusted by qemu code. For variables containing xenstore - * paths, `danger' can mean that both the path refers to a -diff --git a/vl.c b/vl.c -index 6d79072..adfa4f6 100644 ---- a/vl.c -+++ b/vl.c -@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; - int win2k_install_hack = 0; - int rtc_td_hack = 0; - int vga_passthrough = 0; -+const char *dom0_input = NULL; - #endif - int usb_enabled = 0; - int smp_cpus = 1; -@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16]; - - #include "xen-vl-extra.c" - -+char *get_time(void) -+{ -+ -+ char buff[128]; -+ char *str; -+ struct timeval tv; -+ -+ gettimeofday(&tv, NULL); -+ str = malloc(256); -+ strftime(buff, 128, "%T", localtime(&tv.tv_sec)); -+ sprintf(str, "%s:%06d", buff, (int)tv.tv_usec); -+ return str; -+} -+ - /***********************************************************/ - /* x86 ISA bus support */ - -@@ -4289,6 +4304,7 @@ enum { - QEMU_OPTION_acpi, - QEMU_OPTION_vcpus, - QEMU_OPTION_vga_passthrough, -+ QEMU_OPTION_dom0_input, - - /* Debug/Expert options: */ - QEMU_OPTION_serial, -@@ -4463,6 +4479,7 @@ static const QEMUOption qemu_options[] = { - { "vncunused", 0, QEMU_OPTION_vncunused }, - { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, - { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, -+ { "dom0-input", 1, QEMU_OPTION_dom0_input }, - #if defined(CONFIG_XEN) && !defined(CONFIG_DM) - { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, - { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5299,6 +5316,9 @@ int main(int argc, char **argv, char **envp) - case QEMU_OPTION_vga_passthrough: - vga_passthrough = 1; - break; -+ case QEMU_OPTION_dom0_input: -+ dom0_input = optarg; -+ break; - case QEMU_OPTION_direct_pci: - direct_pci = optarg; - break; -@@ -6067,6 +6087,9 @@ int main(int argc, char **argv, char **envp) - close(fd); - } - -+ if (dom0_input) -+ dom0_driver_init(dom0_input); -+ - xenstore_dm_finished_startup(); - - #ifndef CONFIG_STUBDOM -diff --git a/xen-hooks.mak b/xen-hooks.mak -index 799f80d..c0212a2 100644 ---- a/xen-hooks.mak -+++ b/xen-hooks.mak -@@ -37,6 +37,8 @@ OBJS += helper2.o - OBJS += battery_mgmt.o - OBJS += xen_acpi_wmi.o - OBJS += thermal_mgmt.o -+OBJS += dom0_driver.o -+OBJS += hid-linux.o - - CONFIG_AUDIO=1 - -diff --git a/xenstore.c b/xenstore.c -index 3cd2ba6..17136a3 100644 ---- a/xenstore.c -+++ b/xenstore.c -@@ -1741,3 +1741,63 @@ void xenstore_dm_finished_startup(void) - free(buf); - free(path); - } -+ -+char *xenstore_read_dom0_driver(const char *key) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int len = 0; -+ char *val = NULL; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return NULL; -+ val = xs_read(xsh, XBT_NULL, buf, &len); -+ free(buf); -+ return val; -+} -+ -+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int ret = 0; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return 0; -+ xenstore_watch_new_callback(buf, fptr, opaque); -+ free(buf); -+ return ret; -+} -+ -+int xenstore_write_dom0_driver(const char *key, const char *str) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int len = 0; -+ int ret = 0; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return 0; -+ ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str)); -+ free(buf); -+ return ret; -+} -+ -+int *xenstore_get_domids(int *len) -+{ -+ int *tab = NULL; -+ char **e; -+ -+ e = xs_directory(xsh, XBT_NULL, "/local/domain", len); -+ if (e == NULL) -+ { -+ len = 0; -+ return NULL; -+ } -+ -+ tab = malloc(*len * sizeof (int)); -+ for (int i = 0; i < *len; i++) -+ tab[i] = strtol(e[i], NULL, 10); -+ return tab; -+} -+ diff --git a/master/fix-drop-mouse-keyboard b/master/fix-drop-mouse-keyboard deleted file mode 100644 index 4b8d5ba..0000000 --- a/master/fix-drop-mouse-keyboard +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/hid-linux.c b/hid-linux.c -index 59dfec8..f2e0bce 100644 ---- a/hid-linux.c -+++ b/hid-linux.c -@@ -47,6 +47,7 @@ - #define ABS(x) ((x) > 0 ? (x) : -(x)) - #define EVENT_PATH "/dev/input/event" - #define HID_LINUX_MAX_DEV 16 -+#define HID_LINUX_MAX_DEV_NO 64 - - #define DEBUG_HID_LINUX - -@@ -447,8 +448,11 @@ void hid_linux_probe(int grab) - - sprintf(path, "%s%i", EVENT_PATH, i++); - -+ if (i>=HID_LINUX_MAX_DEV_NO) -+ break; -+ - if (stat(path, &st) == -1) -- break; -+ continue; - - for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++) - if (!strcmp(hid_linux_driver.controller_paths[c], path)) diff --git a/master/intel b/master/intel index 3896eb3..53f8e6c 100644 --- a/master/intel +++ b/master/intel @@ -1,5 +1,5 @@ diff --git a/console.h b/console.h -index 97214c0..def586a 100644 +index 14b42f3..7f2fdaa 100644 --- a/console.h +++ b/console.h @@ -70,6 +70,8 @@ void kbd_put_keysym(int keysym); @@ -22,39 +22,15 @@ index 97214c0..def586a 100644 int is_graphic_console(void); int is_fixedsize_console(void); CharDriverState *text_console_init(const char *p); -@@ -356,4 +362,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *); - void hid_linux_reset_keyboard(void); - void hid_linux_probe(int grab); +@@ -341,4 +347,8 @@ const char *readline_get_history(unsigned int index); + void readline_start(const char *prompt, int is_password, + ReadLineFunc *readline_func, void *opaque); +/* intel.c */ +int intel_enter(void); +int intel_leave(void); +void intel_display_init(DisplayState *ds); #endif -diff --git a/dom0_driver.c b/dom0_driver.c -index 92f6b17..7f735a9 100644 ---- a/dom0_driver.c -+++ b/dom0_driver.c -@@ -43,6 +43,7 @@ - #include - - extern int vga_passthrough; -+extern int intel; - - static void dom0_driver_state_change(const char *path, void *opaque); - static void dom0_driver_command(const char *path, void *opaque); -@@ -694,6 +695,11 @@ void dom0_driver_init(const char *position) - driver.enter = intel_enter; - driver.leave = intel_leave; - } -+ else if (intel) -+ { -+ driver.enter = intel_enter; -+ driver.leave = intel_leave; -+ } - else - { - driver.enter = dom0_driver_dummy_enter_leave; diff --git a/hw/vga.c b/hw/vga.c index 90bd544..e4e27a9 100644 --- a/hw/vga.c @@ -224,552 +200,50 @@ index 90bd544..e4e27a9 100644 s->graphic_mode = -1; vga_update_display(s); diff --git a/intel.c b/intel.c -new file mode 100644 -index 0000000..46949f6 ---- /dev/null +index 62701cc..d603e89 100644 +--- a/intel.c +++ b/intel.c -@@ -0,0 +1,500 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "qemu-common.h" -+#include "qemu-timer.h" -+#include "console.h" -+#include "sysemu.h" -+ -+#include "intel_reg.h" -+#include "intel.h" -+ -+#define INTEL_DEBUG(format, args...) \ -+ fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args); -+ -+extern int vga_passthrough; -+uint32_t guest_framebuffer; -+int intel_output = INTEL_OUTPUT_BLITTED; -+static int display = 0; -+ -+static int mmio_fd = -1; -+static int mem_fd = -1; -+static uint8_t *intel_mem = NULL; -+static uint8_t *intel_mmio = NULL; -+static int intel_force_full_update = 0; -+static int intel_have_focus; -+static int IntelPitch = 16; -+static int IntelX = 1280; -+static int IntelY = 1024; -+static DisplayState *lds = NULL; -+static uint32_t intel_fb_base, intel_mmio_base; -+static uint32_t map_s, map_d, map_size; -+static int refresh; -+static QEMUTimer *check_linear_timer = NULL; -+ -+static void set_data_pointer(DisplaySurface *surf); -+static void intel_resize(DisplayState *ds); -+ -+static inline unsigned int intel_get_reg(unsigned int reg) -+{ -+ return *(unsigned int*)(intel_mmio + reg); -+} -+ -+static char surfaenabled(void) -+{ -+ return !!(intel_get_reg(REG_DR_DSPACNTR) & (1 << 31)); -+} -+ -+static inline unsigned int intel_get_surface(void) -+{ -+ if (surfaenabled()) -+ return intel_get_reg(REG_DR_DSPASURF); -+ else -+ return intel_get_reg(REG_DR_DSPBSURF); -+} -+ -+static inline void intel_get_res(unsigned int *x, -+ unsigned int *y, -+ unsigned int *pitch) -+{ -+ if (surfaenabled()) -+ { -+ INTEL_DEBUG("Get resolution from PIPEA\n") -+ *pitch = intel_get_reg(REG_DR_DSPASTRIDE); -+ *x = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1; -+ *y = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1; -+ } -+ else -+ { -+ INTEL_DEBUG("Get resolution from PIPEB\n") -+ *pitch = intel_get_reg(REG_DR_DSPBSTRIDE); -+ *x = ((intel_get_reg(REG_DE_PIPEBSRC) >> 16) & 0xfff) + 1; -+ *y = (intel_get_reg(REG_DE_PIPEBSRC) & 0xfff) + 1; -+ } -+} -+ -+ -+ -+static void intel_force_linear(int linesize) -+{ -+ unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR); -+ unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF); -+ unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF); -+ unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE); -+ -+ unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR); -+ unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF); -+ unsigned int *dspbsurf = (unsigned int *)(intel_mmio + REG_DR_DSPBSURF); -+ unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE); -+ volatile unsigned int *fbc_ctl = (unsigned int *)(intel_mmio + REG_FBC_CONTROL); -+ -+ unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0; -+ char pipeaenabled = !!(*pipeaconf & (1 << 30)); -+ char pipebenabled = !!(*pipebconf & (1 << 30)); -+ -+ INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR)); -+ -+ if (pipeaenabled) -+ { -+ INTEL_DEBUG("PIPEACONF enabled.\n"); -+ /* Disable surface */ -+ pipea = *pipeaconf & (0x3 << 18); -+ *pipeaconf &= ~(0x3 << 18); -+ *dspacntr |= (1 << 31); -+ /* Address of the surface to map to */ -+ surfa = *dspasurf; -+ *dspasurf = 0x00000000; -+ *dspacntr &= ~(1 << 31); -+ *dspasurf = 0x00000000; -+ *pipeaconf |= pipea; -+ } -+ -+ if (pipebenabled) { -+ INTEL_DEBUG("PIPEBCONF enabled.\n"); -+ -+ /* Disable surface */ -+ pipeb = *pipebconf & (0x3 << 18); -+ *pipebconf &= ~(0x3 << 18); -+ *dspbcntr |= (1 << 31); -+ /* Address of the surface to map to */ -+ surfb = *dspbsurf; -+ *dspbsurf = 0x00000000; -+ *dspbcntr &= ~(1 << 31); -+ *dspbsurf = 0x00000000; -+ *pipebconf |= pipeb; -+ } -+ -+ usleep(50 * 1000); /* 50 ms */ -+ -+ if (pipeaenabled) -+ { -+ *pipeaconf &= ~(0x3 << 18); -+ /* Enable surface linear mode */ -+ *dspacntr &= ~(1 << 10); -+ if (linesize) *dspastride = linesize; -+ *dspasurf = surfa; -+ *dspacntr |= (1 << 31); -+ *pipeaconf |= pipea; -+ } -+ -+ if (pipebenabled) { -+ *pipebconf &= ~(0x3 << 18); -+ /* Enable surface linear mode */ -+ *dspbcntr &= ~(1 << 10); -+ if (linesize) *dspbstride = linesize; -+ *dspbsurf = surfb; -+ *dspbcntr |= (1 << 31); -+ *pipebconf |= pipeb; -+ } -+ if (linesize) IntelPitch = linesize; -+ -+ usleep(50 * 1000); /* 50 ms */ -+ -+ /* Clear the compression bit */ -+ *fbc_ctl &= ~(1 << 31); -+ /* Wait for the status register */ -+ while (intel_get_reg(REG_FBC_STATUS) & (1 << 31)) -+ ; -+} -+ -+static void set_fb_mapping(void) -+{ -+ DisplaySurface *surf = lds->surface; -+ int rc; -+ unsigned long nr_pfn; -+ -+ intel_output = INTEL_OUTPUT_MAPPED; -+ -+ unset_vga_acc(); -+ INTEL_DEBUG("set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_surface()), guest_framebuffer); -+ nr_pfn = (ds_get_linesize(lds) * ds_get_height(lds)) >> TARGET_PAGE_BITS; -+ -+ rc = xc_domain_memory_mapping(xc_handle, -+ domid, -+ (guest_framebuffer >> TARGET_PAGE_BITS), -+ ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS), -+ nr_pfn, -+ DPCI_ADD_MAPPING); -+ if (rc) { -+ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); -+ return; -+ } -+ memcpy((uint8_t *)(intel_mem + intel_get_surface()), -+ ds_get_data(lds), ds_get_linesize(lds) * ds_get_height(lds)); -+ map_s = ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS); -+ map_d = (guest_framebuffer >> TARGET_PAGE_BITS); -+ map_size = nr_pfn; -+} -+ -+static void unset_fb_mapping(void) -+{ -+ int rc; -+ -+ INTEL_DEBUG("unset_fb_mapping: %x %x\n", map_d, map_s); -+ -+ rc = xc_domain_memory_mapping(xc_handle, -+ domid, -+ map_d, -+ map_s, -+ map_size, -+ DPCI_REMOVE_MAPPING); -+ if (rc) { -+ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); -+ return; -+ } -+ -+ set_vga_acc(); -+ intel_output = INTEL_OUTPUT_BLITTED; -+ memcpy(ds_get_data(lds), -+ (uint8_t *) (intel_mem + intel_get_surface()), -+ ds_get_linesize(lds) * ds_get_height(lds)); -+ map_s = 0; -+ map_d = 0; -+ map_size = 0; -+} -+ -+ -+static void intel_update(DisplayState *ds, int x, int y, int w, int h) -+{ -+ /* do nothing */ -+ int i, bpp = ds_get_bytes_per_pixel(ds); -+ unsigned char *s, *d; -+ -+ if (!intel_have_focus || !is_buffer_shared(ds->surface)) -+ return; -+ -+ if ((x > IntelX || y > IntelY)) -+ return; -+ if ((x + w) > IntelX) -+ w = IntelX - x; -+ if ((y + h) > IntelY) -+ h = IntelY - y; -+ -+ s = ds_get_data(ds); -+ d = (unsigned char *)(intel_mem + intel_get_surface()); -+ /* Center the screen */ -+ if (ds_get_width(ds) < IntelX && ds_get_height(ds) < IntelY) -+ d += IntelPitch * ((IntelY - ds_get_height(ds)) / 2) + -+ 4 * ((IntelX - ds_get_width(ds)) / 2); -+ -+ s += (ds_get_linesize(ds) * y) + bpp * x; -+ d += (IntelPitch * y) + bpp * x; -+ for (i = 0; i < h; i++) { -+ memcpy(d, s, w * bpp); -+ s += ds_get_linesize(ds); -+ d += IntelPitch; -+ } -+} -+ -+static void intel_resize(DisplayState *ds) -+{ -+ INTEL_DEBUG("intel_resize: shared=%d, width=%d, height=%d, depth=%d\n", -+ is_buffer_shared(ds->surface), -+ ds_get_width(ds), -+ ds_get_height(ds), -+ ds_get_bytes_per_pixel(ds)); -+ if (intel_have_focus) -+ { -+ if (ds_get_width(ds) == IntelX && ds_get_height(ds) == IntelY && -+ is_buffer_shared(ds->surface)) -+ { -+ if (!map_size) -+ { -+ intel_force_linear(ds_get_linesize(ds)); -+ set_fb_mapping(); -+ } -+ } -+ else -+ { -+ if (map_size) -+ unset_fb_mapping(); -+ else -+ intel_force_linear(0); -+ } -+ } else { -+ if (map_size) -+ unset_fb_mapping(); -+ } -+} -+ -+static void intel_setdata(DisplayState *ds) -+{ -+ if (!map_size) -+ return; -+ unset_fb_mapping(); -+ set_fb_mapping(); -+} -+ -+static void intel_refresh(DisplayState *ds) -+{ -+ vga_hw_update(); -+} -+ -+static void intel_init_mapping(void) -+{ -+ struct pci_access *pci_bus; -+ struct pci_dev *pci_dev; -+ -+ mmio_fd = open("/dev/mem", O_RDWR); -+ if (mmio_fd == -1) -+ { -+ perror("open"); -+ exit(1); -+ } -+ mem_fd = open("/dev/mem", O_RDWR); -+ if (mem_fd == -1) -+ { -+ perror("open"); -+ exit(1); -+ } -+ -+ pci_bus = pci_alloc(); -+ pci_init(pci_bus); -+ pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0); -+ pci_fill_info(pci_dev, PCI_FILL_BASES); -+ intel_fb_base = pci_dev->base_addr[2] & 0xfffff000; -+ intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000; -+ pci_free_dev(pci_dev); -+ pci_cleanup(pci_bus); -+ -+ INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base); -+ intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED, -+ mem_fd, intel_fb_base); -+ if (intel_mem == MAP_FAILED) -+ { -+ perror("mmap"); -+ exit(1); -+ } -+ -+ INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base); -+ intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, -+ mmio_fd, intel_mmio_base); -+ if (intel_mmio == MAP_FAILED) -+ { -+ perror("mmap"); -+ exit(1); -+ } -+} -+ -+static void set_data_pointer(DisplaySurface *surf) -+{ -+ surf->data = (unsigned char *)(intel_mem + intel_get_surface()); -+ memset(surf->data, 0x00, surf->linesize * IntelY); -+ surf->data = surf->data + -+ surf->linesize * ((IntelY - surf->height) / 2) + -+ 4 * ((IntelX - surf->width) / 2); -+} -+ -+static int intel_getfocus(void) -+{ -+ return intel_have_focus; -+} -+ -+static inline int is_linear(void) -+{ -+ if (surfaenabled()) -+ return (intel_get_reg(REG_DR_DSPACNTR) & (1 << 10)) == 0; -+ else -+ return (intel_get_reg(REG_DR_DSPBCNTR) & (1 << 10)) == 0; -+} -+ -+static void intel_check_linear(void) -+{ -+ if (!check_linear_timer) -+ check_linear_timer = qemu_new_timer(rt_clock, intel_check_linear, NULL); -+ -+ if (intel_have_focus && !is_linear()) -+ { -+ intel_force_linear(0); -+ vga_hw_invalidate(); -+ vga_hw_update(); -+ } -+ -+ if (intel_have_focus) -+ qemu_mod_timer(check_linear_timer, -+ qemu_get_clock(rt_clock) + 4000); -+} -+ -+static void intel_focus(int focus) -+{ -+ if (intel_have_focus == focus) -+ return; -+ -+ intel_have_focus = focus; -+ if (intel_have_focus) { -+ intel_get_res(&IntelX, &IntelY, &IntelPitch); -+ -+ if (!guest_framebuffer) -+ intel_force_linear(0); -+ memset((uint8_t *)(intel_mem + intel_get_surface()), 0, -+ IntelX * IntelY * 4); -+ } -+ vga_hw_invalidate(); -+ vga_hw_update(); -+ intel_check_linear(); -+ -+ INTEL_DEBUG("intel_focus %d, x=%d, y=%d, stride=%d\n", -+ focus, IntelX, IntelY, IntelPitch); -+} -+ -+int intel_enter(void) -+{ -+ intel_focus(1); -+ return 1; -+} -+ -+int intel_leave(void) -+{ -+ intel_focus(0); -+ return 1; -+} -+ -+static DisplaySurface* intel_create_displaysurface(int width, int height) -+{ -+ DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); -+ if (surface == NULL) { -+ fprintf(stderr, "sdl_create_displaysurface: malloc failed\n"); -+ exit(1); -+ } -+ -+ surface->width = width; -+ surface->height = height; -+ -+ INTEL_DEBUG("intel_create_displaysurface: focus=%d %d %d\n", intel_have_focus, width, height); -+ if (intel_have_focus) { -+ surface->pf = qemu_default_pixelformat(32); -+ surface->flags = QEMU_ALLOCATED_FLAG | INTEL_MAPPED_FLAG; -+ surface->linesize = IntelPitch; -+ set_data_pointer(surface); -+ } else { -+ surface->data = qemu_mallocz(width * height * 4); -+ surface->linesize = width * 4; -+ surface->pf = qemu_default_pixelformat(32); -+ surface->flags = QEMU_ALLOCATED_FLAG; -+ } -+ -+ return surface; -+} -+ -+static void intel_free_displaysurface(DisplaySurface *surface) -+{ -+ if (surface == NULL) +@@ -11,6 +11,7 @@ + + #include "qemu-common.h" + #include "qemu-timer.h" ++#include "qemu-xen.h" + #include "console.h" + #include "sysemu.h" + +@@ -405,24 +406,16 @@ static void intel_focus(int focus) + focus, IntelX, IntelY, IntelPitch); + } + +-int intel_enter(void) +-{ +- intel_focus(1); +- return 1; +-} +- +-int intel_leave(void) +-{ +- intel_focus(0); +- return 1; +-} +- +-void intel_enter_leave(const char *path, void *opaque) ++static void intel_enter_leave(const char *path, void *opaque) + { ++ char *tmp; + int state; + int enter = (int)opaque; + +- state = xenstore_dom_read(domid, path, NULL); ++ if (!(tmp = xenstore_dom_read(domid, path, NULL))) + return; -+ if ((!(surface->flags & INTEL_MAPPED_FLAG)) && (surface->flags & QEMU_ALLOCATED_FLAG)) -+ qemu_free(surface->data); -+ qemu_free(surface); -+} -+ -+static DisplaySurface* intel_resize_displaysurface(DisplaySurface *surface, int width, int height) -+{ -+ intel_free_displaysurface(surface); -+ if (map_size) -+ unset_fb_mapping(); -+ return intel_create_displaysurface(width, height); -+} -+ -+void intel_display_init(DisplayState *ds) -+{ -+ DisplayChangeListener *dcl; -+ DisplayAllocator *da; -+ -+ intel_init_mapping(); -+ -+ INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_surface()); -+ -+ dcl = qemu_mallocz(sizeof(DisplayChangeListener)); -+ if (!dcl) -+ exit(1); -+ dcl->dpy_update = intel_update; -+ dcl->dpy_resize = intel_resize; -+ dcl->dpy_setdata = intel_setdata; -+ dcl->dpy_refresh = intel_refresh; -+ register_displaychangelistener(ds, dcl); -+ -+ da = qemu_mallocz(sizeof(DisplayAllocator)); -+ if (!da) -+ exit(1); -+ da->create_displaysurface = intel_create_displaysurface; -+ da->resize_displaysurface = intel_resize_displaysurface; -+ da->free_displaysurface = intel_free_displaysurface; -+ if (register_displayallocator(ds, da) != da) { -+ fprintf(stderr, "intel_display_init: could not register DisplayAllocator\n"); -+ exit(1); -+ } else { -+ DisplaySurface *surf; -+ surf = intel_create_displaysurface(ds_get_width(ds), ds_get_height(ds)); -+ defaultallocator_free_displaysurface(ds->surface); -+ ds->surface = surf; -+ dpy_resize(ds); -+ } -+ -+ lds = ds; -+} -diff --git a/intel.h b/intel.h -new file mode 100644 -index 0000000..25086be ---- /dev/null -+++ b/intel.h -@@ -0,0 +1,5 @@ -+extern int intel_output; -+#define INTEL_OUTPUT_UNDEF 0 -+#define INTEL_OUTPUT_MAPPED 1 -+#define INTEL_OUTPUT_BLITTED 2 -+ -diff --git a/intel_reg.h b/intel_reg.h -new file mode 100644 -index 0000000..cd7855e ---- /dev/null -+++ b/intel_reg.h -@@ -0,0 +1,22 @@ -+ -+#define TileW 128 -+#define TileH 8 -+ -+#define REG_DR_DSPASURF 0x7019C -+#define REG_DR_DSPACNTR 0x70180 -+#define REG_DR_DSPASTRIDE 0x70188 -+#define REG_DR_PIPEACONF 0x70008 -+ -+#define REG_DR_DSPBSURF 0x7119C -+#define REG_DR_DSPBCNTR 0x71180 -+#define REG_DR_DSPBSTRIDE 0x71188 -+#define REG_DR_PIPEBCONF 0x71008 -+ -+#define REG_DE_PIPEASRC 0x6001c -+#define REG_DE_PIPEBSRC 0x6101c -+ -+#define REG_FBC_CONTROL 0x03208 -+#define REG_FBC_STATUS 0x03210 -+ -+ -+ ++ state = strtol(tmp, NULL, 10); ++ free(tmp); + if (state == 1) + { + intel_focus(enter); diff --git a/vl.c b/vl.c -index adfa4f6..a040403 100644 +index 6350384..cf7ad19 100644 --- a/vl.c +++ b/vl.c @@ -235,6 +235,7 @@ int win2k_install_hack = 0; @@ -796,7 +270,7 @@ index adfa4f6..a040403 100644 #if defined(CONFIG_XEN) && !defined(CONFIG_DM) { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5319,6 +5322,9 @@ int main(int argc, char **argv, char **envp) +@@ -5318,6 +5321,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_dom0_input: dom0_input = optarg; break; @@ -806,7 +280,7 @@ index adfa4f6..a040403 100644 case QEMU_OPTION_direct_pci: direct_pci = optarg; break; -@@ -5923,26 +5929,26 @@ int main(int argc, char **argv, char **envp) +@@ -5922,26 +5928,26 @@ int main(int argc, char **argv, char **envp) curses_display_init(ds, full_screen); } else #endif @@ -851,13 +325,13 @@ index adfa4f6..a040403 100644 dpy_resize(ds); diff --git a/xen-hooks.mak b/xen-hooks.mak -index c0212a2..b90967d 100644 +index 1ed197f..88aff50 100644 --- a/xen-hooks.mak +++ b/xen-hooks.mak -@@ -39,6 +39,7 @@ OBJS += xen_acpi_wmi.o +@@ -38,6 +38,7 @@ OBJS += battery_mgmt.o + OBJS += xen_acpi_wmi.o OBJS += thermal_mgmt.o - OBJS += dom0_driver.o - OBJS += hid-linux.o + OBJS += switcher.o +OBJS += intel.o CONFIG_AUDIO=1 diff --git a/master/new-input-code b/master/new-input-code deleted file mode 100644 index 78b384b..0000000 --- a/master/new-input-code +++ /dev/null @@ -1,1030 +0,0 @@ -diff --git a/hid-linux.c b/hid-linux.c -index f2e0bce..a4b0cd6 100644 ---- a/hid-linux.c -+++ b/hid-linux.c -@@ -42,12 +42,11 @@ - #include - #include - #include -+#include - --#define HID_LINUX_XS_PATH "/local/domain/0/hid_linux" -+#define HID_LINUX_ACTIVITY_FILE "/tmp/.qemu.hid-linux.stamp" -+#define HID_LINUX_XS_PATH "/local/domain/0/linux_hid_driver" - #define ABS(x) ((x) > 0 ? (x) : -(x)) --#define EVENT_PATH "/dev/input/event" --#define HID_LINUX_MAX_DEV 16 --#define HID_LINUX_MAX_DEV_NO 64 - - #define DEBUG_HID_LINUX - -@@ -64,468 +63,649 @@ while (0); - # define DEBUG(_format_, args...) (void)0 - #endif - --static struct hid_linux_driver -+ -+#define N_DEVS 64 -+ -+#define HID_TYPE_KEYBOARD 1 -+#define HID_TYPE_MOUSE 2 -+ -+ -+static struct linux_hid_driver - { -- int keyboard_fds[HID_LINUX_MAX_DEV / 2]; -- int mouse_fds[HID_LINUX_MAX_DEV / 2]; -- char *controller_paths[HID_LINUX_MAX_DEV]; -- int mouse_button_state; -- int key_status[256]; -- void (*secure_key)(int ascii); --} hid_linux_driver; -- --struct hid_linux_binding -+ QEMUTimer *scan_timer; -+ int keyboard_grabbed; -+ int mouse_grabbed; -+ int types[N_DEVS]; -+ int fds[N_DEVS]; -+ int mouse_button_state; -+ int key_status[256]; -+ time_t last_activity; -+ void (*secure_key) (int ascii); -+} linux_hid_driver; -+ -+struct linux_hid_binding - { -- int *binding; -- void (*cb)(void *); -- void *payload; -+ int *binding; -+ void (*cb) (void *); -+ void *payload; - }; - --static struct hid_linux_binding *hid_linux_binding = NULL; -+static struct linux_hid_binding *linux_hid_binding = NULL; - --static const int ascii2keycode_table[] = --{ -- KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, -- KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, -- KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z -+static const int ascii2keycode_table[] = { -+ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, -+ KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, -+ KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z - }; - --static char keycode2ascii(int keycode) -+static int hid_linux_detect_binding (void); -+static void hid_linux_key_inject (int code, uint32_t keycode); -+static char *hid_linux_xs_read (const char *key); -+ -+ -+static char -+keycode2ascii (int keycode) - { -- int i = 0; -+ int i = 0; - -- switch (keycode) -+ switch (keycode) - { -- case KEY_ESC: return 27; -- case KEY_BACKSPACE: return 8; -- case KEY_ENTER: return 10; -- case KEY_LEFT: return 17; -- case KEY_RIGHT: return 18; -- case KEY_DELETE: return 127; -- case KEY_HOME: return 2; -- case KEY_END: return 3; -- case KEY_INSERT: return 19; -- case KEY_SPACE: return 20; -- default: -- for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++) -- if (ascii2keycode_table[i] == keycode) -- return i + 'a'; -+ case KEY_ESC: -+ return 27; -+ case KEY_BACKSPACE: -+ return 8; -+ case KEY_ENTER: -+ return 10; -+ case KEY_LEFT: -+ return 17; -+ case KEY_RIGHT: -+ return 18; -+ case KEY_DELETE: -+ return 127; -+ case KEY_HOME: -+ return 2; -+ case KEY_END: -+ return 3; -+ case KEY_INSERT: -+ return 19; -+ case KEY_SPACE: -+ return 20; -+ default: -+ for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++) -+ if (ascii2keycode_table[i] == keycode) -+ return i + 'a'; - } -- return 0; -+ return 0; - } - --static int ascii2keycode(char ascii) -+static int -+ascii2keycode (char ascii) - { -- return ascii2keycode_table[ascii - 'a']; -+ return ascii2keycode_table[ascii - 'a']; - } - --static char *hid_linux_xs_read(const char *key) -+static char * -+hid_linux_xs_read (const char *key) - { -- char *path = NULL; -- char *ret; -- -- if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1) -- return NULL; -- ret = xenstore_read(path); -- free(path); -- return ret; -+ char *path = NULL; -+ char *ret; -+ -+ if (asprintf (&path, HID_LINUX_XS_PATH "/%s", key) == -1) -+ return NULL; -+ ret = xenstore_read (path); -+ free (path); -+ return ret; - } - --void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload) -+void -+hid_linux_add_binding (const int *tab, void (*cb) (void *), void *payload) - { -- int i = 0, j = 0; -- -- for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++) -- ; -- hid_linux_binding = realloc(hid_linux_binding, -- (i + 2) * sizeof (struct hid_linux_binding)); -- hid_linux_binding[i + 1].cb = NULL; -- hid_linux_binding[i].cb = cb; -- hid_linux_binding[i].payload = payload; -- hid_linux_binding[i].binding = NULL; -- -- j = 0; -- do -+ int i = 0, j = 0; -+ -+ for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++) -+ ; -+ linux_hid_binding = realloc (linux_hid_binding, -+ (i + 2) * sizeof (struct linux_hid_binding)); -+ linux_hid_binding[i + 1].cb = NULL; -+ linux_hid_binding[i].cb = cb; -+ linux_hid_binding[i].payload = payload; -+ linux_hid_binding[i].binding = NULL; -+ -+ j = 0; -+ do - { -- hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding, -- (j + 1) * sizeof (int)); -- hid_linux_binding[i].binding[j] = tab[j]; -+ linux_hid_binding[i].binding = realloc (linux_hid_binding[i].binding, -+ (j + 1) * sizeof (int)); -+ linux_hid_binding[i].binding[j] = tab[j]; - } -- while (tab[j++] != -1); -+ while (tab[j++] != -1); - } - --static int hid_linux_detect_binding(void) -+static int -+hid_linux_detect_binding (void) - { -- int i, j; -+ int i, j; - -- for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++) -+ for (i = 0; linux_hid_binding && linux_hid_binding[i].cb; i++) - { -- int *tab = hid_linux_binding[i].binding; -- -- for (j = 0; tab[j] != -1; j++) -- if (hid_linux_driver.key_status[tab[j]] == 0) -- break; -- if (tab[j] != -1) -- continue; -- else /* We match a binding */ -- { -- DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload)); -- hid_linux_binding[i].cb(hid_linux_binding[i].payload); -- hid_linux_reset_keyboard(); -- return 1; -- } -+ int *tab = linux_hid_binding[i].binding; -+ -+ for (j = 0; tab[j] != -1; j++) -+ if (linux_hid_driver.key_status[tab[j]] == 0) -+ break; -+ if (tab[j] != -1) -+ continue; -+ else /* We match a binding */ -+ { -+ DEBUG ("binding payload %d\n", -+ (int) (linux_hid_binding[i].payload)); -+ linux_hid_binding[i].cb (linux_hid_binding[i].payload); -+ hid_linux_reset_keyboard (); -+ return 1; -+ } - } -- return 0; -+ return 0; - } - --static void hid_linux_key_inject(int code, uint32_t keycode) -+static void -+hid_linux_key_inject (int code, uint32_t keycode) - { -- int first = 0; -+ int first = 0; - -- switch (keycode) -+ switch (keycode) - { -- case KEY_F11: keycode = 0X57; break; /* F11 */ -- case KEY_F12: keycode = 0X58; break; /* F12 */ -- case KEY_INSERT: keycode = 0X52; break; -- case KEY_HOME: keycode = 0X47; break; -- case KEY_PAGEUP: keycode = 0X49; break; -- case KEY_DELETE: keycode = 0X53; break; -- case KEY_END: keycode = 0X4F; break; -- case KEY_PAGEDOWN: keycode = 0x51; break; -- case KEY_UP: keycode = 0X48; break; -- case KEY_LEFT: keycode = 0X4B; break; -- case KEY_DOWN: keycode = 0X50; break; -- case KEY_RIGHT: keycode = 0X4D; break; -- case KEY_RIGHTALT: keycode = 0x38; first = 0xe0; break; -- case KEY_LEFTMETA: keycode = 0x5B; first = 0xe0; break; -- case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break; -+ case KEY_F11: -+ keycode = 0X57; -+ break; /* F11 */ -+ case KEY_F12: -+ keycode = 0X58; -+ break; /* F12 */ -+ case KEY_INSERT: -+ keycode = 0X52; -+ break; -+ case KEY_HOME: -+ keycode = 0X47; -+ break; -+ case KEY_PAGEUP: -+ keycode = 0X49; -+ break; -+ case KEY_DELETE: -+ keycode = 0X53; -+ break; -+ case KEY_END: -+ keycode = 0X4F; -+ break; -+ case KEY_PAGEDOWN: -+ keycode = 0x51; -+ break; -+ case KEY_UP: -+ keycode = 0X48; -+ break; -+ case KEY_LEFT: -+ keycode = 0X4B; -+ break; -+ case KEY_DOWN: -+ keycode = 0X50; -+ break; -+ case KEY_RIGHT: -+ keycode = 0X4D; -+ break; -+ case KEY_RIGHTALT: -+ keycode = 0x38; -+ first = 0xe0; -+ break; -+ case KEY_LEFTMETA: -+ keycode = 0x5B; -+ first = 0xe0; -+ break; -+ case KEY_RIGHTMETA: -+ keycode = 0x5C; -+ first = 0xe0; -+ break; -+ case KEY_PROG1: -+ keycode = 0x1; -+ first = 0xe0; -+ break; -+ case KEY_SYSRQ: -+ keycode = 0x37; -+ first = 0xe0; -+ break; -+ case KEY_MUTE: -+ keycode = 0x20; -+ first = 0xe0; -+ break; -+ case KEY_VOLUMEDOWN: -+ keycode = 0x2e; -+ first = 0xe0; -+ break; -+ case KEY_VOLUMEUP: -+ keycode = 0x30; -+ first = 0xe0; -+ break; - } - -- if (first) -- kbd_put_keycode(first); -+ if (first) -+ kbd_put_keycode (first); - -- if (code == 0) -- kbd_put_keycode(keycode | 0x80); -- else -- kbd_put_keycode(keycode & 0x7f); -+ if (code == 0) -+ kbd_put_keycode (keycode | 0x80); -+ else -+ kbd_put_keycode (keycode & 0x7f); - } - -- -- --static void hid_linux_key_event(int code, uint32_t keycode) -+static void -+linux_hid_key_event (int code, uint32_t keycode) - { -- if (code == 1) -- if (hid_linux_detect_binding()) -- return; -- hid_linux_key_inject(code, keycode); -+ int fd; -+ -+ if (code == 1) -+ if (hid_linux_detect_binding ()) -+ return; -+ hid_linux_key_inject (code, keycode); - } - --static void hid_linux_read(void *opaque) -+ -+static int -+hid_linux_read (int fd) - { -- struct input_event event[5]; -- int i = 0; -- int read_sz = 0; -- int fd = *(int *)opaque; -+ struct input_event event[5]; -+ int i = 0; -+ int read_sz = 0; - -- read_sz = read(fd, event, sizeof (event)); -- for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) -+ read_sz = read (fd, event, sizeof (event)); -+ if (read_sz <= 0) -+ return -1; -+ -+ close(creat(HID_LINUX_ACTIVITY_FILE, S_IRUSR | S_IRWXU)); -+ utime(HID_LINUX_ACTIVITY_FILE, NULL); -+ -+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) - { -- if (event[i].type == EV_KEY) -- { -- if (event[i].code >= BTN_MOUSE) -- { -- /* Mouse Key */ -- int type = 0; -- -- switch(event[i].code) -- { -- case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break; -- case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break; -- case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break; -- } -- -- if (event[i].value) -- hid_linux_driver.mouse_button_state |= type; -- else -- hid_linux_driver.mouse_button_state &= ~type; -- kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state); -- } -- else -- { -- hid_linux_driver.key_status[event[i].code] = event[i].value; -- hid_linux_key_event(event[i].value, event[i].code); -- } -- } -- -- if (event[i].type == EV_REL || event[i].type == EV_ABS) -- { -- /* Mouse motion */ -- int x = 0, y = 0, z = 0; -- -- if (event[i].type == EV_REL) -- switch (event[i].code) -- { -- case REL_X : x = event[i].value; break; -- case REL_Y : y = event[i].value; break; -- case REL_WHEEL : z = -event[i].value; break; -- } -- if (event[i].type == EV_ABS) -- { -- static int last_x = 1, last_y = 1; -- int px = 0, py = 0, l = 50; -- double div = 1; -- char *str = NULL; -- -- str = hid_linux_xs_read("touchpad-limit"); -- if (str) -- l = strtol(str, NULL, 10); -- str = hid_linux_xs_read("touchpad-div"); -- if (str) -- div = strtol(str, NULL, 10) / 1000.; -- -- switch (event[i].code) -- { -- case ABS_X : x = event[i].value; break; -- case ABS_Y : y = event[i].value; break; -- } -- -- if (x) -- { -- px = x - last_x; -- last_x = x; -- } -- if (y) -- { -- py = y - last_y; -- last_y = y; -- } -- -- x = (ABS(px) < l ? px : 0) / div; -- y = (ABS(py) < l ? py : 0) / div; -- } -- -- kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state); -- } -+ if (event[i].type == EV_KEY) -+ { -+ if (event[i].code >= BTN_MOUSE) -+ { -+ /* Mouse Key */ -+ int type = 0; -+ -+ switch (event[i].code) -+ { -+ case BTN_LEFT: -+ type = MOUSE_EVENT_LBUTTON; -+ break; -+ case BTN_RIGHT: -+ type = MOUSE_EVENT_RBUTTON; -+ break; -+ case BTN_MIDDLE: -+ type = MOUSE_EVENT_MBUTTON; -+ break; -+ } -+ -+ if (event[i].value) -+ linux_hid_driver.mouse_button_state |= type; -+ else -+ linux_hid_driver.mouse_button_state &= ~type; -+ kbd_mouse_event (0, 0, 0, linux_hid_driver.mouse_button_state); -+ } -+ else -+ { -+ linux_hid_driver.key_status[event[i].code] = event[i].value; -+ linux_hid_key_event (event[i].value, event[i].code); -+ } -+ } -+ -+ if (event[i].type == EV_REL || event[i].type == EV_ABS) -+ { -+ /* Mouse motion */ -+ int x = 0, y = 0, z = 0; -+ -+ if (event[i].type == EV_REL) -+ switch (event[i].code) -+ { -+ case REL_X: -+ x = event[i].value; -+ break; -+ case REL_Y: -+ y = event[i].value; -+ break; -+ case REL_WHEEL: -+ z = -event[i].value; -+ break; -+ } -+ if (event[i].type == EV_ABS) -+ { -+ static int last_x = 1, last_y = 1; -+ int px = 0, py = 0, l = 50; -+ double div = 1; -+ char *str = NULL; -+ -+ str = hid_linux_xs_read ("touchpad-limit"); -+ if (str) -+ l = strtol (str, NULL, 10); -+ str = hid_linux_xs_read ("touchpad-div"); -+ if (str) -+ div = strtol (str, NULL, 10) / 1000.; -+ -+ switch (event[i].code) -+ { -+ case ABS_X: -+ x = event[i].value; -+ break; -+ case ABS_Y: -+ y = event[i].value; -+ break; -+ } -+ -+ if (x) -+ { -+ px = x - last_x; -+ last_x = x; -+ } -+ if (y) -+ { -+ py = y - last_y; -+ last_y = y; -+ } -+ -+ x = (ABS (px) < l ? px : 0) / div; -+ y = (ABS (py) < l ? py : 0) / div; -+ } -+ -+ kbd_mouse_event (x, y, z, linux_hid_driver.mouse_button_state); -+ } - } -+ return 0; - } - --void hid_linux_reset_keyboard(void) -+void -+hid_linux_reset_keyboard (void) - { -- int i = 0; -- -- for (i = 0; i < 256; i++) -- if (hid_linux_driver.key_status[i]) -- { -- hid_linux_key_inject(0, i); -- hid_linux_driver.key_status[i] = 0; -- } -+ int i = 0; -+ -+ for (i = 0; i < 256; i++) -+ if (linux_hid_driver.key_status[i]) -+ { -+ hid_linux_key_inject (0, i); -+ linux_hid_driver.key_status[i] = 0; -+ } - } - - -+static int -+hid_linux_secure_read (int fd) -+{ -+ struct input_event event[5]; -+ int i = 0; -+ int read_sz = 0; -+ -+ assert (linux_hid_driver.secure_key); - --static void hid_linux_redirect_fds(int *fd, IOHandler *cb) -+ read_sz = read (fd, event, sizeof (event)); -+ -+ if (read_sz <= 0) -+ return -1; -+ -+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) -+ if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE && -+ event[i].value > 0) -+ linux_hid_driver.secure_key (keycode2ascii (event[i].code)); -+ -+ return 0; -+} -+ -+ -+ -+static int -+hid_linux_do_read (void *opaque) - { -- assert(fd != NULL); -+ int result; -+ int slot = (int) opaque; -+ -+ if (slot < 0) -+ return 0; -+ if (slot >= N_DEVS) -+ return 0; -+ -+ if (linux_hid_driver.secure_key) -+ result = hid_linux_secure_read (linux_hid_driver.fds[slot]); -+ else -+ result = hid_linux_read (linux_hid_driver.fds[slot]); - -- while (*fd != -1) -+ if (result) - { -- qemu_set_fd_handler(*fd, cb, NULL, fd); -- fd++; -+ /* The read failed - stop watching and close the fd */ -+ -+ fprintf (stderr, -+ "read failed on /dev/input/event%d fd=%d dropping it\n", slot, -+ linux_hid_driver.fds[slot]); -+ -+ qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL); -+ close (linux_hid_driver.fds[slot]); -+ linux_hid_driver.fds[slot] = -1; - } -+ -+ return 0; - } - --static void hid_linux_secure_read(void *opaque) -+ -+void -+hid_linux_secure_keyboard (void (*cb) (int ascii)) - { -- struct input_event event[5]; -- int i = 0; -- int read_sz = 0; -- int fd = *(int *)opaque; -- -- assert(hid_linux_driver.secure_key); -- -- read_sz = read(fd, event, sizeof (event)); -- for (i = 0; i < read_sz / (sizeof (struct input_event)); i++) -- if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE && -- event[i].value > 0) -- hid_linux_driver.secure_key(keycode2ascii(event[i].code)); -+ linux_hid_driver.secure_key = cb; - } - - --void hid_linux_secure_keyboard(void (*cb)(int ascii)) -+ -+static void -+set_handler (int slot, int onoff) - { -- hid_linux_driver.secure_key = cb; -- if (cb) -- hid_linux_redirect_fds(hid_linux_driver.keyboard_fds, -- hid_linux_secure_read); -- else -- hid_linux_redirect_fds(hid_linux_driver.keyboard_fds, -- hid_linux_read); -+ -+ if (onoff) -+ qemu_set_fd_handler (linux_hid_driver.fds[slot], hid_linux_do_read, NULL, -+ (void *) slot); -+ else -+ qemu_set_fd_handler (linux_hid_driver.fds[slot], NULL, NULL, NULL); -+ - } - --static int hid_linux_grab_devices(int grab, int *fd) -+ -+static int -+try_to_grab (int fd, int grab) - { -- int rc = 0; -- int try = 10; -+ int try = 10; - -- assert(fd != NULL && *fd != -1); -- for (; *fd != -1; fd++) -+ while (try--) - { -- while (try--) -- { -- if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1) -- { -- char *er; -- -- if (errno == EBUSY) -- continue; -- er = strerror(errno); -- DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er); -- return 0; -- } -- else -- break; -- } -- assert(try); -- -- DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd); -- -- if (grab) -- qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd); -- else -- qemu_set_fd_handler(*fd, NULL, NULL, fd); -+ char *er; -+ if (!ioctl (fd, EVIOCGRAB, grab)) -+ return 0; -+ -+ if (errno != EBUSY) -+ { -+ er = strerror (errno); -+ DEBUG ("ioctl(%d, EVOCGRAB) failed, %s\n", fd, er); -+ return -1; -+ } -+ -+ /*FIXME -- backoff */ - } -- return 1; -+ -+ return -1; - } - --int hid_linux_grab_keyboard(int grab) -+ -+static int -+do_grab (int type, int grab) - { -- return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds); -+ int i; -+ int fail = 0; -+ -+ for (i = 0; i < N_DEVS; ++i) -+ { -+ if (linux_hid_driver.fds[i] < 0) -+ continue; -+ if (linux_hid_driver.types[i] != type) -+ continue; -+ -+ if (try_to_grab (linux_hid_driver.fds[i], grab)) -+ { -+ fail++; -+ fprintf (stderr, "Failed to grab /dev/input/event%d\n", i); -+ } -+ -+ set_handler (i, grab); -+ -+ } -+ -+ return fail ? 0 : 1; - } - --int hid_linux_grab_mouse(int grab) -+int -+hid_linux_grab_keyboard (int grab) - { -- return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds); -+ linux_hid_driver.keyboard_grabbed = grab; /*So new devices know which mode to be in */ -+ return do_grab (HID_TYPE_KEYBOARD, grab); - } - --static int hid_linux_open_timeout(const char *path, int flags) -+int -+hid_linux_grab_mouse (int grab) - { -- int try = 10; -- int fd = 0; -- -- while (try-- && ((fd = open(path, flags)) == -1)) -- usleep(100000); /* 10 ms */ -- if (try == 0) -- return 0; -- return fd == -1 ? 0 : fd; -+ linux_hid_driver.mouse_grabbed = grab; /*So new devices know which mode to be in */ -+ return do_grab (HID_TYPE_MOUSE, grab); - } - --static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2) -+ -+static int -+consider_device (int slot) - { -- int try = 10; -+ int fd = linux_hid_driver.fds[slot]; - -- while (try-- && ioctl(fd, arg1, arg2) == -1) -- usleep(100000); /* 10 ms */ -- if (try == 0) -- return 0; -- return 1; --} -+ char name[128] = { 0 }; -+ struct input_id id; - --void hid_linux_probe(int grab) --{ -- int i = 0, j = 0, c = 0; -- int fd = -1; -- int keyboard = 0, mouse = 0; -- char path[strlen(EVENT_PATH) + 3]; -- char name[128]; -- int *controllers; -- struct input_id id; -- struct stat st; -- -- while (1) -+ if (ioctl (fd, EVIOCGNAME (sizeof (name)), name) == -1) -+ return -1; -+ if (ioctl (fd, EVIOCGID, &id) == -1) -+ return -1; -+ -+ if (id.bustype != BUS_I8042 && id.bustype != BUS_USB) -+ return -1; -+ -+ name[sizeof (name) - 1] = 0; -+ -+ -+ -+ if (strcasestr (name, "keyboard")) -+ { -+ fprintf (stderr, "/dev/input/event%d added keyboard on fd %d (%s)\n", -+ slot, fd, name); -+ linux_hid_driver.types[slot] = HID_TYPE_KEYBOARD; -+ -+ set_handler (slot, linux_hid_driver.keyboard_grabbed); -+ -+ } -+ else - { -- if (fd != -1) -- close(fd); -+ fprintf (stderr, "/dev/input/event%d added mouse on fd %d (%s)\n", -+ slot, fd, name); -+ linux_hid_driver.types[slot] = HID_TYPE_MOUSE; -+ set_handler (slot, linux_hid_driver.mouse_grabbed); -+ } - -- sprintf(path, "%s%i", EVENT_PATH, i++); - -- if (i>=HID_LINUX_MAX_DEV_NO) -- break; -+ return 0; -+} - -- if (stat(path, &st) == -1) -- continue; - -- for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++) -- if (!strcmp(hid_linux_driver.controller_paths[c], path)) -- break; -- assert(c != HID_LINUX_MAX_DEV); -- if (hid_linux_driver.controller_paths[c]) -- continue; - -- if ((fd = open(path, O_RDONLY)) == -1) -- break; - -- if (ioctl(fd, EVIOCGNAME(128), name) == -1) -- { -- DEBUG("Input get name failed on %s\n", path); -- break; -- } -+static void -+hid_linux_scan (void *opaque) -+{ -+ char name[128]; -+ int i; -+ struct stat s; - -- if (ioctl(fd, EVIOCGID, &id) == -1) -- { -- DEBUG("Input get id failed on %s\n", path); -- continue; -- } -+// fprintf (stderr, "hid_linux_scan()\n"); - -- /* Only get devices on usb and i8042 */ -- if (id.bustype != BUS_I8042 && id.bustype != BUS_USB) -- continue; - -- if (strcasestr(name, "keyboard")) -- { -- DEBUG("Add %s %s as a keyboard, fd=%d, bus=%d\n", path, name, fd, id.bustype); -- controllers = hid_linux_driver.keyboard_fds; -- } -- else -+ for (i = 0; i < N_DEVS; ++i) -+ { -+ -+/* Do We already have this device open and working */ -+ if (linux_hid_driver.fds[i] >= 0) -+ continue; -+ -+ sprintf (name, "/dev/input/event%d", i); -+ -+/* Check to see if we can open it */ -+ linux_hid_driver.fds[i] = open (name, O_RDONLY); -+ if (linux_hid_driver.fds[i] < 0) -+ continue; /* No */ -+ -+/* Switch to NBIO*/ -+ { -+ long arg = 0; -+ arg = fcntl (linux_hid_driver.fds[i], F_GETFL, arg); -+ arg |= O_NONBLOCK; -+ fcntl (linux_hid_driver.fds[i], F_SETFL, arg); -+ } -+ -+/* See if we like it and set up input notify if we do*/ -+ if (consider_device (i)) - { -- DEBUG("Add %s %s as a mouse, fd=%d, bus=%d\n", path, name, fd, id.bustype); -- controllers = hid_linux_driver.mouse_fds; -+ close (linux_hid_driver.fds[i]); -+ linux_hid_driver.fds[i] = -1; -+ continue; - } - -- for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++) -- ; -- assert(j != (HID_LINUX_MAX_DEV / 2)); -+ } - -- controllers[j] = fd; -- controllers[j + 1] = -1; -+/* Check the activity file */ -+ if (!linux_hid_driver.mouse_grabbed) -+ { -+ if (stat(HID_LINUX_ACTIVITY_FILE, &s) == -1) -+ { -+ fprintf (stderr, "cannot stat %s\n", HID_LINUX_ACTIVITY_FILE); -+ return; -+ } -+ if (linux_hid_driver.last_activity && -+ s.st_mtime > linux_hid_driver.last_activity) -+ { -+ /* simulated a key press (down and up) on LEFTCTRL */ -+ linux_hid_key_event(1, KEY_LEFTCTRL); -+ linux_hid_key_event(0, KEY_LEFTCTRL); -+ } -+ linux_hid_driver.last_activity = s.st_mtime; -+ } - -- if (grab) -- { -- if (!hid_linux_grab_devices(1, controllers + j)) -- { -- DEBUG("Grabing failed, try next time...\n"); -- controllers[j] = -1; -- break; -- } -- } -+/* Kick off the periodic scan for devices */ -+ if (!linux_hid_driver.scan_timer) -+ linux_hid_driver.scan_timer = -+ qemu_new_timer (rt_clock, hid_linux_scan, NULL); - -- hid_linux_driver.controller_paths[c] = strdup(path); -- hid_linux_driver.controller_paths[c + 1] = NULL; -+/* Schedule ourselves */ -+ qemu_mod_timer (linux_hid_driver.scan_timer, -+ qemu_get_clock (rt_clock) + 4000); - -- fd = -1; -- } -- if (fd != -1) -- close(fd); - } - --void hid_linux_init(void) -+ -+void -+hid_linux_probe (int grab) - { -- hid_linux_driver.keyboard_fds[0] = -1; -- hid_linux_driver.mouse_fds[0] = -1; -- hid_linux_driver.controller_paths[0] = NULL; -+ hid_linux_scan (NULL); -+} - -- while (hid_linux_driver.keyboard_fds[0] == -1) -- { -- hid_linux_probe(0); -- usleep(100000); /* 10 ms */ -- } -+ -+void -+hid_linux_init (void) -+{ -+ int i; -+ for (i = 0; i < N_DEVS; ++i) -+ linux_hid_driver.fds[i] = -1; -+ linux_hid_driver.keyboard_grabbed = 0; -+ linux_hid_driver.mouse_grabbed = 0; -+ linux_hid_driver.last_activity = 0; -+ hid_linux_scan (NULL); - } diff --git a/master/series b/master/series index 73ebb45..0131808 100644 --- a/master/series +++ b/master/series @@ -18,11 +18,9 @@ thermal-management vga-passthrough -dom0-driver +switcher intel -fix-drop-mouse-keyboard fix-imobile-mouse -new-input-code atapi-pass-through pv_driver_throttling_disabled diff --git a/master/switcher b/master/switcher new file mode 100644 index 0000000..cdadd98 --- /dev/null +++ b/master/switcher @@ -0,0 +1,921 @@ +diff --git a/intel.c b/intel.c +new file mode 100644 +index 0000000..62701cc +--- /dev/null ++++ b/intel.c +@@ -0,0 +1,515 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qemu-common.h" ++#include "qemu-timer.h" ++#include "console.h" ++#include "sysemu.h" ++ ++#include "intel_reg.h" ++#include "intel.h" ++ ++#define INTEL_DEBUG(format, args...) \ ++ fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args); ++ ++extern int vga_passthrough; ++uint32_t guest_framebuffer; ++int intel_output = INTEL_OUTPUT_BLITTED; ++static int display = 0; ++ ++static int mmio_fd = -1; ++static int mem_fd = -1; ++static uint8_t *intel_mem = NULL; ++static uint8_t *intel_mmio = NULL; ++static int intel_force_full_update = 0; ++static int intel_have_focus; ++static int IntelPitch = 16; ++static int IntelX = 1280; ++static int IntelY = 1024; ++static DisplayState *lds = NULL; ++static uint32_t intel_fb_base, intel_mmio_base; ++static uint32_t map_s, map_d, map_size; ++static int refresh; ++static QEMUTimer *check_linear_timer = NULL; ++ ++static void set_data_pointer(DisplaySurface *surf); ++static void intel_resize(DisplayState *ds); ++ ++static inline unsigned int intel_get_reg(unsigned int reg) ++{ ++ return *(unsigned int*)(intel_mmio + reg); ++} ++ ++static char surfaenabled(void) ++{ ++ return !!(intel_get_reg(REG_DR_DSPACNTR) & (1 << 31)); ++} ++ ++static inline unsigned int intel_get_surface(void) ++{ ++ if (surfaenabled()) ++ return intel_get_reg(REG_DR_DSPASURF); ++ else ++ return intel_get_reg(REG_DR_DSPBSURF); ++} ++ ++static inline void intel_get_res(unsigned int *x, ++ unsigned int *y, ++ unsigned int *pitch) ++{ ++ if (surfaenabled()) ++ { ++ INTEL_DEBUG("Get resolution from PIPEA\n") ++ *pitch = intel_get_reg(REG_DR_DSPASTRIDE); ++ *x = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1; ++ *y = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1; ++ } ++ else ++ { ++ INTEL_DEBUG("Get resolution from PIPEB\n") ++ *pitch = intel_get_reg(REG_DR_DSPBSTRIDE); ++ *x = ((intel_get_reg(REG_DE_PIPEBSRC) >> 16) & 0xfff) + 1; ++ *y = (intel_get_reg(REG_DE_PIPEBSRC) & 0xfff) + 1; ++ } ++} ++ ++ ++ ++static void intel_force_linear(int linesize) ++{ ++ unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR); ++ unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF); ++ unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF); ++ unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE); ++ ++ unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR); ++ unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF); ++ unsigned int *dspbsurf = (unsigned int *)(intel_mmio + REG_DR_DSPBSURF); ++ unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE); ++ volatile unsigned int *fbc_ctl = (unsigned int *)(intel_mmio + REG_FBC_CONTROL); ++ ++ unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0; ++ char pipeaenabled = !!(*pipeaconf & (1 << 30)); ++ char pipebenabled = !!(*pipebconf & (1 << 30)); ++ ++ INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR)); ++ ++ if (pipeaenabled) ++ { ++ INTEL_DEBUG("PIPEACONF enabled.\n"); ++ /* Disable surface */ ++ pipea = *pipeaconf & (0x3 << 18); ++ *pipeaconf &= ~(0x3 << 18); ++ *dspacntr |= (1 << 31); ++ /* Address of the surface to map to */ ++ surfa = *dspasurf; ++ *dspasurf = 0x00000000; ++ *dspacntr &= ~(1 << 31); ++ *dspasurf = 0x00000000; ++ *pipeaconf |= pipea; ++ } ++ ++ if (pipebenabled) { ++ INTEL_DEBUG("PIPEBCONF enabled.\n"); ++ ++ /* Disable surface */ ++ pipeb = *pipebconf & (0x3 << 18); ++ *pipebconf &= ~(0x3 << 18); ++ *dspbcntr |= (1 << 31); ++ /* Address of the surface to map to */ ++ surfb = *dspbsurf; ++ *dspbsurf = 0x00000000; ++ *dspbcntr &= ~(1 << 31); ++ *dspbsurf = 0x00000000; ++ *pipebconf |= pipeb; ++ } ++ ++ usleep(50 * 1000); /* 50 ms */ ++ ++ if (pipeaenabled) ++ { ++ *pipeaconf &= ~(0x3 << 18); ++ /* Enable surface linear mode */ ++ *dspacntr &= ~(1 << 10); ++ if (linesize) *dspastride = linesize; ++ *dspasurf = surfa; ++ *dspacntr |= (1 << 31); ++ *pipeaconf |= pipea; ++ } ++ ++ if (pipebenabled) { ++ *pipebconf &= ~(0x3 << 18); ++ /* Enable surface linear mode */ ++ *dspbcntr &= ~(1 << 10); ++ if (linesize) *dspbstride = linesize; ++ *dspbsurf = surfb; ++ *dspbcntr |= (1 << 31); ++ *pipebconf |= pipeb; ++ } ++ if (linesize) IntelPitch = linesize; ++ ++ usleep(50 * 1000); /* 50 ms */ ++ ++ /* Clear the compression bit */ ++ *fbc_ctl &= ~(1 << 31); ++ /* Wait for the status register */ ++ while (intel_get_reg(REG_FBC_STATUS) & (1 << 31)) ++ ; ++} ++ ++static void set_fb_mapping(void) ++{ ++ DisplaySurface *surf = lds->surface; ++ int rc; ++ unsigned long nr_pfn; ++ ++ intel_output = INTEL_OUTPUT_MAPPED; ++ ++ unset_vga_acc(); ++ INTEL_DEBUG("set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_surface()), guest_framebuffer); ++ nr_pfn = (ds_get_linesize(lds) * ds_get_height(lds)) >> TARGET_PAGE_BITS; ++ ++ rc = xc_domain_memory_mapping(xc_handle, ++ domid, ++ (guest_framebuffer >> TARGET_PAGE_BITS), ++ ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS), ++ nr_pfn, ++ DPCI_ADD_MAPPING); ++ if (rc) { ++ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); ++ return; ++ } ++ memcpy((uint8_t *)(intel_mem + intel_get_surface()), ++ ds_get_data(lds), ds_get_linesize(lds) * ds_get_height(lds)); ++ map_s = ((intel_fb_base + intel_get_surface()) >> TARGET_PAGE_BITS); ++ map_d = (guest_framebuffer >> TARGET_PAGE_BITS); ++ map_size = nr_pfn; ++} ++ ++static void unset_fb_mapping(void) ++{ ++ int rc; ++ ++ INTEL_DEBUG("unset_fb_mapping: %x %x\n", map_d, map_s); ++ ++ rc = xc_domain_memory_mapping(xc_handle, ++ domid, ++ map_d, ++ map_s, ++ map_size, ++ DPCI_REMOVE_MAPPING); ++ if (rc) { ++ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); ++ return; ++ } ++ ++ set_vga_acc(); ++ intel_output = INTEL_OUTPUT_BLITTED; ++ memcpy(ds_get_data(lds), ++ (uint8_t *) (intel_mem + intel_get_surface()), ++ ds_get_linesize(lds) * ds_get_height(lds)); ++ map_s = 0; ++ map_d = 0; ++ map_size = 0; ++} ++ ++ ++static void intel_update(DisplayState *ds, int x, int y, int w, int h) ++{ ++ /* do nothing */ ++ int i, bpp = ds_get_bytes_per_pixel(ds); ++ unsigned char *s, *d; ++ ++ if (!intel_have_focus || !is_buffer_shared(ds->surface)) ++ return; ++ ++ if ((x > IntelX || y > IntelY)) ++ return; ++ if ((x + w) > IntelX) ++ w = IntelX - x; ++ if ((y + h) > IntelY) ++ h = IntelY - y; ++ ++ s = ds_get_data(ds); ++ d = (unsigned char *)(intel_mem + intel_get_surface()); ++ /* Center the screen */ ++ if (ds_get_width(ds) < IntelX && ds_get_height(ds) < IntelY) ++ d += IntelPitch * ((IntelY - ds_get_height(ds)) / 2) + ++ 4 * ((IntelX - ds_get_width(ds)) / 2); ++ ++ s += (ds_get_linesize(ds) * y) + bpp * x; ++ d += (IntelPitch * y) + bpp * x; ++ for (i = 0; i < h; i++) { ++ memcpy(d, s, w * bpp); ++ s += ds_get_linesize(ds); ++ d += IntelPitch; ++ } ++} ++ ++static void intel_resize(DisplayState *ds) ++{ ++ INTEL_DEBUG("intel_resize: shared=%d, width=%d, height=%d, depth=%d\n", ++ is_buffer_shared(ds->surface), ++ ds_get_width(ds), ++ ds_get_height(ds), ++ ds_get_bytes_per_pixel(ds)); ++ if (intel_have_focus) ++ { ++ if (ds_get_width(ds) == IntelX && ds_get_height(ds) == IntelY && ++ is_buffer_shared(ds->surface)) ++ { ++ if (!map_size) ++ { ++ intel_force_linear(ds_get_linesize(ds)); ++ set_fb_mapping(); ++ } ++ } ++ else ++ { ++ if (map_size) ++ unset_fb_mapping(); ++ else ++ intel_force_linear(0); ++ } ++ } else { ++ if (map_size) ++ unset_fb_mapping(); ++ } ++} ++ ++static void intel_setdata(DisplayState *ds) ++{ ++ if (!map_size) ++ return; ++ unset_fb_mapping(); ++ set_fb_mapping(); ++} ++ ++static void intel_refresh(DisplayState *ds) ++{ ++ vga_hw_update(); ++} ++ ++static void intel_init_mapping(void) ++{ ++ struct pci_access *pci_bus; ++ struct pci_dev *pci_dev; ++ ++ mmio_fd = open("/dev/mem", O_RDWR); ++ if (mmio_fd == -1) ++ { ++ perror("open"); ++ exit(1); ++ } ++ mem_fd = open("/dev/mem", O_RDWR); ++ if (mem_fd == -1) ++ { ++ perror("open"); ++ exit(1); ++ } ++ ++ pci_bus = pci_alloc(); ++ pci_init(pci_bus); ++ pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0); ++ pci_fill_info(pci_dev, PCI_FILL_BASES); ++ intel_fb_base = pci_dev->base_addr[2] & 0xfffff000; ++ intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000; ++ pci_free_dev(pci_dev); ++ pci_cleanup(pci_bus); ++ ++ INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base); ++ intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED, ++ mem_fd, intel_fb_base); ++ if (intel_mem == MAP_FAILED) ++ { ++ perror("mmap"); ++ exit(1); ++ } ++ ++ INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base); ++ intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, ++ mmio_fd, intel_mmio_base); ++ if (intel_mmio == MAP_FAILED) ++ { ++ perror("mmap"); ++ exit(1); ++ } ++} ++ ++static void set_data_pointer(DisplaySurface *surf) ++{ ++ surf->data = (unsigned char *)(intel_mem + intel_get_surface()); ++ memset(surf->data, 0x00, surf->linesize * IntelY); ++ surf->data = surf->data + ++ surf->linesize * ((IntelY - surf->height) / 2) + ++ 4 * ((IntelX - surf->width) / 2); ++} ++ ++static int intel_getfocus(void) ++{ ++ return intel_have_focus; ++} ++ ++static inline int is_linear(void) ++{ ++ if (surfaenabled()) ++ return (intel_get_reg(REG_DR_DSPACNTR) & (1 << 10)) == 0; ++ else ++ return (intel_get_reg(REG_DR_DSPBCNTR) & (1 << 10)) == 0; ++} ++ ++static void intel_check_linear(void) ++{ ++ if (!check_linear_timer) ++ check_linear_timer = qemu_new_timer(rt_clock, intel_check_linear, NULL); ++ ++ if (intel_have_focus && !is_linear()) ++ { ++ intel_force_linear(0); ++ vga_hw_invalidate(); ++ vga_hw_update(); ++ } ++ ++ if (intel_have_focus) ++ qemu_mod_timer(check_linear_timer, ++ qemu_get_clock(rt_clock) + 4000); ++} ++ ++static void intel_focus(int focus) ++{ ++ if (intel_have_focus == focus) ++ return; ++ ++ intel_have_focus = focus; ++ if (intel_have_focus) { ++ intel_get_res(&IntelX, &IntelY, &IntelPitch); ++ ++ if (!guest_framebuffer) ++ intel_force_linear(0); ++ memset((uint8_t *)(intel_mem + intel_get_surface()), 0, ++ IntelX * IntelY * 4); ++ } ++ vga_hw_invalidate(); ++ vga_hw_update(); ++ intel_check_linear(); ++ ++ INTEL_DEBUG("intel_focus %d, x=%d, y=%d, stride=%d\n", ++ focus, IntelX, IntelY, IntelPitch); ++} ++ ++int intel_enter(void) ++{ ++ intel_focus(1); ++ return 1; ++} ++ ++int intel_leave(void) ++{ ++ intel_focus(0); ++ return 1; ++} ++ ++void intel_enter_leave(const char *path, void *opaque) ++{ ++ int state; ++ int enter = (int)opaque; ++ ++ state = xenstore_dom_read(domid, path, NULL); ++ if (state == 1) ++ { ++ intel_focus(enter); ++ xenstore_dom_write(domid, path, "2"); ++ } ++} ++ ++static DisplaySurface* intel_create_displaysurface(int width, int height) ++{ ++ DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); ++ if (surface == NULL) { ++ fprintf(stderr, "sdl_create_displaysurface: malloc failed\n"); ++ exit(1); ++ } ++ ++ surface->width = width; ++ surface->height = height; ++ ++ INTEL_DEBUG("intel_create_displaysurface: focus=%d %d %d\n", intel_have_focus, width, height); ++ if (intel_have_focus) { ++ surface->pf = qemu_default_pixelformat(32); ++ surface->flags = QEMU_ALLOCATED_FLAG | INTEL_MAPPED_FLAG; ++ surface->linesize = IntelPitch; ++ set_data_pointer(surface); ++ } else { ++ surface->data = qemu_mallocz(width * height * 4); ++ surface->linesize = width * 4; ++ surface->pf = qemu_default_pixelformat(32); ++ surface->flags = QEMU_ALLOCATED_FLAG; ++ } ++ ++ return surface; ++} ++ ++static void intel_free_displaysurface(DisplaySurface *surface) ++{ ++ if (surface == NULL) ++ return; ++ if ((!(surface->flags & INTEL_MAPPED_FLAG)) && (surface->flags & QEMU_ALLOCATED_FLAG)) ++ qemu_free(surface->data); ++ qemu_free(surface); ++} ++ ++static DisplaySurface* intel_resize_displaysurface(DisplaySurface *surface, int width, int height) ++{ ++ intel_free_displaysurface(surface); ++ if (map_size) ++ unset_fb_mapping(); ++ return intel_create_displaysurface(width, height); ++} ++ ++void intel_display_init(DisplayState *ds) ++{ ++ DisplayChangeListener *dcl; ++ DisplayAllocator *da; ++ ++ intel_init_mapping(); ++ ++ INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_surface()); ++ ++ dcl = qemu_mallocz(sizeof(DisplayChangeListener)); ++ if (!dcl) ++ exit(1); ++ dcl->dpy_update = intel_update; ++ dcl->dpy_resize = intel_resize; ++ dcl->dpy_setdata = intel_setdata; ++ dcl->dpy_refresh = intel_refresh; ++ register_displaychangelistener(ds, dcl); ++ ++ da = qemu_mallocz(sizeof(DisplayAllocator)); ++ if (!da) ++ exit(1); ++ da->create_displaysurface = intel_create_displaysurface; ++ da->resize_displaysurface = intel_resize_displaysurface; ++ da->free_displaysurface = intel_free_displaysurface; ++ if (register_displayallocator(ds, da) != da) { ++ fprintf(stderr, "intel_display_init: could not register DisplayAllocator\n"); ++ exit(1); ++ } else { ++ DisplaySurface *surf; ++ surf = intel_create_displaysurface(ds_get_width(ds), ds_get_height(ds)); ++ defaultallocator_free_displaysurface(ds->surface); ++ ds->surface = surf; ++ dpy_resize(ds); ++ } ++ ++ xenstore_dom_watch(domid, "switcher/enter", intel_enter_leave, (void*)0); ++ xenstore_dom_watch(domid, "switcher/leave", intel_enter_leave, (void*)1); ++ lds = ds; ++} +diff --git a/intel.h b/intel.h +new file mode 100644 +index 0000000..25086be +--- /dev/null ++++ b/intel.h +@@ -0,0 +1,5 @@ ++extern int intel_output; ++#define INTEL_OUTPUT_UNDEF 0 ++#define INTEL_OUTPUT_MAPPED 1 ++#define INTEL_OUTPUT_BLITTED 2 ++ +diff --git a/intel_reg.h b/intel_reg.h +new file mode 100644 +index 0000000..cd7855e +--- /dev/null ++++ b/intel_reg.h +@@ -0,0 +1,22 @@ ++ ++#define TileW 128 ++#define TileH 8 ++ ++#define REG_DR_DSPASURF 0x7019C ++#define REG_DR_DSPACNTR 0x70180 ++#define REG_DR_DSPASTRIDE 0x70188 ++#define REG_DR_PIPEACONF 0x70008 ++ ++#define REG_DR_DSPBSURF 0x7119C ++#define REG_DR_DSPBCNTR 0x71180 ++#define REG_DR_DSPBSTRIDE 0x71188 ++#define REG_DR_PIPEBCONF 0x71008 ++ ++#define REG_DE_PIPEASRC 0x6001c ++#define REG_DE_PIPEBSRC 0x6101c ++ ++#define REG_FBC_CONTROL 0x03208 ++#define REG_FBC_STATUS 0x03210 ++ ++ ++ +diff --git a/qemu-xen.h b/qemu-xen.h +index 7883718..0b6214c 100644 +--- a/qemu-xen.h ++++ b/qemu-xen.h +@@ -148,4 +148,6 @@ int has_tpm_device_danger(void); + static void vga_dirty_log_start(void *s) { } + static void vga_dirty_log_stop(void *s) { } + ++void switcher_init(const char *); ++ + #endif /*QEMU_XEN_H*/ +diff --git a/switcher.c b/switcher.c +new file mode 100644 +index 0000000..f352d08 +--- /dev/null ++++ b/switcher.c +@@ -0,0 +1,263 @@ ++/* ++ * QEMU dom0_driver ++ * ++ * Copyright (c) 2009 Citrix Systems ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu-common.h" ++#include "console.h" ++#include "qemu-timer.h" ++#include "qemu-xen.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int vga_passthrough; ++ ++#define DOM0_INPUT_NONE 'N' ++#define DOM0_INPUT_DONE 'D' ++#define DOM0_INPUT_DOMID 'I' ++#define DOM0_INPUT_OPT 'O' ++ ++#define DOM0_INPUT_SOCKET "/tmp/input.socket" ++ ++static int s; ++static struct sockaddr_un remote; ++static int slot; ++ ++static int switcher_init_socket(void); ++ ++static void switcher_key_inject (int code, uint32_t keycode) ++{ ++ int first = 0; ++ ++ switch (keycode) ++ { ++ case KEY_F11: ++ keycode = 0X57; ++ break; /* F11 */ ++ case KEY_F12: ++ keycode = 0X58; ++ break; /* F12 */ ++ case KEY_INSERT: ++ keycode = 0X52; ++ break; ++ case KEY_HOME: ++ keycode = 0X47; ++ break; ++ case KEY_PAGEUP: ++ keycode = 0X49; ++ break; ++ case KEY_DELETE: ++ keycode = 0X53; ++ break; ++ case KEY_END: ++ keycode = 0X4F; ++ break; ++ case KEY_PAGEDOWN: ++ keycode = 0x51; ++ break; ++ case KEY_UP: ++ keycode = 0X48; ++ break; ++ case KEY_LEFT: ++ keycode = 0X4B; ++ break; ++ case KEY_DOWN: ++ keycode = 0X50; ++ break; ++ case KEY_RIGHT: ++ keycode = 0X4D; ++ break; ++ case KEY_RIGHTALT: ++ keycode = 0x38; ++ first = 0xe0; ++ break; ++ case KEY_LEFTMETA: ++ keycode = 0x5B; ++ first = 0xe0; ++ break; ++ case KEY_RIGHTMETA: ++ keycode = 0x5C; ++ first = 0xe0; ++ break; ++ } ++ ++ if (first) ++ kbd_put_keycode (first); ++ ++ if (code == 0) ++ kbd_put_keycode (keycode | 0x80); ++ else ++ kbd_put_keycode (keycode & 0x7f); ++} ++ ++ ++static void switcher_event(struct input_event *e) ++{ ++ static int mouse_button_state = 0; ++ ++ if (e->type == EV_KEY) ++ { ++ if (e->code >= BTN_MOUSE) ++ { ++ int type = 0; ++ ++ switch (e->code) ++ { ++ case BTN_LEFT: ++ type = MOUSE_EVENT_LBUTTON; ++ break; ++ case BTN_RIGHT: ++ type = MOUSE_EVENT_RBUTTON; ++ break; ++ case BTN_MIDDLE: ++ type = MOUSE_EVENT_MBUTTON; ++ break; ++ } ++ ++ if (e->value) ++ mouse_button_state |= type; ++ else ++ mouse_button_state &= ~type; ++ kbd_mouse_event (0, 0, 0, mouse_button_state); ++ } ++ else ++ switcher_key_inject(e->value, e->code); ++ } ++ ++ if (e->type == EV_REL || e->type == EV_ABS) ++ { ++ /* Mouse motion */ ++ int x = 0, y = 0, z = 0; ++ if (e->type == EV_REL) ++ switch (e->code) ++ { ++ case REL_X: ++ x = e->value; ++ break; ++ case REL_Y: ++ y = e->value; ++ break; ++ case REL_WHEEL: ++ z = -e->value; ++ break; ++ } ++ kbd_mouse_event (x, y, z, mouse_button_state); ++ } ++} ++ ++static void switcher_send(const char *format, ...) ++{ ++ char buff[128]; ++ va_list arg; ++ ++ va_start(arg, format); ++ vsnprintf(buff, 128, format, arg); ++ va_end(arg); ++ ++ fprintf(stderr, "send: %s\n", buff); ++ send(s, buff, strlen(buff), 0); ++} ++ ++static void switcher_recv(void *opaque) ++{ ++ static int left_over = 0; ++ static int read_sz = 0; ++ static char buff[128]; ++ static char *p = buff; ++ struct input_event *e = NULL; ++ int ret; ++ ++ memmove(buff, p, left_over); ++ if ((read_sz = recv(s, buff + left_over, 128, 0)) <= 0) ++ { ++ do ++ { ++ fprintf(stderr, "Trying to reconnect ...\n"); ++ if (switcher_init_socket()) ++ return; ++ ret = errno; ++ sleep(1); ++ } ++ while (ret == EAGAIN); ++ } ++ read_sz += left_over; ++ left_over = 0; ++ p = buff; ++ ++ while (left_over == 0 && p - buff < read_sz) ++ { ++ if ((p - buff) + (int)sizeof (struct input_event) > read_sz) ++ { ++ left_over = read_sz - (p - buff); ++ break; ++ } ++ e = (struct input_event *)p; ++ p += sizeof (struct input_event); ++ switcher_event(e); ++ } ++} ++ ++static int switcher_init_socket(void) ++{ ++ struct stat st; ++ ++ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) ++ { ++ fprintf(stderr, "switcher: socket %s\n", strerror(errno)); ++ errno = EAGAIN; ++ return 0; ++ } ++ ++ memset(&remote, 0, sizeof (remote)); ++ remote.sun_family = AF_UNIX; ++ strcpy(remote.sun_path, DOM0_INPUT_SOCKET); ++ if (connect(s, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1) ++ { ++ fprintf(stderr, "switcher: connect %s, %s\n", strerror(errno), remote.sun_path); ++ errno = EAGAIN; ++ return 0; ++ } ++ ++ switcher_send("%c%d", DOM0_INPUT_DOMID, domid); ++ if (vga_passthrough) ++ switcher_send("%c%d", DOM0_INPUT_OPT, 1); ++ ++ qemu_set_fd_handler(s, switcher_recv, NULL, NULL); ++ return 1; ++} ++ ++void switcher_init(const char *str_slot) ++{ ++ slot = strtol(str_slot, NULL, 10); ++ fprintf(stderr, "switcher_init: slot %d\n", slot); ++ xenstore_dom_write(domid, "switcher/slot", str_slot); ++ switcher_init_socket(); ++} +diff --git a/vl.c b/vl.c +index a4b8bd8..6350384 100644 +--- a/vl.c ++++ b/vl.c +@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; + int win2k_install_hack = 0; + int rtc_td_hack = 0; + int vga_passthrough = 0; ++const char *dom0_input = NULL; + #endif + int usb_enabled = 0; + int smp_cpus = 1; +@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16]; + + #include "xen-vl-extra.c" + ++char *get_time(void) ++{ ++ ++ char buff[128]; ++ char *str; ++ struct timeval tv; ++ ++ gettimeofday(&tv, NULL); ++ str = malloc(256); ++ strftime(buff, 128, "%T", localtime(&tv.tv_sec)); ++ sprintf(str, "%s:%06d", buff, (int)tv.tv_usec); ++ return str; ++} ++ + /***********************************************************/ + /* x86 ISA bus support */ + +@@ -4289,6 +4304,7 @@ enum { + QEMU_OPTION_acpi, + QEMU_OPTION_vcpus, + QEMU_OPTION_vga_passthrough, ++ QEMU_OPTION_dom0_input, + + /* Debug/Expert options: */ + QEMU_OPTION_serial, +@@ -4463,6 +4479,7 @@ static const QEMUOption qemu_options[] = { + { "vncunused", 0, QEMU_OPTION_vncunused }, + { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, + { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, ++ { "dom0-input", 1, QEMU_OPTION_dom0_input }, + #if defined(CONFIG_XEN) && !defined(CONFIG_DM) + { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, + { "xen-create", 0, QEMU_OPTION_xen_create }, +@@ -5298,6 +5315,9 @@ int main(int argc, char **argv, char **envp) + cirrus_vga_enabled = 0; + vmsvga_enabled = 0; + break; ++ case QEMU_OPTION_dom0_input: ++ dom0_input = optarg; ++ break; + case QEMU_OPTION_direct_pci: + direct_pci = optarg; + break; +@@ -6066,6 +6086,9 @@ int main(int argc, char **argv, char **envp) + close(fd); + } + ++ if (dom0_input) ++ switcher_init(dom0_input); ++ + xenstore_dm_finished_startup(); + + #ifndef CONFIG_STUBDOM +diff --git a/xen-hooks.mak b/xen-hooks.mak +index 23f2bb7..1ed197f 100644 +--- a/xen-hooks.mak ++++ b/xen-hooks.mak +@@ -37,6 +37,7 @@ OBJS += helper2.o + OBJS += battery_mgmt.o + OBJS += xen_acpi_wmi.o + OBJS += thermal_mgmt.o ++OBJS += switcher.o + + CONFIG_AUDIO=1 +