#include "qemu-common.h"
#include "console.h"
#include "qemu-timer.h"
+#include "qemu-xen.h"
#include <sys/types.h>
#include <linux/input.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
+#include <time.h>
extern int vga_passthrough;
-void xenstore_watch_dom0_driver(const char *, const char *);
+static void dom0_driver_state_change(const char *path, void *opaque);
+static void dom0_driver_command(const char *path, void *opaque);
#define DEBUG_DOM0_DRIVER 1
#define EVENT_PATH "/dev/input/event"
int domid;
int leaving_dir;
int new_slot;
+ int timestamp;
};
static struct dom0_driver driver;
char *str = NULL;
char path[128];
int val[10];
- const char *key[] = {"state", "domid", "new-slot"};
+ const char *key[] = {"state", "domid", "new-slot", "timestamp"};
memset(info, -1, sizeof (struct dom0_driver_xs_info));
for (int i = 0; i < sizeof (key) / sizeof (key[0]); i++)
info->state = val[0];
info->domid = val[1];
info->new_slot = val[2];
+ info->timestamp = val[3];
}
static void dom0_driver_xs_write(const char *key, int val, int controller)
{
- char path[128];
+ char path[128], str[10];
if (controller == DOM0_MOUSE)
sprintf(path, "mouse/%s", key);
if (controller == DOM0_KEYBOARD)
sprintf(path, "keyboard/%s", key);
- xenstore_write_dom0_driver(path, val);
+ sprintf(str, "%d", val);
+ xenstore_write_dom0_driver(path, str);
}
static int dom0_windows_key_switch(int code, int keycode)
{
int new_slot = 0;
struct dom0_driver_xs_info info;
+ char buff[128];
dom0_driver_read_xs_info(&info, DOM0_MOUSE);
if (info.state == 0)
default:
return 0;
}
+ sprintf(buff, "switch %d", new_slot);
- DEBUG("Write state = 0 inside xenstore\n");
-
- dom0_driver_xs_write("new-slot", new_slot, DOM0_KEYBOARD);
- dom0_driver_xs_write("new-slot", new_slot, DOM0_MOUSE);
-
- dom0_driver_xs_write("state", 0, DOM0_KEYBOARD);
- dom0_driver_xs_write("state", 0, DOM0_MOUSE);
+ DEBUG("Write \"%s\" into xenstore\n", buff);
+ xenstore_write_dom0_driver("command", buff);
return 1;
}
int *domids = NULL;
int num;
char *tmp;
- unsigned long len;
+ unsigned int len;
int pos = 0;
memset(positions, 0, NB_SLOTS * 4);
if (controller == DOM0_MOUSE)
{
if (vga_passthrough)
- xenstore_write_dom0_driver("blank", !grab);
+ {
+ char str[10];
+
+ sprintf(str, "%d", !grab);
+ xenstore_write_dom0_driver("blank", str);
+ }
else
{
struct dom0_driver_xs_info info;
static int dom0_driver_failover_switch(void *opaque)
{
- struct dom0_driver_xs_info info;
+ struct dom0_driver_xs_info mouse, keyboard;
int ret = 1;
- dom0_driver_read_xs_info(&info, DOM0_MOUSE);
+ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
+ dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
- if (info.state == -1)
+ if (mouse.state == -1)
{
DEBUG("No state grab the device\n");
dom0_gr_devices(1, DOM0_KEYBOARD);
}
/* The domain which has the focus crash */
- if (!dom0_dom_alive(info.domid))
+ if (!dom0_dom_alive(mouse.domid))
{
- DEBUG("steal the focus from %d\n", info.domid);
+ DEBUG("steal the focus from %d\n", mouse.domid);
dom0_gr_devices(1, DOM0_KEYBOARD);
dom0_gr_devices(1, DOM0_MOUSE);
goto out;
}
+ /* The domain is still alive but nobody grab the device
+ ** on the other side after 3 secondes */
+ if (keyboard.state == 0 && keyboard.timestamp != -1 &&
+ (time(NULL) - keyboard.timestamp) > 3)
+ dom0_gr_devices(1, DOM0_KEYBOARD);
+ if (mouse.state == 0 && keyboard.timestamp == -1 &&
+ (time(NULL) - mouse.timestamp) > 3)
+ {
+ dom0_gr_devices(1, DOM0_MOUSE);
+ xenstore_write_dom0_driver("blank", "0");
+ }
+
ret = 0;
out:
qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
}
if (vga_passthrough)
- xenstore_write_dom0_driver("natif", domid);
+ {
+ char str[10];
+
+ sprintf(str, "%d", domid);
+ xenstore_write_dom0_driver("natif", str);
+ }
- xenstore_watch_dom0_driver("mouse/state", "dom0_driver_keyboard_state");
- xenstore_watch_dom0_driver("keyboard/state", "dom0_driver_mouse_state");
- xenstore_watch_dom0_driver("blank", "dom0_driver_blank_done");
+ 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("blank", dom0_driver_state_change, NULL);
+ xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
/* Register the failover switch */
driver.xs_timer = qemu_new_timer(rt_clock, dom0_driver_failover_switch, NULL);
}
}
+static void dom0_driver_switch_controller(int slot, int controller)
+{
+ dom0_driver_xs_write("new-slot", slot, controller);
+ dom0_driver_xs_write("timestamp", time(NULL), controller);
+ dom0_driver_xs_write("state", 0, controller);
+}
+
+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);
+ }
+ 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);
+ }
+out:
+ free(val);
+}
+
static void dom0_driver_blank_done(void)
{
struct dom0_driver_xs_info info;
}
}
-void dom0_driver_state_change(const char *str)
+static void dom0_driver_state_change(const char *path, void *opaque)
{
- if (!strcmp(str, "dom0_driver_keyboard_state"))
+ if (strstr(path, "/keyboard/state"))
dom0_driver_slots(DOM0_KEYBOARD);
- if (!strcmp(str, "dom0_driver_mouse_state"))
+ if (strstr(path, "/mouse/state"))
dom0_driver_slots(DOM0_MOUSE);
- if (!strcmp(str, "dom0_driver_blank_done"))
+ if (strstr(path, "/blank"))
dom0_driver_blank_done();
}
struct xenstore_watch_cb_t
{
- char *token;
+ char *path;
xenstore_callback cb;
void *opaque;
};
static struct xenstore_watch_cb_t *xenstore_watch_callbacks = NULL;
-void xenstore_watch_callback(const char *token, xenstore_callback fptr, void *opaque)
+int xenstore_watch_new_callback(const char *path,
+ xenstore_callback fptr,
+ void *opaque)
{
- int i = 0;
+ int i = 0, ret = 0;
+
+ ret = xs_watch(xsh, path, path);
+ if (ret == 0)
+ return 0;
if (!xenstore_watch_callbacks)
{
xenstore_watch_callbacks = malloc(sizeof (struct xenstore_watch_cb_t));
- xenstore_watch_callbacks[0].token = NULL;
+ xenstore_watch_callbacks[0].path = NULL;
}
- while (xenstore_watch_callbacks[i].token)
+ while (xenstore_watch_callbacks[i].path)
i++;
xenstore_watch_callbacks = realloc(xenstore_watch_callbacks,
(i + 2) * sizeof (struct xenstore_watch_cb_t));
- xenstore_watch_callbacks[i].token = strdup(token);
+ xenstore_watch_callbacks[i].path = strdup(path);
xenstore_watch_callbacks[i].cb = fptr;
xenstore_watch_callbacks[i].opaque = opaque;
- xenstore_watch_callbacks[i + 1].token = NULL;
+ xenstore_watch_callbacks[i + 1].path = NULL;
+ return ret;
}
static int pasprintf(char **buf, const char *fmt, ...)
if (!vec)
return;
- for (i = 0; xenstore_watch_callbacks && xenstore_watch_callbacks[i].token; i++)
- if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].token))
+ for (i = 0; xenstore_watch_callbacks && xenstore_watch_callbacks[i].path; i++)
+ if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path))
+ {
+ fprintf(stderr, "xenstore_callback: call %s\n", vec[XS_WATCH_TOKEN]);
xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
xenstore_watch_callbacks[i].opaque);
+ }
if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
xenstore_process_logdirty_event();
goto out;
}
- if (!strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_keyboard_state") ||
- !strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_mouse_state") ||
- !strcmp(vec[XS_WATCH_TOKEN], "dom0_driver_blank_done"))
- {
- dom0_driver_state_change(vec[XS_WATCH_TOKEN]);
- goto out;
- }
-
if (!strcmp(vec[XS_WATCH_TOKEN], "acadapterstatechangeevt")) {
acpi_ac_adapter_state_changed();
goto out;
return val;
}
-int xenstore_watch_dom0_driver(const char *key, const char *token)
+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque)
{
const char *path = "/local/domain/0/dom0_driver";
char *buf = NULL;
if (pasprintf(&buf, "%s/%s", path, key) == -1)
return 0;
- ret = xs_watch(xsh, buf, token);
+ xenstore_watch_new_callback(buf, fptr, opaque);
free(buf);
return ret;
}
-int xenstore_write_dom0_driver(const char *key, int val)
+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;
- char str[10];
int ret = 0;
if (pasprintf(&buf, "%s/%s", path, key) == -1)
return 0;
- sprintf(str, "%d", val);
ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str));
free(buf);
return ret;
return tab;
}
-
-/* Advertise through xenstore that the device model is up and the
- domain can be started. */
void xenstore_dm_finished_startup(void)
{
char *path;
fprintf(logfile, "pasprintf failed to get path.\n");
goto out;
}
- xenstore_watch_callback("screenshot", xenstore_screenshot, ds);
fprintf(stderr, "screenshot watch node %s\n", buf);
- ret = xs_watch(xsh, buf, "screenshot");
+ ret = xenstore_watch_new_callback(buf, xenstore_screenshot, ds);
out:
free(buf);
free(path);
return ret;
}
+
+char *xenstore_read(const char *path)
+{
+ char *value = NULL;
+ unsigned int len;
+
+ if (xsh == NULL)
+ return NULL;
+ return xs_read(xsh, XBT_NULL, path, &len);
+}
+
+