[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] minios: add PVFB support



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1204037243 0
# Node ID 580bcd4c9642ed6f83b4c35ae0a13bb61efe7035
# Parent  ca2cf5c1adccba39aba6b08d5107cd4c5d1dfd42
minios: add PVFB support
Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
 extras/mini-os/fbfront.c         |  468 +++++++++++++++++++++++++++++++++++++++
 extras/mini-os/include/fbfront.h |   38 +++
 extras/mini-os/include/lib.h     |    4 
 extras/mini-os/kernel.c          |  149 ++++++++++++
 extras/mini-os/lib/sys.c         |   24 ++
 5 files changed, 683 insertions(+)

diff -r ca2cf5c1adcc -r 580bcd4c9642 extras/mini-os/fbfront.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/fbfront.c  Tue Feb 26 14:47:23 2008 +0000
@@ -0,0 +1,468 @@
+/*
+ * Frame Buffer + Keyboard driver for Mini-OS. 
+ * Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, 2008
+ * Based on blkfront.c.
+ */
+
+#include <os.h>
+#include <xenbus.h>
+#include <events.h>
+#include <xen/io/kbdif.h>
+#include <xen/io/fbif.h>
+#include <xen/io/protocols.h>
+#include <gnttab.h>
+#include <xmalloc.h>
+#include <fbfront.h>
+#include <lib.h>
+
+DECLARE_WAIT_QUEUE_HEAD(kbdfront_queue);
+
+
+
+
+
+
+struct kbdfront_dev {
+    domid_t dom;
+
+    struct xenkbd_page *page;
+    evtchn_port_t evtchn, local_port;
+
+    char *nodename;
+    char *backend;
+
+    char *data;
+    int width;
+    int height;
+    int depth;
+    int line_length;
+    int mem_length;
+
+#ifdef HAVE_LIBC
+    int fd;
+#endif
+};
+
+void kbdfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+#ifdef HAVE_LIBC
+    struct kbdfront_dev *dev = data;
+    int fd = dev->fd;
+
+    files[fd].read = 1;
+#endif
+    wake_up(&kbdfront_queue);
+}
+
+struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer)
+{
+    xenbus_transaction_t xbt;
+    char* err;
+    char* message=NULL;
+    struct xenkbd_page *s;
+    int retry=0;
+    char* msg;
+
+    struct kbdfront_dev *dev;
+
+    if (!nodename)
+        nodename = "device/vkbd/0";
+
+    char path[strlen(nodename) + 1 + 10 + 1];
+
+    printk("******************* KBDFRONT for %s **********\n\n\n", nodename);
+
+    dev = malloc(sizeof(*dev));
+    dev->nodename = strdup(nodename);
+
+    evtchn_alloc_unbound_t op;
+    op.dom = DOMID_SELF;
+    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    dev->dom = op.remote_dom = xenbus_read_integer(path); 
+    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
+    dev->local_port = bind_evtchn(op.port, kbdfront_handler, dev);
+    dev->evtchn=op.port;
+
+    dev->page = s = (struct xenkbd_page*) alloc_page();
+    memset(s,0,PAGE_SIZE);
+
+    s->in_cons = s->in_prod = 0;
+    s->out_cons = s->out_prod = 0;
+
+    // FIXME: proper frees on failures
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "page-ref","%u", virt_to_mfn(s));
+    if (err) {
+        message = "writing page-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+    if (abs_pointer) {
+        err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1");
+        if (err) {
+            message = "writing event-channel";
+            goto abort_transaction;
+        }
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
+    if (err)
+        printk("error writing initialized: %s\n", err);
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+    return NULL;
+
+done:
+
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    msg = xenbus_read(XBT_NIL, path, &dev->backend);
+    if (msg) {
+        printk("Error %s when reading the backend path %s\n", msg, path);
+        return NULL;
+    }
+
+    printk("backend at %s\n", dev->backend);
+
+    {
+        char path[strlen(dev->backend) + 1 + 6 + 1];
+
+        snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+        xenbus_watch_path(XBT_NIL, path);
+
+        xenbus_wait_for_value(path,"4");
+
+        xenbus_unwatch_path(XBT_NIL, path);
+
+        printk("%s connected\n", dev->backend);
+
+        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected 
*/
+    }
+
+    printk("************************** KBDFRONT\n");
+
+    return dev;
+}
+
+int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int 
n)
+{
+    struct xenkbd_page *page = dev->page;
+    uint32_t prod, cons;
+    int i;
+
+#ifdef HAVE_LIBC
+    files[dev->fd].read = 0;
+    mb(); /* Make sure to let the handler set read to 1 before we start 
looking at the ring */
+#endif
+
+    prod = page->in_prod;
+
+    if (prod == page->in_cons)
+        return 0;
+
+    rmb();      /* ensure we see ring contents up to prod */
+
+    for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
+        memcpy(buf + i, &XENKBD_IN_RING_REF(page, cons), sizeof(*buf));
+
+    mb();       /* ensure we got ring contents */
+    page->in_cons = cons;
+    notify_remote_via_evtchn(dev->evtchn);
+
+#ifdef HAVE_LIBC
+    if (cons != prod)
+        /* still some events to read */
+        files[dev->fd].read = 1;
+#endif
+
+    return i;
+}
+
+
+void shutdown_kbdfront(struct kbdfront_dev *dev)
+{
+    char* err;
+    char *nodename = dev->nodename;
+
+    char path[strlen(dev->backend) + 1 + 5 + 1];
+
+    printk("close kbd: backend at %s\n",dev->backend);
+
+    snprintf(path, sizeof(path), "%s/state", dev->backend);
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
+    xenbus_wait_for_value(path,"5");
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
+    xenbus_wait_for_value(path,"6");
+
+    unbind_evtchn(dev->local_port);
+
+    free_pages(dev->page,0);
+    free(nodename);
+    free(dev->backend);
+    free(dev);
+}
+
+#ifdef HAVE_LIBC
+int kbdfront_open(struct kbdfront_dev *dev)
+{
+    dev->fd = alloc_fd(FTYPE_KBD);
+    printk("kbd_open(%s) -> %d\n", dev->nodename, dev->fd);
+    files[dev->fd].kbd.dev = dev;
+    return dev->fd;
+}
+#endif
+
+
+
+
+
+DECLARE_WAIT_QUEUE_HEAD(fbfront_queue);
+
+
+
+
+
+
+struct fbfront_dev {
+    domid_t dom;
+
+    struct xenfb_page *page;
+    evtchn_port_t evtchn, local_port;
+
+    char *nodename;
+    char *backend;
+
+    char *data;
+    int width;
+    int height;
+    int depth;
+    int line_length;
+    int mem_length;
+};
+
+void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+    wake_up(&fbfront_queue);
+}
+
+struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int 
height, int depth, int line_length, int mem_length)
+{
+    xenbus_transaction_t xbt;
+    char* err;
+    char* message=NULL;
+    struct xenfb_page *s;
+    int retry=0;
+    char* msg;
+    int i, j;
+    struct fbfront_dev *dev;
+
+    if (!nodename)
+        nodename = "device/vfb/0";
+
+    char path[strlen(nodename) + 1 + 10 + 1];
+
+    printk("******************* FBFRONT for %s **********\n\n\n", nodename);
+
+    dev = malloc(sizeof(*dev));
+    dev->nodename = strdup(nodename);
+
+    evtchn_alloc_unbound_t op;
+    op.dom = DOMID_SELF;
+    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    dev->dom = op.remote_dom = xenbus_read_integer(path); 
+    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
+    dev->local_port = bind_evtchn(op.port, fbfront_handler, dev);
+    dev->evtchn=op.port;
+
+    dev->page = s = (struct xenfb_page*) alloc_page();
+    memset(s,0,PAGE_SIZE);
+
+    s->in_cons = s->in_prod = 0;
+    s->out_cons = s->out_prod = 0;
+    dev->width = s->width = width;
+    dev->height = s->height = height;
+    dev->depth = s->depth = depth;
+    dev->line_length = s->line_length = line_length;
+    dev->mem_length = s->mem_length = mem_length;
+
+    ASSERT(!((unsigned long)data & ~PAGE_MASK));
+    dev->data = data;
+
+    const int max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
+    unsigned long mapped = 0;
+
+    for (i = 0; mapped < mem_length && i < max_pd; i++) {
+        unsigned long *pd = (unsigned long *) alloc_page();
+        for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned 
long); j++) {
+            pd[j] = virt_to_mfn((unsigned long) data + mapped);
+            mapped += PAGE_SIZE;
+        }
+        for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
+            pd[j] = 0;
+        s->pd[i] = virt_to_mfn(pd);
+    }
+    for ( ; i < max_pd; i++)
+        s->pd[i] = 0;
+
+
+    // FIXME: proper frees on failures
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "page-ref","%u", virt_to_mfn(s));
+    if (err) {
+        message = "writing page-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename, "protocol", "%s",
+                        XEN_IO_PROTO_ABI_NATIVE);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename, "feature-update", "1");
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+    return NULL;
+
+done:
+
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    msg = xenbus_read(XBT_NIL, path, &dev->backend);
+    if (msg) {
+        printk("Error %s when reading the backend path %s\n", msg, path);
+        return NULL;
+    }
+
+    printk("backend at %s\n", dev->backend);
+
+    {
+        char path[strlen(dev->backend) + 1 + 6 + 1];
+
+        snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+        xenbus_watch_path(XBT_NIL, path);
+
+        xenbus_wait_for_value(path,"4");
+
+        printk("%s connected\n", dev->backend);
+
+        xenbus_unwatch_path(XBT_NIL, path);
+
+        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected 
*/
+    }
+
+    printk("************************** FBFRONT\n");
+
+    return dev;
+}
+
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int 
height)
+{
+    struct xenfb_page *page = dev->page;
+    uint32_t prod;
+    DEFINE_WAIT(w);
+
+    if (x < 0) {
+        width += x;
+        x = 0;
+    }
+    if (x + width > dev->width)
+        width = dev->width - x;
+
+    if (y < 0) {
+        height += y;
+        y = 0;
+    }
+    if (y + height > dev->height)
+        height = dev->height - y;
+
+    if (width <= 0 || height <= 0)
+        return;
+
+    add_waiter(w, fbfront_queue);
+    while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
+        schedule();
+    remove_waiter(w);
+
+    prod = page->out_prod;
+    mb(); /* ensure ring space available */
+    XENFB_OUT_RING_REF(page, prod).type = XENFB_TYPE_UPDATE;
+    XENFB_OUT_RING_REF(page, prod).update.x = x;
+    XENFB_OUT_RING_REF(page, prod).update.y = y;
+    XENFB_OUT_RING_REF(page, prod).update.width = width;
+    XENFB_OUT_RING_REF(page, prod).update.height = height;
+    wmb(); /* ensure ring contents visible */
+    page->out_prod = prod + 1;
+    notify_remote_via_evtchn(dev->evtchn);
+}
+
+void shutdown_fbfront(struct fbfront_dev *dev)
+{
+    char* err;
+    char *nodename = dev->nodename;
+
+    char path[strlen(dev->backend) + 1 + 5 + 1];
+
+    printk("close fb: backend at %s\n",dev->backend);
+
+    snprintf(path, sizeof(path), "%s/state", dev->backend);
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
+    xenbus_wait_for_value(path,"5");
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
+    xenbus_wait_for_value(path,"6");
+
+    unbind_evtchn(dev->local_port);
+
+    free_pages(dev->page,0);
+    free(nodename);
+    free(dev->backend);
+    free(dev);
+}
diff -r ca2cf5c1adcc -r 580bcd4c9642 extras/mini-os/include/fbfront.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/fbfront.h  Tue Feb 26 14:47:23 2008 +0000
@@ -0,0 +1,38 @@
+#include <xen/io/kbdif.h>
+#include <wait.h>
+
+/* from <linux/input.h> */
+#ifndef BTN_LEFT
+#define BTN_LEFT 0x110
+#endif
+#ifndef BTN_RIGHT
+#define BTN_RIGHT 0x111
+#endif
+#ifndef BTN_MIDDLE
+#define BTN_MIDDLE 0x112
+#endif
+#ifndef KEY_Q
+#define KEY_Q 16
+#endif
+
+
+struct kbdfront_dev;
+struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer);
+#ifdef HAVE_LIBC
+int kbdfront_open(struct kbdfront_dev *dev);
+#endif
+
+int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int 
n);
+extern struct wait_queue_head kbdfront_queue;
+
+void shutdown_kbdfront(struct kbdfront_dev *dev);
+
+
+struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int 
height, int depth, int line_length, int mem_length);
+#ifdef HAVE_LIBC
+int fbfront_open(struct fbfront_dev *dev);
+#endif
+
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int 
height);
+
+void shutdown_fbfront(struct fbfront_dev *dev);
diff -r ca2cf5c1adcc -r 580bcd4c9642 extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Tue Feb 26 14:46:57 2008 +0000
+++ b/extras/mini-os/include/lib.h      Tue Feb 26 14:47:23 2008 +0000
@@ -140,6 +140,7 @@ enum fd_type {
     FTYPE_SOCKET,
     FTYPE_TAP,
     FTYPE_BLK,
+    FTYPE_KBD,
 };
 
 #define MAX_EVTCHN_PORTS 16
