diff --git a/console.h b/console.h
index 9615f56..568d097 100644
--- a/console.h
+++ b/console.h
@@ -26,7 +26,16 @@ typedef struct QEMUPutMouseEntry {
     struct QEMUPutMouseEntry *next;
 } QEMUPutMouseEntry;
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+typedef struct QEMUPutKeyboardEntry {
+    QEMUPutKBDEvent *qemu_put_kbd_event;
+    void *qemu_put_kbd_event_opaque;
+
+    /* used internally by qemu for handling mice */
+    struct QEMUPutKeyboardEntry *next;
+} QEMUPutKeyboardEntry;
+
+QEMUPutKeyboardEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+void qemu_remove_kbd_event_handler(QEMUPutKeyboardEntry *entry);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 795a326..090f857 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -68,6 +68,7 @@ struct XenInput {
     int button_state;       /* Last seen pointer button state */
     int extended;
     QEMUPutMouseEntry *qmouse;
+    QEMUPutKeyboardEntry *qkeyboard;
 };
 
 #define UP_QUEUE 8
@@ -373,7 +374,7 @@ static int input_connect(struct XenDevice *xendev)
     if (rc != 0)
 	return rc;
 
-    qemu_add_kbd_event_handler(xenfb_key_event, in);
+    in->qkeyboard = qemu_add_kbd_event_handler(xenfb_key_event, in);
     in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
 					      in->abs_pointer_wanted,
 					      "Xen PVFB Mouse");
@@ -388,7 +389,10 @@ static void input_disconnect(struct XenDevice *xendev)
 	qemu_remove_mouse_event_handler(in->qmouse);
 	in->qmouse = NULL;
     }
-    qemu_add_kbd_event_handler(NULL, NULL);
+    if (in->qkeyboard) {
+	qemu_remove_kbd_event_handler(in->qkeyboard);
+	in->qkeyboard = NULL;
+    }
     common_unbind(&in->c);
 }
 
diff --git a/vl.c b/vl.c
index eb2744e..1bb7d40 100644
--- a/vl.c
+++ b/vl.c
@@ -346,15 +346,57 @@ ram_addr_t qemu_balloon_status(void)
 /***********************************************************/
 /* keyboard/mouse */
 
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
+static QEMUPutKeyboardEntry *qemu_put_kbd_event_head;
 static QEMUPutMouseEntry *qemu_put_mouse_event_head;
 static QEMUPutMouseEntry *qemu_put_mouse_event_current;
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
+QEMUPutKeyboardEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
-    qemu_put_kbd_event_opaque = opaque;
-    qemu_put_kbd_event = func;
+    QEMUPutKeyboardEntry *s, *cursor;
+
+    s = qemu_mallocz(sizeof(QEMUPutKeyboardEntry));
+
+    s->qemu_put_kbd_event = func;
+    s->qemu_put_kbd_event_opaque = opaque;
+    s->next = NULL;
+
+    if (!qemu_put_kbd_event_head) {
+        qemu_put_kbd_event_head = s;
+        return s;
+    }
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor->next != NULL)
+        cursor = cursor->next;
+
+    cursor->next = s;
+
+    return s;
+}
+
+void qemu_remove_kbd_event_handler(QEMUPutKeyboardEntry *entry)
+{
+    QEMUPutKeyboardEntry *prev = NULL, *cursor;
+
+    if (!qemu_put_kbd_event_head || entry == NULL)
+        return;
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor != NULL && cursor != entry) {
+        prev = cursor;
+        cursor = cursor->next;
+    }
+
+    if (cursor == NULL) // does not exist or list empty
+        return;
+    else if (prev == NULL) { // entry is head
+        qemu_put_kbd_event_head = cursor->next;
+        qemu_free(entry);
+        return;
+    }
+
+    prev->next = entry->next;
+    qemu_free(entry);
 }
 
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
@@ -421,8 +463,12 @@ void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
 
 void kbd_put_keycode(int keycode)
 {
-    if (qemu_put_kbd_event) {
-        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+    QEMUPutKeyboardEntry *cursor;
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor != NULL) {
+        cursor->qemu_put_kbd_event(cursor->qemu_put_kbd_event_opaque, keycode);
+        cursor = cursor->next;
     }
 }
 
