diff -r a2618d3912e7 tools/python/xen/xend/server/vfbif.py
--- a/tools/python/xen/xend/server/vfbif.py Mon Dec 04 19:13:55 2006 +0000
+++ b/tools/python/xen/xend/server/vfbif.py Tue Dec 05 10:29:17 2006 +0100
@@ -50,6 +50,9 @@ class VfbifController(DevController):
# is HVM, so qemu-dm will handle the vfb.
return
+ # old frontend compatibility
+ self.vm._writeDom("console/use_graphics", "1")
+ # /old
std_args = [ "--domid", "%d" % self.vm.getDomid(),
"--title", self.vm.getName() ]
t = config.get("type", None)
diff -r 7df4d8cfba3b tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Tue Dec 05 12:42:29 2006 +0000
+++ b/tools/python/xen/xm/create.py Thu Dec 07 15:50:07 2006 +0100
@@ -577,6 +577,24 @@ def configure_usb(config_devs, vals):
config_devs.append(['device', config_usb])
def configure_vfbs(config_devs, vals):
+ # old config compatibility
+ if vals.vfb == [] and (vals.sdl or vals.vnc):
+ if vals.vnc:
+ cfg = 'type=vnc'
+ if vals.vncdisplay:
+ cfg += ',vncdisplay=%s' % vals.vncdisplay
+ if vals.vncunused:
+ cfg += ',vncunused=%s' % vals.vncunused
+ if vals.vnclisten:
+ cfg += ',vnclisten=%s' % vals.vnclisten
+ else:
+ cfg = 'type=sdl'
+ if vals.xauthority:
+ cfg += ',xauthority=%s' % vals.xauthority
+ if vals.display:
+ cfg += ',display=%s' % vals.display
+ vals.vfb = [ cfg, ]
+ # /old
for f in vals.vfb:
d = comma_sep_kv_to_dict(f)
config = ['vfb']
diff -r a2618d3912e7 tools/xenfb/Makefile
--- a/tools/xenfb/Makefile Mon Dec 04 19:13:55 2006 +0000
+++ b/tools/xenfb/Makefile Tue Dec 05 10:26:52 2006 +0100
@@ -13,12 +17,14 @@ all: build
.PHONY: build
build:
- $(MAKE) vncfb sdlfb
+ $(MAKE) vncfb sdlfb vncfbo sdlfbo
install: all
$(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
$(INSTALL_PROG) vncfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfb
$(INSTALL_PROG) sdlfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfb
+ $(INSTALL_PROG) vncfbo $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfbo
+ $(INSTALL_PROG) sdlfbo $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfbo
sdlfb: sdlfb.o xenfb.o
@@ -33,3 +39,14 @@ vncfb: LDLIBS += $(shell libvncserver-co
vncfb: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore
sdlfb.o xenfb.o vncfb.o: xenfb.h
+
+sdlfbo vncfbo:
+ $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
+
+sdlfbo: sdlfb.o oldxenfb.o
+sdlfbo: LDLIBS += $(shell sdl-config --libs) -lxenctrl -lxenstore
+
+vncfbo: vncfb.o oldxenfb.o
+vncfbo: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore
+
+oldxenfb.o: xenfb.h oldxenfb.h oldxenkbd.h
diff -r a2618d3912e7 tools/xenfb/sdlfb.c
--- a/tools/xenfb/sdlfb.c Tue Dec 05 12:42:29 2006 +0000
+++ b/tools/xenfb/sdlfb.c Thu Dec 07 19:45:51 2006 +0100
@@ -212,6 +212,7 @@ int main(int argc, char **argv)
struct xenfb *xenfb;
int domid = -1;
char * title = NULL;
+ int ret;
fd_set readfds;
int nfds;
struct SDLFBData data;
@@ -256,11 +257,19 @@ int main(int argc, char **argv)
exit(1);
}
- if (xenfb_attach_dom(xenfb, domid) < 0) {
+ ret = xenfb_attach_dom(xenfb, domid);
+ if (ret < 0) {
fprintf(stderr, "Could not connect to domain (%s)\n",
strerror(errno));
exit(1);
}
+ if (ret > 0) {
+ if (xenfb_switch_to_old_protocol(argv) < 0) {
+ fprintf(stderr, "Could not switch to old protocol (%s)\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Could not initialize SDL\n");
diff -r a2618d3912e7 tools/xenfb/vncfb.c
--- a/tools/xenfb/vncfb.c Mon Dec 04 19:13:55 2006 +0000
+++ b/tools/xenfb/vncfb.c Tue Dec 05 10:26:52 2006 +0100
@@ -269,6 +269,7 @@ int main(int argc, char **argv)
bool unused = false;
int opt;
struct xenfb *xenfb;
+ int ret;
fd_set readfds;
int nfds;
char portstr[10];
@@ -340,10 +341,18 @@ int main(int argc, char **argv)
exit(1);
}
- if (xenfb_attach_dom(xenfb, domid) < 0) {
+ ret = xenfb_attach_dom(xenfb, domid);
+ if (ret < 0) {
fprintf(stderr, "Could not connect to domain (%s)\n",
strerror(errno));
exit(1);
+ }
+ if (ret > 0) {
+ if (xenfb_switch_to_old_protocol(argv) < 0) {
+ fprintf(stderr, "Could not switch to old protocol (%s)\n",
+ strerror(errno));
+ exit(1);
+ }
}
server = rfbGetScreen(&fake_argc, fake_argv,
diff -r a2618d3912e7 tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c Mon Dec 04 19:13:55 2006 +0000
+++ b/tools/xenfb/xenfb.c Tue Dec 05 10:26:52 2006 +0100
@@ -290,6 +301,60 @@ static int xenfb_hotplug(struct xenfb_de
return 0;
}
+static int xenfb_using_old_protocol(struct xenfb_private *xenfb)
+{
+ struct xs_handle *xsh = xenfb->xsh;
+ char buf[64];
+ char *p, *v, **vec;
+ enum xenbus_state state;
+ unsigned dummy;
+ int ret;
+
+ p = xenfb_path_in_dom(xsh, buf, sizeof(buf),
+ xenfb->fb.otherend_id, "vfb/page-ref");
+ if (!xs_watch(xsh, p, ""))
+ return -1;
+
+ for (;;) {
+ state = xenfb_read_state(xsh, xenfb->fb.otherend);
+ if (state > XenbusStateInitialising) {
+ ret = 0; /* frontend talks xenbus protocol */
+ break;
+ }
+
+ v = xs_read(xsh, XBT_NULL, p, NULL);
+ free(v);
+ if (v) {
+ ret = 1; /* frontend talks old protocol */
+ break;
+ }
+
+ vec = xs_read_watch(xsh, &dummy);
+ if (!vec) {
+ ret = -1;
+ break;
+ }
+ free(vec);
+ }
+
+ xs_unwatch(xsh, p, "");
+ return ret;
+}
+
+int xenfb_switch_to_old_protocol(char **argv)
+{
+ size_t len = strlen(argv[0]);
+ char *prog;
+
+ prog = malloc(len + 2);
+ if (!prog)
+ return -1;
+ strcpy(prog, argv[0]);
+ strcpy(prog + len, "o");
+ argv[0] = prog;
+ return execv(prog, argv);
+}
+
static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
{
switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
@@ -473,6 +534,9 @@ int xenfb_attach_dom(struct xenfb *xenfb
goto error;
if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
goto error;
+
+ if (xenfb_using_old_protocol(xenfb))
+ return 1;
if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
goto error;
diff -r a2618d3912e7 tools/xenfb/xenfb.h
--- a/tools/xenfb/xenfb.h Mon Dec 04 19:13:55 2006 +0000
+++ b/tools/xenfb/xenfb.h Tue Dec 05 10:26:52 2006 +0100
@@ -32,4 +32,6 @@ int xenfb_send_motion(struct xenfb *xenf
int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
+int xenfb_switch_to_old_protocol(char **);
+
#endif
diff -r 3f0ca90351e2 tools/xenfb/oldxenfb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xenfb/oldxenfb.c Fri Dec 08 16:31:34 2006 +0100
@@ -0,0 +1,611 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xenctrl.h>
+#include <xen/io/xenbus.h>
+#include "oldxenfb.h"
+#include "oldxenkbd.h"
+#include <sys/select.h>
+#include <stdbool.h>
+#include <xen/linux/evtchn.h>
+#include <xen/event_channel.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <xs.h>
+
+#include "xenfb.h"
+
+// FIXME defend against malicious frontend?
+
+struct xenfb_device {
+ const char *devicetype;
+ char nodename[64]; /* backend xenstore dir */
+ char otherend[64]; /* frontend xenstore dir */
+ int otherend_id; /* frontend domid */
+ enum xenbus_state state; /* backend state */
+ void *page; /* shared page */
+ evtchn_port_t port;
+ struct xenfb_private *xenfb;
+};
+
+struct xenfb_private {
+ struct xenfb pub;
+ int evt_xch; /* event channel driver handle */
+ int xc; /* hypervisor interface handle */
+ struct xs_handle *xsh; /* xs daemon handle */
+ struct xenfb_device fb, kbd;
+ size_t fb_len; /* size of framebuffer */
+};
+
+static void xenfb_detach_dom(struct xenfb_private *);
+static int xenfb_fb_event(struct xenfb_private *, union xenfb_in_event *);
+
+static char *xenfb_path_in_dom(struct xs_handle *xsh,
+ char *buf, size_t size,
+ unsigned domid, const char *fmt, ...)
+{
+ va_list ap;
+ char *domp = xs_get_domain_path(xsh, domid);
+ int n;
+
+ if (domp == NULL)
+ return NULL;
+
+ n = snprintf(buf, size, "%s/", domp);
+ free(domp);
+ if (n >= size)
+ return NULL;
+
+ va_start(ap, fmt);
+ n += vsnprintf(buf + n, size - n, fmt, ap);
+ va_end(ap);
+ if (n >= size)
+ return NULL;
+
+ return buf;
+}
+
+static int xenfb_xs_scanf1(struct xs_handle *xsh,
+ const char *dir, const char *node,
+ const char *fmt, void *dest)
+{
+ char buf[1024];
+ char *p;
+ int ret;
+
+ if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
+ errno = ENOENT;
+ return -1;
+ }
+ p = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (!p) {
+ errno = ENOENT;
+ return -1;
+ }
+ ret = sscanf(p, fmt, dest);
+ free(p);
+ if (ret != 1) {
+ errno = EDOM;
+ return -1;
+ }
+ return ret;
+}
+
+static int xenfb_xs_printf(struct xs_handle *xsh,
+ const char *dir, const char *node, char *fmt, ...)
+{
+ va_list ap;
+ char key[1024];
+ char val[1024];
+ int n;
+
+ if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ n = vsnprintf(val, sizeof(val), fmt, ap);
+ va_end(ap);
+ if (n >= sizeof(val)) {
+ errno = ENOSPC; /* close enough */
+ return -1;
+ }
+
+ if (!xs_write(xsh, XBT_NULL, key, val, n))
+ return -1;
+ return 0;
+}
+
+static void xenfb_device_init(struct xenfb_device *dev,
+ const char *type,
+ struct xenfb_private *xenfb)
+{
+ dev->devicetype = type;
+ dev->otherend_id = -1;
+ dev->port = -1;
+ dev->xenfb = xenfb;
+}
+
+int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+
+ dev->otherend_id = domid;
+
+ if (!xenfb_path_in_dom(xenfb->xsh,
+ dev->otherend, sizeof(dev->otherend),
+ domid, "device/%s/0", dev->devicetype)) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (!xenfb_path_in_dom(xenfb->xsh,
+ dev->nodename, sizeof(dev->nodename),
+ 0, "backend/%s/%d/0", dev->devicetype, domid)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return 0;
+}
+
+struct xenfb *xenfb_new(void)
+{
+ struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
+ int serrno;
+
+ if (xenfb == NULL)
+ return NULL;
+
+ memset(xenfb, 0, sizeof(*xenfb));
+ xenfb->evt_xch = xenfb->xc = -1;
+ xenfb_device_init(&xenfb->fb, "vfb", xenfb);
+ xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
+
+ xenfb->evt_xch = xc_evtchn_open();
+ if (xenfb->evt_xch == -1)
+ goto fail;
+
+ xenfb->xc = xc_interface_open();
+ if (xenfb->xc == -1)
+ goto fail;
+
+ xenfb->xsh = xs_daemon_open();
+ if (!xenfb->xsh)
+ goto fail;
+
+ return &xenfb->pub;
+
+ fail:
+ serrno = errno;
+ xenfb_delete(&xenfb->pub);
+ errno = serrno;
+ return NULL;
+}
+
+/* Remove the backend area in xenbus since the framebuffer really is
+ going away. */
+void xenfb_teardown(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
+}
+
+
+void xenfb_delete(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+
+ xenfb_detach_dom(xenfb);
+ if (xenfb->xc >= 0)
+ xc_interface_close(xenfb->xc);
+ if (xenfb->evt_xch >= 0)
+ xc_evtchn_close(xenfb->evt_xch);
+ if (xenfb->xsh)
+ xs_daemon_close(xenfb->xsh);
+ free(xenfb);
+}
+
+static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
+ const char *dir)
+{
+ int ret, state;
+
+ ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
+ if (ret < 0)
+ return XenbusStateUnknown;
+
+ if ((unsigned)state > XenbusStateClosed)
+ state = XenbusStateUnknown;
+ return state;
+}
+
+static int xenfb_switch_state(struct xenfb_device *dev,
+ enum xenbus_state state)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+
+ if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
+ return -1;
+ dev->state = state;
+ return 0;
+}
+
+int xenfb_switch_to_old_protocol(char **argv)
+{
+ abort();
+}
+
+static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
+{
+ struct xenfb_page *page = xenfb->fb.page;
+ int n_fbmfns;
+ int n_fbdirs;
+ unsigned long *fbmfns;
+
+ n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+ n_fbdirs = n_fbmfns * sizeof(unsigned long);
+ n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+
+ /*
+ * Bug alert: xc_map_foreign_batch() can fail partly and
+ * return a non-null value. This is a design flaw. When it
+ * happens, we happily continue here, and later crash on
+ * access.
+ */
+ fbmfns = xc_map_foreign_batch(xenfb->xc, domid,
+ PROT_READ, page->pd, n_fbdirs);
+ if (fbmfns == NULL)
+ return -1;
+
+ xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
+ PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
+ if (xenfb->pub.pixels == NULL) {
+ munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
+ return -1;
+ }
+
+ return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
+}
+
+static int xenfb_bind(struct xenfb_device *dev)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+ unsigned long mfn;
+ evtchn_port_t evtchn;
+ char buf[64];
+ char *p, **vec;
+ unsigned dummy;
+
+ p = xenfb_path_in_dom(xenfb->xsh, buf, sizeof(buf),
+ dev->otherend_id, dev->devicetype);
+ if (!xs_watch(xenfb->xsh, p, ""))
+ return -1;
+ for (;;) {
+ if (xenfb_xs_scanf1(xenfb->xsh, p, "page-ref", "%lu",
+ &mfn) < 0) {
+ if (errno == ENOENT || errno == EAGAIN)
+ goto wait;
+ return -1;
+ }
+ if (xenfb_xs_scanf1(xenfb->xsh, p, "event-channel", "%u",
+ &evtchn) < 0) {
+ if (errno == ENOENT || errno == EAGAIN)
+ goto wait;
+ return -1;
+ }
+ break;
+
+ wait:
+ printf("Waiting...\n");
+ vec = xs_read_watch(xenfb->xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+ }
+
+ dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
+ dev->otherend_id, evtchn);
+ if (dev->port == -1)
+ return -1;
+
+ dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
+ XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
+ if (dev->page == NULL)
+ return -1;
+
+ return 0;
+}
+
+static void xenfb_unbind(struct xenfb_device *dev)
+{
+ if (dev->page) {
+ munmap(dev->page, XC_PAGE_SIZE);
+ dev->page = NULL;
+ }
+ if (dev->port >= 0) {
+ xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
+ dev->port = -1;
+ }
+}
+
+static void xenfb_dev_fatal(struct xenfb_device *dev, int err,
+ const char *fmt, ...)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+ va_list ap;
+ char errdir[80];
+ char buf[1024];
+ int n;
+
+ fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (err)
+ fprintf(stderr, " (%s)", strerror(err));
+ putc('\n', stderr);
+
+ if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0,
+ "error/%s", dev->nodename))
+ goto out; /* FIXME complain */
+
+ va_start(ap, fmt);
+ n = snprintf(buf, sizeof(buf), "%d ", err);
+ snprintf(buf + n, sizeof(buf) - n, fmt, ap);
+ va_end(ap);
+
+ if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
+ goto out; /* FIXME complain */
+
+ out:
+ xenfb_switch_state(dev, XenbusStateClosing);
+}
+
+int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ struct xs_handle *xsh = xenfb->xsh;
+ int val, serrno;
+ struct xenfb_page *fb_page;
+ union xenfb_in_event event;
+
+ xenfb_detach_dom(xenfb);
+
+ xenfb_device_set_domain(&xenfb->fb, domid);
+ xenfb_device_set_domain(&xenfb->kbd, domid);
+
+ if (!xs_watch(xsh, xenfb->fb.otherend, ""))
+ goto error;
+ if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
+ goto error;
+
+ if (xenfb_bind(&xenfb->fb) < 0)
+ goto error;
+ if (xenfb_bind(&xenfb->kbd) < 0)
+ goto error;
+
+ /* TODO check for permitted ranges */
+ fb_page = xenfb->fb.page;
+ xenfb->pub.depth = fb_page->depth;
+ xenfb->pub.width = fb_page->width;
+ xenfb->pub.height = fb_page->height;
+ /* TODO check for consistency with the above */
+ xenfb->fb_len = fb_page->mem_length;
+ xenfb->pub.row_stride = fb_page->line_length;
+
+ if (xenfb_map_fb(xenfb, domid) < 0)
+ goto error;
+
+ event.type = XENFB_TYPE_SET_EVENTS;
+ event.set_events.flags = XENFB_FLAG_UPDATE;
+ if (xenfb_fb_event(xenfb, &event))
+ goto error;
+
+ return 0;
+
+ error:
+ serrno = errno;
+ xenfb_detach_dom(xenfb);
+ xenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
+ xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
+ errno = serrno;
+ return -1;
+}
+
+static void xenfb_detach_dom(struct xenfb_private *xenfb)
+{
+ xenfb_unbind(&xenfb->fb);
+ xenfb_unbind(&xenfb->kbd);
+ if (xenfb->pub.pixels) {
+ munmap(xenfb->pub.pixels, xenfb->fb_len);
+ xenfb->pub.pixels = NULL;
+ }
+}
+
+static void xenfb_on_fb_event(struct xenfb_private *xenfb)
+{
+ uint32_t prod, cons;
+ struct xenfb_page *page = xenfb->fb.page;
+
+ prod = page->out_prod;
+ if (prod == page->out_cons)
+ return;
+ rmb(); /* ensure we see ring contents up to prod */
+ for (cons = page->out_cons; cons != prod; cons++) {
+ union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+
+ switch (event->type) {
+ case XENFB_TYPE_UPDATE:
+ if (xenfb->pub.update)
+ xenfb->pub.update(&xenfb->pub,
+ event->update.x, event->update.y,
+ event->update.width, event->update.height);
+ break;
+ }
+ }
+ mb(); /* ensure we're done with ring contents */
+ page->out_cons = cons;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
+{
+ struct xenkbd_info *page = xenfb->kbd.page;
+
+ /* We don't understand any keyboard events, so just ignore them. */
+ if (page->out_prod == page->out_cons)
+ return;
+ page->out_cons = page->out_prod;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+static int xenfb_on_state_change(struct xenfb_device *dev)
+{
+ enum xenbus_state state;
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
+
+ switch (state) {
+ case XenbusStateUnknown:
+ /* There was an error reading the frontend state. The
+ domain has probably gone away; in any case, there's
+ not much point in us continuing. */
+ return -1;
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
+ case XenbusStateConnected:
+ break;
+ case XenbusStateClosing:
+ xenfb_unbind(dev);
+ xenfb_switch_state(dev, state);
+ break;
+ case XenbusStateClosed:
+ xenfb_switch_state(dev, state);
+ }
+ return 0;
+}
+
+/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
+int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ evtchn_port_t port;
+ unsigned dummy;
+ char **vec;
+ int r;
+
+ if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
+ port = xc_evtchn_pending(xenfb->evt_xch);
+ if (port == -1)
+ return -1;
+
+ if (port == xenfb->fb.port)
+ xenfb_on_fb_event(xenfb);
+ else if (port == xenfb->kbd.port)
+ xenfb_on_kbd_event(xenfb);
+
+ if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
+ return -1;
+ }
+
+ if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
+ vec = xs_read_watch(xenfb->xsh, &dummy);
+ free(vec);
+ r = xenfb_on_state_change(&xenfb->fb);
+ if (r == 0)
+ r = xenfb_on_state_change(&xenfb->kbd);
+ if (r == -1)
+ return -2;
+ }
+
+ return 0;
+}
+
+int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ int fd1 = xc_evtchn_fd(xenfb->evt_xch);
+ int fd2 = xs_fileno(xenfb->xsh);
+
+ FD_SET(fd1, readfds);
+ FD_SET(fd2, readfds);
+ return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
+}
+
+static int xenfb_fb_event(struct xenfb_private *xenfb,
+ union xenfb_in_event *event)
+{
+ uint32_t prod;
+ struct xenfb_page *page = xenfb->fb.page;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENFB_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENFB_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static int xenfb_kbd_event(struct xenfb_private *xenfb,
+ union xenkbd_in_event *event)
+{
+ uint32_t prod;
+ struct xenkbd_info *page = xenfb->kbd.page;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENKBD_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_KEY;
+ event.key.pressed = down ? 1 : 0;
+ event.key.keycode = keycode;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_MOTION;
+ event.motion.rel_x = rel_x;
+ event.motion.rel_y = rel_y;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
+{
+ abort();
+}
diff -r 7df4d8cfba3b tools/xenfb/oldxenfb.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xenfb/oldxenfb.h Tue Dec 05 10:26:52 2006 +0100
@@ -0,0 +1,108 @@
+/*
+ * linux/include/linux/xenfb.h -- Xen virtual frame buffer device
+ *
+ * Copyright (C) 2005
+ *
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef _LINUX_XENFB_H
+#define _LINUX_XENFB_H
+
+#include <asm/types.h>
+
+/* out events */
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+#define XENFB_TYPE_MOTION 1
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_motion /* currently unused */
+{
+ __u8 type; /* XENFB_TYPE_MOTION */
+ __u16 x; /* The new x coordinate */
+ __u16 y; /* The new y coordinate */
+};
+
+struct xenfb_update
+{
+ __u8 type; /* XENFB_TYPE_UPDATE */
+ __u16 x; /* source x */
+ __u16 y; /* source y */
+ __u16 width; /* rect width */
+ __u16 height; /* rect height */
+};
+
+union xenfb_out_event
+{
+ __u8 type;
+ struct xenfb_motion motion;
+ struct xenfb_update update;
+ char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* in events */
+
+#define XENFB_IN_EVENT_SIZE 40
+
+#define XENFB_TYPE_SET_EVENTS 1
+
+#define XENFB_FLAG_MOTION 1
+#define XENFB_FLAG_UPDATE 2
+#define XENFB_FLAG_COPY 4
+#define XENFB_FLAG_FILL 8
+
+struct xenfb_set_events
+{
+ __u8 type; /* XENFB_TYPE_SET_EVENTS */
+ __u32 flags; /* combination of XENFB_FLAG_* */
+};
+
+union xenfb_in_event
+{
+ __u8 type;
+ struct xenfb_set_events set_events;
+ char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page
+{
+ __u16 width; /* the width of the framebuffer (in pixels) */
+ __u16 height; /* the height of the framebuffer (in pixels) */
+ __u32 line_length; /* the length of a row of pixels (in bytes) */
+ __u32 mem_length; /* the length of the framebuffer (in bytes) */
+ __u8 depth; /* the depth of a pixel (in bits) */
+
+ unsigned long pd[2]; /* FIXME rename to pgdir? */
+ /* FIXME pd[1] unused at this time, shrink? */
+
+ __u32 in_cons, in_prod;
+ __u32 out_cons, out_prod;
+};
+
+void xenfb_resume(void);
+
+#endif
diff -r 7df4d8cfba3b tools/xenfb/oldxenkbd.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xenfb/oldxenkbd.h Tue Dec 05 10:26:52 2006 +0100
@@ -0,0 +1,92 @@
+/*
+ * linux/include/linux/xenkbd.h -- Xen virtual keyboard/mouse
+ *
+ * Copyright (C) 2005
+ *
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef _LINUX_XENKBD_H
+#define _LINUX_XENKBD_H
+
+#include <asm/types.h>
+
+/* in events */
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+#define XENKBD_TYPE_MOTION 1 /* mouse movement event */
+#define XENKBD_TYPE_BUTTON 2 /* mouse button event */
+#define XENKBD_TYPE_KEY 3 /* keyboard event */
+
+struct xenkbd_motion
+{
+ __u8 type; /* XENKBD_TYPE_MOTION */
+ __s16 rel_x; /* relative X motion */
+ __s16 rel_y; /* relative Y motion */
+};
+
+struct xenkbd_button
+{
+ __u8 type; /* XENKBD_TYPE_BUTTON */
+ __u8 pressed; /* 1 if pressed; 0 otherwise */
+ __u8 button; /* the button (0, 1, 2 is right, middle, left) */
+};
+
+struct xenkbd_key
+{
+ __u8 type; /* XENKBD_TYPE_KEY */
+ __u8 pressed; /* 1 if pressed; 0 otherwise */
+ __u16 keycode; /* KEY_* from linux/input.h */
+};
+
+union xenkbd_in_event
+{
+ __u8 type;
+ struct xenkbd_motion motion;
+ struct xenkbd_button button;
+ struct xenkbd_key key;
+ char _[XENKBD_IN_EVENT_SIZE];
+};
+
+/* out events */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event
+{
+ __u8 type;
+ char _[XENKBD_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_info
+{
+ __u32 in_cons, in_prod;
+ __u32 out_cons, out_prod;
+};
+
+void xenkbd_resume(void);
+
+#endif