@@ -171,6 +172,9 @@ extern struct file {
        struct {
            struct blkfront_dev *dev;
        } blk;
+       struct {
+           struct kbdfront_dev *dev;
+       } kbd;
         struct {
             /* To each xenbus FD is associated a queue of watch events for this
              * FD.  */
diff -r ca2cf5c1adcc -r 580bcd4c9642 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Tue Feb 26 14:46:57 2008 +0000
+++ b/extras/mini-os/kernel.c   Tue Feb 26 14:47:23 2008 +0000
@@ -39,6 +39,7 @@
 #include <gnttab.h>
 #include <netfront.h>
 #include <blkfront.h>
+#include <fbfront.h>
 #include <fs.h>
 #include <xmalloc.h>
 #include <fcntl.h>
@@ -248,6 +249,152 @@ static void blkfront_thread(void *p)
     }
 }
 
+#define WIDTH 800
+#define HEIGHT 600
+#define DEPTH 32
+
+static uint32_t *fb;
+static struct fbfront_dev *fb_dev;
+static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0);
+
+static void fbfront_drawvert(int x, int y1, int y2, uint32_t color)
+{
+    int y;
+    if (x < 0)
+        return;
+    if (x >= WIDTH)
+        return;
+    if (y1 < 0)
+        y1 = 0;
+    if (y2 >= HEIGHT)
+        y2 = HEIGHT-1;
+    for (y = y1; y <= y2; y++)
+        fb[x + y*WIDTH] ^= color;
+}
+
+static void fbfront_drawhoriz(int x1, int x2, int y, uint32_t color)
+{
+    int x;
+    if (y < 0)
+        return;
+    if (y >= HEIGHT)
+        return;
+    if (x1 < 0)
+        x1 = 0;
+    if (x2 >= WIDTH)
+        x2 = WIDTH-1;
+    for (x = x1; x <= x2; x++)
+        fb[x + y*WIDTH] ^= color;
+}
+
+static void fbfront_thread(void *p)
+{
+    size_t line_length = WIDTH * (DEPTH / 8);
+    size_t memsize = HEIGHT * line_length;
+
+    fb = _xmalloc(memsize, PAGE_SIZE);
+    fb_dev = init_fbfront(NULL, fb, WIDTH, HEIGHT, DEPTH, line_length, 
memsize);
+    if (!fb_dev) {
+        xfree(fb);
+        return;
+    }
+    up(&fbfront_sem);
+}
+
+static void clip_cursor(int *x, int *y)
+{
+    if (*x < 0)
+        *x = 0;
+    if (*x >= WIDTH)
+        *x = WIDTH - 1;
+    if (*y < 0)
+        *y = 0;
+    if (*y >= HEIGHT)
+        *y = HEIGHT - 1;
+}
+
+static void refresh_cursor(int new_x, int new_y)
+{
+    static int old_x = -1, old_y = -1;
+    if (old_x != -1 && old_y != -1) {
+        fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff);
+        fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff);
+        fbfront_update(fb_dev, old_x, old_y, 9, 9);
+    }
+    old_x = new_x;
+    old_y = new_y;
+    fbfront_drawvert(new_x, new_y + 1, new_y + 8, 0xffffffff);
+    fbfront_drawhoriz(new_x + 1, new_x + 8, new_y, 0xffffffff);
+    fbfront_update(fb_dev, new_x, new_y, 9, 9);
+}
+
+static void kbdfront_thread(void *p)
+{
+    struct kbdfront_dev *kbd_dev;
+    DEFINE_WAIT(w);
+    int x = WIDTH / 2, y = HEIGHT / 2, z;
+
+    kbd_dev = init_kbdfront(NULL, 1);
+    if (!kbd_dev)
+        return;
+
+    down(&fbfront_sem);
+    refresh_cursor(x, y);
+    while (1) {
+        union xenkbd_in_event event;
+
+        add_waiter(w, kbdfront_queue);
+
+        if (kbdfront_receive(kbd_dev, &event, 1) == 0)
+            schedule();
+        else switch(event.type) {
+            case XENKBD_TYPE_MOTION:
+                printk("motion x:%d y:%d z:%d\n",
+                        event.motion.rel_x,
+                        event.motion.rel_y,
+                        event.motion.rel_z);
+                x += event.motion.rel_x;
+                y += event.motion.rel_y;
+                z += event.motion.rel_z;
+                clip_cursor(&x, &y);
+                refresh_cursor(x, y);
+                break;
+            case XENKBD_TYPE_POS:
+                printk("pos x:%d y:%d z:%d\n",
+                        event.pos.abs_x,
+                        event.pos.abs_y,
+                        event.pos.abs_z);
+                x = event.pos.abs_x;
+                y = event.pos.abs_y;
+                z = event.pos.abs_z;
+                clip_cursor(&x, &y);
+                refresh_cursor(x, y);
+                break;
+            case XENKBD_TYPE_KEY:
+                printk("key %d %s\n",
+                        event.key.keycode,
+                        event.key.pressed ? "pressed" : "released");
+                if (event.key.keycode == BTN_LEFT) {
+                    printk("mouse %s at (%d,%d,%d)\n",
+                            event.key.pressed ? "clic" : "release", x, y, z);
+                    if (event.key.pressed) {
+                        uint32_t color = rand();
+                        fbfront_drawvert(x - 16, y - 16, y + 15, color);
+                        fbfront_drawhoriz(x - 16, x + 15, y + 16, color);
+                        fbfront_drawvert(x + 16, y - 15, y + 16, color);
+                        fbfront_drawhoriz(x - 15, x + 16, y - 16, color);
+                        fbfront_update(fb_dev, x - 16, y - 16, 33, 33);
+                    }
+                } else if (event.key.keycode == KEY_Q) {
+                    struct sched_shutdown sched_shutdown = { .reason = 
SHUTDOWN_poweroff };
+                    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+                    do_exit();
+                }
+                break;
+        }
+    }
+}
+
 static void fs_thread(void *p)
 {
     init_fs_frontend();
@@ -261,6 +408,8 @@ __attribute__((weak)) int app_main(start
     create_thread("periodic_thread", periodic_thread, si);
     create_thread("netfront", netfront_thread, si);
     create_thread("blkfront", blkfront_thread, si);
+    create_thread("fbfront", fbfront_thread, si);
+    create_thread("kbdfront", kbdfront_thread, si);
     create_thread("fs-frontend", fs_thread, si);
     return 0;
 }
diff -r ca2cf5c1adcc -r 580bcd4c9642 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Tue Feb 26 14:46:57 2008 +0000
+++ b/extras/mini-os/lib/sys.c  Tue Feb 26 14:47:23 2008 +0000
@@ -26,6 +26,7 @@
 #include <wait.h>
 #include <netfront.h>
 #include <blkfront.h>
+#include <fbfront.h>
 #include <xenbus.h>
 #include <xs.h>
 
@@ -221,6 +222,16 @@ int read(int fd, void *buf, size_t nbyte
            }
            return ret;
        }
+        case FTYPE_KBD: {
+            int ret, n;
+            n = nbytes / sizeof(union xenkbd_in_event);
+            ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
+           if (ret <= 0) {
+               errno = EAGAIN;
+               return -1;
+           }
+           return ret * sizeof(union xenkbd_in_event);
+        }
        case FTYPE_NONE:
        case FTYPE_XENBUS:
        case FTYPE_EVTCHN:
@@ -261,6 +272,7 @@ int write(int fd, const void *buf, size_
        case FTYPE_XENBUS:
        case FTYPE_EVTCHN:
        case FTYPE_BLK:
+       case FTYPE_KBD:
            break;
     }
     printk("write(%d): Bad descriptor\n", fd);
@@ -318,6 +330,7 @@ int fsync(int fd) {
        case FTYPE_EVTCHN:
        case FTYPE_TAP:
        case FTYPE_BLK:
+       case FTYPE_KBD:
            break;
     }
     printk("fsync(%d): Bad descriptor\n", fd);
@@ -360,6 +373,10 @@ int close(int fd)
             shutdown_blkfront(files[fd].blk.dev);
            files[fd].type = FTYPE_NONE;
            return 0;
+       case FTYPE_KBD:
+            shutdown_kbdfront(files[fd].kbd.dev);
+            files[fd].type = FTYPE_NONE;
+            return 0;
        case FTYPE_NONE:
            break;
     }
@@ -450,6 +467,7 @@ int fstat(int fd, struct stat *buf)
        case FTYPE_EVTCHN:
        case FTYPE_TAP:
        case FTYPE_BLK:
+       case FTYPE_KBD:
            break;
     }
 
@@ -477,6 +495,7 @@ int ftruncate(int fd, off_t length)
        case FTYPE_EVTCHN:
        case FTYPE_TAP:
        case FTYPE_BLK:
+       case FTYPE_KBD:
            break;
     }
 
@@ -587,6 +606,7 @@ static const char file_types[] = {
     [FTYPE_SOCKET]     = 'S',
     [FTYPE_TAP]                = 'T',
     [FTYPE_BLK]                = 'B',
+    [FTYPE_KBD]                = 'K',
 };
 #ifdef LIBC_DEBUG
 static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set 
*exceptfds, struct timeval *timeout)
@@ -694,6 +714,7 @@ static int select_poll(int nfds, fd_set 
        case FTYPE_EVTCHN:
        case FTYPE_TAP:
        case FTYPE_BLK:
+       case FTYPE_KBD:
            if (FD_ISSET(i, readfds)) {
                if (files[i].read)
                    n++;
@@ -775,6 +796,7 @@ int select(int nfds, fd_set *readfds, fd
     DEFINE_WAIT(w2);
     DEFINE_WAIT(w3);
     DEFINE_WAIT(w4);
+    DEFINE_WAIT(w5);
 
     assert(thread == main_thread);
 
@@ -795,6 +817,7 @@ int select(int nfds, fd_set *readfds, fd
     add_waiter(w2, event_queue);
     add_waiter(w3, blkfront_queue);
     add_waiter(w4, xenbus_watch_queue);
+    add_waiter(w5, kbdfront_queue);
 
     myread = *readfds;
     mywrite = *writefds;
@@ -860,6 +883,7 @@ out:
     remove_waiter(w2);
     remove_waiter(w3);
     remove_waiter(w4);
+    remove_waiter(w5);
     return ret;
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.