All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] Qemu support for multiple keyboard devices - v2
@ 2010-03-23 19:57 Shahar Havivi
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices Shahar Havivi
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
  0 siblings, 2 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-23 19:57 UTC (permalink / raw)
  To: qemu-devel

* After Anthony patches, and Luiz comments

Qemu support for multiple keyboard devices:

Patch #1 adding keyboard is done to list instead of "last added keyboard 
         wins", when removing keyboard via device_del - next keyboard
         selected.

Patch #2 adding 2 new monitor command to handle keyboard list: 
         'info keyboard' - show all keyboards and mark the current one
         'keyboard_set'  - set active keyboard by index as display in
                           'info keyboard' 

Shahar Havivi (2):
  Support for multiple keyboard devices
  Added monitor commands: 'keyboard_set' and 'info keybaord'

 console.h            |   16 ++++-
 hw/adb.c             |    2 +-
 hw/escc.c            |    3 +-
 hw/musicpal.c        |    2 +-
 hw/nseries.c         |    4 +-
 hw/palm.c            |    2 +-
 hw/ps2.c             |    2 +-
 hw/pxa2xx_keypad.c   |    2 +-
 hw/spitz.c           |    2 +-
 hw/stellaris_input.c |    2 +-
 hw/syborg_keyboard.c |    2 +-
 hw/usb-hid.c         |   10 ++-
 hw/xenfb.c           |    4 +-
 input.c              |  194 +++++++++++++++++++++++++++++++++++++++++++++++---
 monitor.c            |    8 ++
 qemu-monitor.hx      |   17 +++++
 qerror.c             |    8 ++
 17 files changed, 253 insertions(+), 27 deletions(-)

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices
  2010-03-23 19:57 [Qemu-devel] [PATCH 0/2] Qemu support for multiple keyboard devices - v2 Shahar Havivi
@ 2010-03-23 19:58 ` Shahar Havivi
  2010-03-26  9:46   ` Markus Armbruster
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
  1 sibling, 1 reply; 20+ messages in thread
From: Shahar Havivi @ 2010-03-23 19:58 UTC (permalink / raw)
  To: qemu-devel

Currently you get segfault when trying to remove keyboard (device_del
monitor command) because no keyboard handling is done.

This patch add QEMUPutKbdEntry structure, handling each keyboard entry.
Adding a keyboard add to the list, removing keyboard select the previous
keyboard in list.

Signed-off-by: Shahar Havivi <shaharh@redhat.com>
---
 console.h            |   12 ++++++-
 hw/adb.c             |    2 +-
 hw/escc.c            |    3 +-
 hw/musicpal.c        |    2 +-
 hw/nseries.c         |    4 +-
 hw/palm.c            |    2 +-
 hw/ps2.c             |    2 +-
 hw/pxa2xx_keypad.c   |    2 +-
 hw/spitz.c           |    2 +-
 hw/stellaris_input.c |    2 +-
 hw/syborg_keyboard.c |    2 +-
 hw/usb-hid.c         |   10 ++++--
 hw/xenfb.c           |    4 +-
 input.c              |   90 ++++++++++++++++++++++++++++++++++++++++++++-----
 14 files changed, 112 insertions(+), 27 deletions(-)

diff --git a/console.h b/console.h
index 6def115..16c9c3d 100644
--- a/console.h
+++ b/console.h
@@ -41,7 +41,17 @@ typedef struct QEMUPutLEDEntry {
     QTAILQ_ENTRY(QEMUPutLEDEntry) next;
 } QEMUPutLEDEntry;
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+typedef struct QEMUPutKbdEntry {
+    char *qemu_put_kbd_name;
+    QEMUPutKBDEvent *qemu_put_kbd_event;
+    void *qemu_put_kbd_event_opaque;
+    struct QEMUPutKbdEntry *next;
+} QEMUPutKbdEntry;
+
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
+                                            void *opaque,
+                                            const char *name);
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62..09afcf9 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -304,7 +304,7 @@ void adb_kbd_init(ADBBusState *bus)
     s = qemu_mallocz(sizeof(KBDState));
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
-    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
+    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d, "adb");
     register_savevm("adb_kbd", -1, 1, adb_kbd_save,
                     adb_kbd_load, s);
 }
diff --git a/hw/escc.c b/hw/escc.c
index 6d2fd36..2b21d98 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -919,7 +919,8 @@ static int escc_init1(SysBusDevice *dev)
                                      "QEMU Sun Mouse");
     }
     if (s->chn[1].type == kbd) {
-        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
+        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1],
+                                   "QEMU Sun Keyboard");
     }
 
     return 0;
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 7fc9fb3..aca8a88 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1447,7 +1447,7 @@ static int musicpal_key_init(SysBusDevice *dev)
 
     qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
 
-    qemu_add_kbd_event_handler(musicpal_key_event, s);
+    qemu_add_kbd_event_handler(musicpal_key_event, s, "Musicpal");
 
     return 0;
 }
diff --git a/hw/nseries.c b/hw/nseries.c
index 0273eee..abfcec3 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -262,7 +262,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
         if (n800_keys[i] >= 0)
             s->keymap[n800_keys[i]] = i;
 
-    qemu_add_kbd_event_handler(n800_key_event, s);
+    qemu_add_kbd_event_handler(n800_key_event, s, "Nokia n800");
 
     tsc210x_set_transform(s->ts.chip, &n800_pointercal);
 }
@@ -371,7 +371,7 @@ static void n810_kbd_setup(struct n800_s *s)
         if (n810_keys[i] > 0)
             s->keymap[n810_keys[i]] = i;
 
-    qemu_add_kbd_event_handler(n810_key_event, s);
+    qemu_add_kbd_event_handler(n810_key_event, s, "Nokia n810");
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
diff --git a/hw/palm.c b/hw/palm.c
index 6d19167..1b405d4 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -228,7 +228,7 @@ static void palmte_init(ram_addr_t ram_size,
 
     palmte_microwire_setup(cpu);
 
-    qemu_add_kbd_event_handler(palmte_button_event, cpu);
+    qemu_add_kbd_event_handler(palmte_button_event, cpu, "Palm Keyboard");
 
     palmte_gpio_setup(cpu);
 
diff --git a/hw/ps2.c b/hw/ps2.c
index f0b206a..886da37 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -596,7 +596,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
     vmstate_register(0, &vmstate_ps2_keyboard, s);
-    qemu_add_kbd_event_handler(ps2_put_keycode, s);
+    qemu_add_kbd_event_handler(ps2_put_keycode, s, "QEMU PS/2 Keyboard");
     qemu_register_reset(ps2_kbd_reset, s);
     return s;
 }
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 060df58..7fa5af9 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -332,5 +332,5 @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp, struct keymap *map,
     }
 
     kp->map = map;
-    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) pxa27x_keyboard_event, kp);
+    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) pxa27x_keyboard_event, kp, "PXA keypad");
 }
diff --git a/hw/spitz.c b/hw/spitz.c
index 564519b..64e8a6e 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -506,7 +506,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
         pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i], s->strobe[i]);
 
     spitz_keyboard_pre_map(s);
-    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
+    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s, "Spitz keyboard");
 
     register_savevm("spitz_keyboard", 0, 0,
                     spitz_keyboard_save, spitz_keyboard_load, s);
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 33395a4..775cb46 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -85,7 +85,7 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
         s->buttons[i].keycode = keycode[i];
     }
     s->num_buttons = n;
-    qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
+    qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s, "Stellaris Gamepad");
     register_savevm("stellaris_gamepad", -1, 1,
                     stellaris_gamepad_save, stellaris_gamepad_load, s);
 }
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 4a562f8..d1651b4 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -218,7 +218,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
     }
     s->key_fifo = qemu_mallocz(s->fifo_size * sizeof(s->key_fifo[0]));
 
-    qemu_add_kbd_event_handler(syborg_keyboard_event, s);
+    qemu_add_kbd_event_handler(syborg_keyboard_event, s, "Syborg Keyboard");
 
     register_savevm("syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8e6c6e0..dbab5d3 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -55,6 +55,7 @@ typedef struct USBKeyboardState {
     uint8_t leds;
     uint8_t key[16];
     int keys;
+    QEMUPutKbdEntry *eh_entry;
 } USBKeyboardState;
 
 typedef struct USBHIDState {
@@ -633,7 +634,8 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    qemu_add_kbd_event_handler(usb_keyboard_event, s);
+    s->kbd.eh_entry = qemu_add_kbd_event_handler(usb_keyboard_event, s,
+                                                 dev->product_desc);
     s->protocol = 1;
 }
 
@@ -854,9 +856,11 @@ static void usb_hid_handle_destroy(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    if (s->kind != USB_KEYBOARD)
+    if (s->kind != USB_KEYBOARD) {
         qemu_remove_mouse_event_handler(s->ptr.eh_entry);
-    /* TODO: else */
+    } else {
+        qemu_remove_kbd_event_handler(s->kbd.eh_entry);
+    }
 }
 
 static int usb_hid_initfn(USBDevice *dev, int kind)
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 422cd53..2c700bd 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -373,7 +373,7 @@ static int input_connect(struct XenDevice *xendev)
     if (rc != 0)
 	return rc;
 
-    qemu_add_kbd_event_handler(xenfb_key_event, in);
+    qemu_add_kbd_event_handler(xenfb_key_event, in, "Xen Keyboard");
     in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
 					      in->abs_pointer_wanted,
 					      "Xen PVFB Mouse");
@@ -388,7 +388,7 @@ static void input_disconnect(struct XenDevice *xendev)
 	qemu_remove_mouse_event_handler(in->qmouse);
 	in->qmouse = NULL;
     }
-    qemu_add_kbd_event_handler(NULL, NULL);
+    qemu_add_kbd_event_handler(NULL, NULL, NULL);
     common_unbind(&in->c);
 }
 
diff --git a/input.c b/input.c
index 8f0941e..563ecad 100644
--- a/input.c
+++ b/input.c
@@ -28,20 +28,14 @@
 #include "console.h"
 #include "qjson.h"
 
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
+static QEMUPutKbdEntry *qemu_put_kbd_event_head;
+static QEMUPutKbdEntry *qemu_put_kbd_event_current;
 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
 static NotifierList mouse_mode_notifiers = 
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-{
-    qemu_put_kbd_event_opaque = opaque;
-    qemu_put_kbd_event = func;
-}
-
 static void check_mode_change(void)
 {
     static int current_is_absolute, current_has_absolute;
@@ -60,6 +54,81 @@ static void check_mode_change(void)
     current_has_absolute = has_absolute;
 }
 
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
+                                            void *opaque,
+                                            const char *name)
+{
+    QEMUPutKbdEntry *s, *cursor;
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor) {
+        if (cursor->qemu_put_kbd_event == func &&
+            cursor->qemu_put_kbd_event_opaque == opaque) {
+
+            qemu_put_kbd_event_current = cursor;
+            return cursor;
+        }
+        cursor = cursor->next;
+    }
+
+    s = qemu_mallocz(sizeof(QEMUPutKbdEntry));
+
+    s->qemu_put_kbd_event_opaque = opaque;
+    s->qemu_put_kbd_event = func;
+    s->qemu_put_kbd_name = qemu_strdup(name);
+    s->next = NULL;
+
+    if (!qemu_put_kbd_event_head) {
+        qemu_put_kbd_event_head = s;
+        qemu_put_kbd_event_current = s;
+        return s;
+    }
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor->next) {
+        cursor = cursor->next;
+    }
+
+    cursor->next = s;
+    qemu_put_kbd_event_current = s;
+
+    return s;
+}
+
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
+{
+    QEMUPutKbdEntry *prev = NULL, *cursor;
+
+    if (!qemu_put_kbd_event_head || !entry) {
+        return;
+    }
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor && cursor != entry) {
+        prev = cursor;
+        cursor = cursor->next;
+    }
+
+    if (cursor == NULL) {
+        return;
+    } else if (prev == NULL) {
+        qemu_put_kbd_event_head = cursor->next;
+        if (qemu_put_kbd_event_current == entry) {
+            qemu_put_kbd_event_current = cursor->next;
+        }
+        qemu_free(entry);
+        return;
+    }
+
+    prev->next = entry->next;
+
+    if (qemu_put_kbd_event_current == entry) {
+        qemu_put_kbd_event_current = prev;
+    }
+
+    qemu_free(entry);
+}
+
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name)
@@ -123,8 +192,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
 
 void kbd_put_keycode(int keycode)
 {
-    if (qemu_put_kbd_event) {
-        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+    if (qemu_put_kbd_event_current) {
+        qemu_put_kbd_event_current->qemu_put_kbd_event(
+            qemu_put_kbd_event_current->qemu_put_kbd_event_opaque, keycode);
     }
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-23 19:57 [Qemu-devel] [PATCH 0/2] Qemu support for multiple keyboard devices - v2 Shahar Havivi
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices Shahar Havivi
@ 2010-03-23 19:58 ` Shahar Havivi
  2010-03-26  9:57   ` Markus Armbruster
  1 sibling, 1 reply; 20+ messages in thread
From: Shahar Havivi @ 2010-03-23 19:58 UTC (permalink / raw)
  To: qemu-devel

Two new monitor commands: adding ability to handle which keyboard qemu will
use and to see which keyboard are currently available.

$ info keyboard
$ keyboard_set <index>

Signed-off-by: Shahar Havivi <shaharh@redhat.com>
---
 console.h       |    4 ++
 input.c         |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 monitor.c       |    8 ++++
 qemu-monitor.hx |   17 +++++++++
 qerror.c        |    8 ++++
 5 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/console.h b/console.h
index 16c9c3d..7efa88e 100644
--- a/console.h
+++ b/console.h
@@ -85,6 +85,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
 void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
+void do_info_keyboard_print(Monitor *mon, const QObject *data);
+void do_info_keyboard(Monitor *mon, QObject **ret_data);
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
diff --git a/input.c b/input.c
index 563ecad..4daaeb0 100644
--- a/input.c
+++ b/input.c
@@ -368,3 +368,107 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
 {
     notifier_list_remove(&mouse_mode_notifiers, notify);
 }
+
+static void info_keyboard_iter(QObject *data, void *opaque)
+{
+    QDict *kbd;
+    Monitor *mon = opaque;
+
+    kbd = qobject_to_qdict(data);
+    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
+                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
+                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
+}
+
+void do_info_keyboard_print(Monitor *mon, const QObject *data)
+{
+    QList *kbd_list;
+
+    kbd_list = qobject_to_qlist(data);
+    if (qlist_empty(kbd_list)) {
+        monitor_printf(mon, "No keyboard devices connected\n");
+        return;
+    }
+
+    qlist_iter(kbd_list, info_keyboard_iter, mon);
+}
+
+/*
+ * do_info_keyboard(): Show VM keyboard information
+ *
+ * Each keyboard is represented by a QDict, the returned QObject is
+ * a QList of all keyboards.
+ *
+ * The keyboard QDict contains the following:
+ *
+ * - "name": keyboard's name
+ * - "index": keyboard's index
+ * - "current": true if this keyboard is receiving events, false otherwise
+ *
+ * Example:
+ *
+ * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
+ *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
+ */
+void do_info_keyboard(Monitor *mon, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    QList *kbd_list;
+    int index = 0;
+
+    kbd_list = qlist_new();
+
+    if (!qemu_put_kbd_event_head) {
+        goto out;
+    }
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor != NULL) {
+        QObject *obj;
+        obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
+                                 cursor->qemu_put_kbd_name,
+                                 index, cursor == qemu_put_kbd_event_current);
+        qlist_append_obj(kbd_list, obj);
+        index++;
+        cursor = cursor->next;
+    }
+out:
+    *ret_data = QOBJECT(kbd_list);
+}
+
+/*
+ * do_keyboard_set(): Set active keyboard
+ *
+ * Argument qdict contains
+ * - "index": the keyboard index to set
+ *
+ * Example:
+ *
+ * { "index": "0" }
+ */
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    int i = 0;
+    int index = qdict_get_int(qdict, "index");
+
+    if (!qemu_put_kbd_event_head) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
+        return -1;
+    }
+
+    cursor = qemu_put_kbd_event_head;
+    while (cursor != NULL && index != i) {
+        i++;
+        cursor = cursor->next;
+    }
+
+    if (cursor != NULL) {
+        qemu_put_kbd_event_current = cursor;
+    }
+    else {
+        qerror_report(QERR_INVALID_PARAMETER, "index");
+        return -1;
+    }
+    return 0;
+}
diff --git a/monitor.c b/monitor.c
index 0448a70..cc95b3d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2783,6 +2783,14 @@ static const mon_cmd_t info_cmds[] = {
         .mhandler.info_new = do_info_mice,
     },
     {
+        .name       = "keyboard",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show which guest keyboard is receiving events",
+        .user_print = do_info_keyboard_print,
+        .mhandler.info_new = do_info_keyboard,
+    },
+    {
         .name       = "vnc",
         .args_type  = "",
         .params     = "",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5308f36..e9beb12 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -659,6 +659,23 @@ info mice
 @end example
 ETEXI
 
+    {
+        .name       = "keyboard_set",
+        .args_type  = "index:i",
+        .params     = "index",
+        .help       = "set which keyboard device receives events",
+        .mhandler.cmd_new = do_keyboard_set,
+    },
+
+STEXI
+@item keyboard_set @var{index}
+@findex keyboard_set
+Set which keyboard device receives events at given @var{index}, index
+can be obtained with
+@example
+info keyboard
+@end example
+ETEXI
 #ifdef HAS_AUDIO
     {
         .name       = "wavcapture",
diff --git a/qerror.c b/qerror.c
index d0aba61..42a5cf7 100644
--- a/qerror.c
+++ b/qerror.c
@@ -172,6 +172,14 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
+    {
+        .error_fmt = QERR_DEVICE_NOT_FOUND,
+        .desc      = "No keyboard device found",
+    },
+    {
+        .error_fmt = QERR_INVALID_PARAMETER,
+        .desc      = "Invalid index '%(name)' for keyboard device",
+    },
     {}
 };
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices Shahar Havivi
@ 2010-03-26  9:46   ` Markus Armbruster
  2010-03-27 15:56     ` Shahar Havivi
  0 siblings, 1 reply; 20+ messages in thread
From: Markus Armbruster @ 2010-03-26  9:46 UTC (permalink / raw)
  To: Shahar Havivi; +Cc: qemu-devel

Shahar Havivi <shaharh@redhat.com> writes:

> Currently you get segfault when trying to remove keyboard (device_del
> monitor command) because no keyboard handling is done.
>
> This patch add QEMUPutKbdEntry structure, handling each keyboard entry.
> Adding a keyboard add to the list, removing keyboard select the previous
> keyboard in list.
>
> Signed-off-by: Shahar Havivi <shaharh@redhat.com>
> ---
>  console.h            |   12 ++++++-
>  hw/adb.c             |    2 +-
>  hw/escc.c            |    3 +-
>  hw/musicpal.c        |    2 +-
>  hw/nseries.c         |    4 +-
>  hw/palm.c            |    2 +-
>  hw/ps2.c             |    2 +-
>  hw/pxa2xx_keypad.c   |    2 +-
>  hw/spitz.c           |    2 +-
>  hw/stellaris_input.c |    2 +-
>  hw/syborg_keyboard.c |    2 +-
>  hw/usb-hid.c         |   10 ++++--
>  hw/xenfb.c           |    4 +-
>  input.c              |   90 ++++++++++++++++++++++++++++++++++++++++++++-----
>  14 files changed, 112 insertions(+), 27 deletions(-)
>
> diff --git a/console.h b/console.h
> index 6def115..16c9c3d 100644
> --- a/console.h
> +++ b/console.h
> @@ -41,7 +41,17 @@ typedef struct QEMUPutLEDEntry {
>      QTAILQ_ENTRY(QEMUPutLEDEntry) next;
>  } QEMUPutLEDEntry;
>  
> -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
> +typedef struct QEMUPutKbdEntry {
> +    char *qemu_put_kbd_name;
> +    QEMUPutKBDEvent *qemu_put_kbd_event;
> +    void *qemu_put_kbd_event_opaque;
> +    struct QEMUPutKbdEntry *next;
> +} QEMUPutKbdEntry;
> +
> +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
> +                                            void *opaque,
> +                                            const char *name);
> +void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
>  QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
>                                                  void *opaque, int absolute,
>                                                  const char *name);
[...]
> diff --git a/input.c b/input.c
> index 8f0941e..563ecad 100644
> --- a/input.c
> +++ b/input.c
> @@ -28,20 +28,14 @@
>  #include "console.h"
>  #include "qjson.h"
>  
> -static QEMUPutKBDEvent *qemu_put_kbd_event;
> -static void *qemu_put_kbd_event_opaque;
> +static QEMUPutKbdEntry *qemu_put_kbd_event_head;
> +static QEMUPutKbdEntry *qemu_put_kbd_event_current;
>  static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
>  static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
>      QTAILQ_HEAD_INITIALIZER(mouse_handlers);
>  static NotifierList mouse_mode_notifiers = 
>      NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
>  
> -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
> -{
> -    qemu_put_kbd_event_opaque = opaque;
> -    qemu_put_kbd_event = func;
> -}
> -
>  static void check_mode_change(void)
>  {
>      static int current_is_absolute, current_has_absolute;
> @@ -60,6 +54,81 @@ static void check_mode_change(void)
>      current_has_absolute = has_absolute;
>  }
>  
> +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
> +                                            void *opaque,
> +                                            const char *name)
> +{
> +    QEMUPutKbdEntry *s, *cursor;
> +
> +    cursor = qemu_put_kbd_event_head;
> +    while (cursor) {
> +        if (cursor->qemu_put_kbd_event == func &&
> +            cursor->qemu_put_kbd_event_opaque == opaque) {
> +
> +            qemu_put_kbd_event_current = cursor;
> +            return cursor;
> +        }
> +        cursor = cursor->next;
> +    }

You're chasing list pointers.  Why not use a suitable list type from
qemu-queue.h?

> +
> +    s = qemu_mallocz(sizeof(QEMUPutKbdEntry));
> +
> +    s->qemu_put_kbd_event_opaque = opaque;
> +    s->qemu_put_kbd_event = func;
> +    s->qemu_put_kbd_name = qemu_strdup(name);
> +    s->next = NULL;
> +
> +    if (!qemu_put_kbd_event_head) {
> +        qemu_put_kbd_event_head = s;
> +        qemu_put_kbd_event_current = s;
> +        return s;
> +    }
> +
> +    cursor = qemu_put_kbd_event_head;
> +    while (cursor->next) {
> +        cursor = cursor->next;
> +    }
> +
> +    cursor->next = s;
> +    qemu_put_kbd_event_current = s;
> +
> +    return s;
> +}
> +
> +void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
> +{
> +    QEMUPutKbdEntry *prev = NULL, *cursor;
> +
> +    if (!qemu_put_kbd_event_head || !entry) {
> +        return;
> +    }
> +
> +    cursor = qemu_put_kbd_event_head;
> +    while (cursor && cursor != entry) {
> +        prev = cursor;
> +        cursor = cursor->next;
> +    }
> +
> +    if (cursor == NULL) {
> +        return;
> +    } else if (prev == NULL) {
> +        qemu_put_kbd_event_head = cursor->next;
> +        if (qemu_put_kbd_event_current == entry) {
> +            qemu_put_kbd_event_current = cursor->next;
> +        }
> +        qemu_free(entry);
> +        return;
> +    }
> +
> +    prev->next = entry->next;
> +
> +    if (qemu_put_kbd_event_current == entry) {
> +        qemu_put_kbd_event_current = prev;
> +    }
> +
> +    qemu_free(entry);

More list pointer chasing.

> +}
> +
>  QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
>                                                  void *opaque, int absolute,
>                                                  const char *name)
> @@ -123,8 +192,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
>  
>  void kbd_put_keycode(int keycode)
>  {
> -    if (qemu_put_kbd_event) {
> -        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
> +    if (qemu_put_kbd_event_current) {
> +        qemu_put_kbd_event_current->qemu_put_kbd_event(
> +            qemu_put_kbd_event_current->qemu_put_kbd_event_opaque, keycode);
>      }
>  }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-23 19:58 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
@ 2010-03-26  9:57   ` Markus Armbruster
  2010-03-26 18:40     ` Shahar Havivi
  2010-03-27 18:15     ` [Qemu-devel] " Shahar Havivi
  0 siblings, 2 replies; 20+ messages in thread
From: Markus Armbruster @ 2010-03-26  9:57 UTC (permalink / raw)
  To: Shahar Havivi; +Cc: qemu-devel

Shahar Havivi <shaharh@redhat.com> writes:

> Two new monitor commands: adding ability to handle which keyboard qemu will
> use and to see which keyboard are currently available.
>
> $ info keyboard
> $ keyboard_set <index>
>
> Signed-off-by: Shahar Havivi <shaharh@redhat.com>
> ---
>  console.h       |    4 ++
>  input.c         |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  monitor.c       |    8 ++++
>  qemu-monitor.hx |   17 +++++++++
>  qerror.c        |    8 ++++
>  5 files changed, 141 insertions(+), 0 deletions(-)
>
> diff --git a/console.h b/console.h
> index 16c9c3d..7efa88e 100644
> --- a/console.h
> +++ b/console.h
> @@ -85,6 +85,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
>  void do_info_mice(Monitor *mon, QObject **ret_data);
>  void do_mouse_set(Monitor *mon, const QDict *qdict);
>  
> +void do_info_keyboard_print(Monitor *mon, const QObject *data);
> +void do_info_keyboard(Monitor *mon, QObject **ret_data);
> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
> +
>  /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
>     constants) */
>  #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
> diff --git a/input.c b/input.c
> index 563ecad..4daaeb0 100644
> --- a/input.c
> +++ b/input.c
> @@ -368,3 +368,107 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
>  {
>      notifier_list_remove(&mouse_mode_notifiers, notify);
>  }
> +
> +static void info_keyboard_iter(QObject *data, void *opaque)
> +{
> +    QDict *kbd;
> +    Monitor *mon = opaque;
> +
> +    kbd = qobject_to_qdict(data);
> +    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
> +                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
> +                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
> +}
> +
> +void do_info_keyboard_print(Monitor *mon, const QObject *data)
> +{
> +    QList *kbd_list;
> +
> +    kbd_list = qobject_to_qlist(data);
> +    if (qlist_empty(kbd_list)) {
> +        monitor_printf(mon, "No keyboard devices connected\n");
> +        return;
> +    }
> +
> +    qlist_iter(kbd_list, info_keyboard_iter, mon);
> +}
> +
> +/*
> + * do_info_keyboard(): Show VM keyboard information
> + *
> + * Each keyboard is represented by a QDict, the returned QObject is
> + * a QList of all keyboards.
> + *
> + * The keyboard QDict contains the following:
> + *
> + * - "name": keyboard's name
> + * - "index": keyboard's index
> + * - "current": true if this keyboard is receiving events, false otherwise
> + *
> + * Example:
> + *
> + * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
> + *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
> + */
> +void do_info_keyboard(Monitor *mon, QObject **ret_data)
> +{
> +    QEMUPutKbdEntry *cursor;
> +    QList *kbd_list;
> +    int index = 0;
> +
> +    kbd_list = qlist_new();
> +
> +    if (!qemu_put_kbd_event_head) {
> +        goto out;
> +    }
> +
> +    cursor = qemu_put_kbd_event_head;
> +    while (cursor != NULL) {
> +        QObject *obj;
> +        obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
> +                                 cursor->qemu_put_kbd_name,
> +                                 index, cursor == qemu_put_kbd_event_current);
> +        qlist_append_obj(kbd_list, obj);
> +        index++;
> +        cursor = cursor->next;
> +    }
> +out:
> +    *ret_data = QOBJECT(kbd_list);
> +}

Keyboard indexes change when keyboards other than the last one get
removed.  Hmm.

> +
> +/*
> + * do_keyboard_set(): Set active keyboard
> + *
> + * Argument qdict contains
> + * - "index": the keyboard index to set
> + *
> + * Example:
> + *
> + * { "index": "0" }
> + */
> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
> +{
> +    QEMUPutKbdEntry *cursor;
> +    int i = 0;
> +    int index = qdict_get_int(qdict, "index");
> +
> +    if (!qemu_put_kbd_event_head) {
> +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
> +        return -1;
> +    }
> +
> +    cursor = qemu_put_kbd_event_head;
> +    while (cursor != NULL && index != i) {
> +        i++;
> +        cursor = cursor->next;
> +    }
> +
> +    if (cursor != NULL) {
> +        qemu_put_kbd_event_current = cursor;
> +    }
> +    else {
> +        qerror_report(QERR_INVALID_PARAMETER, "index");
> +        return -1;
> +    }
> +    return 0;
> +}

Since the index is not a stable identifier of keyboards, and we support
multiple monitors, you're prone to remove the wrong keyboard.

    Monitor#1                           Monitor#2
    "info keyboard" to find the index
                                        unplug a keyboard, invalidating
                                        index
    keyboard_set <index>

I think it's best to use a stable ID, like we do in other places.  We
commonly let the user specify it, e.g. as id=ID in -netdev, -device and
elswhere.

> diff --git a/monitor.c b/monitor.c
> index 0448a70..cc95b3d 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2783,6 +2783,14 @@ static const mon_cmd_t info_cmds[] = {
>          .mhandler.info_new = do_info_mice,
>      },
>      {
> +        .name       = "keyboard",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show which guest keyboard is receiving events",
> +        .user_print = do_info_keyboard_print,
> +        .mhandler.info_new = do_info_keyboard,
> +    },
> +    {
>          .name       = "vnc",
>          .args_type  = "",
>          .params     = "",
> diff --git a/qemu-monitor.hx b/qemu-monitor.hx
> index 5308f36..e9beb12 100644
> --- a/qemu-monitor.hx
> +++ b/qemu-monitor.hx
> @@ -659,6 +659,23 @@ info mice
>  @end example
>  ETEXI
>  
> +    {
> +        .name       = "keyboard_set",
> +        .args_type  = "index:i",
> +        .params     = "index",
> +        .help       = "set which keyboard device receives events",
> +        .mhandler.cmd_new = do_keyboard_set,
> +    },
> +
> +STEXI
> +@item keyboard_set @var{index}
> +@findex keyboard_set
> +Set which keyboard device receives events at given @var{index}, index
> +can be obtained with
> +@example
> +info keyboard
> +@end example
> +ETEXI
>  #ifdef HAS_AUDIO
>      {
>          .name       = "wavcapture",
> diff --git a/qerror.c b/qerror.c
> index d0aba61..42a5cf7 100644
> --- a/qerror.c
> +++ b/qerror.c
> @@ -172,6 +172,14 @@ static const QErrorStringTable qerror_table[] = {
>          .error_fmt = QERR_VNC_SERVER_FAILED,
>          .desc      = "Could not start VNC server on %(target)",
>      },
> +    {
> +        .error_fmt = QERR_DEVICE_NOT_FOUND,
> +        .desc      = "No keyboard device found",
> +    },
> +    {
> +        .error_fmt = QERR_INVALID_PARAMETER,
> +        .desc      = "Invalid index '%(name)' for keyboard device",
> +    },
>      {}
>  };

I'm afraid you're breaking all other uses of these errors here.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-26  9:57   ` Markus Armbruster
@ 2010-03-26 18:40     ` Shahar Havivi
  2010-03-31 15:10       ` Markus Armbruster
  2010-03-27 18:15     ` [Qemu-devel] " Shahar Havivi
  1 sibling, 1 reply; 20+ messages in thread
From: Shahar Havivi @ 2010-03-26 18:40 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

On Fri, Mar 26, 2010 at 10:57:58AM +0100, Markus Armbruster wrote:
> Date: Fri, 26 Mar 2010 10:57:58 +0100
> From: Markus Armbruster <armbru@redhat.com>
> To: Shahar Havivi <shaharh@redhat.com>
> Cc: qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] [PATCH 2/2] Added monitor commands:
>  'keyboard_set' and 'info keybaord'
> 
> Shahar Havivi <shaharh@redhat.com> writes:
> 
> > Two new monitor commands: adding ability to handle which keyboard qemu will
> > use and to see which keyboard are currently available.
> >
> > $ info keyboard
> > $ keyboard_set <index>
> >
> > Signed-off-by: Shahar Havivi <shaharh@redhat.com>
> > ---
> >  console.h       |    4 ++
> >  input.c         |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  monitor.c       |    8 ++++
> >  qemu-monitor.hx |   17 +++++++++
> >  qerror.c        |    8 ++++
> >  5 files changed, 141 insertions(+), 0 deletions(-)
> >
> > diff --git a/console.h b/console.h
> > index 16c9c3d..7efa88e 100644
> > --- a/console.h
> > +++ b/console.h
> > @@ -85,6 +85,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
> >  void do_info_mice(Monitor *mon, QObject **ret_data);
> >  void do_mouse_set(Monitor *mon, const QDict *qdict);
> >  
> > +void do_info_keyboard_print(Monitor *mon, const QObject *data);
> > +void do_info_keyboard(Monitor *mon, QObject **ret_data);
> > +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
> > +
> >  /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
> >     constants) */
> >  #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
> > diff --git a/input.c b/input.c
> > index 563ecad..4daaeb0 100644
> > --- a/input.c
> > +++ b/input.c
> > @@ -368,3 +368,107 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
> >  {
> >      notifier_list_remove(&mouse_mode_notifiers, notify);
> >  }
> > +
> > +static void info_keyboard_iter(QObject *data, void *opaque)
> > +{
> > +    QDict *kbd;
> > +    Monitor *mon = opaque;
> > +
> > +    kbd = qobject_to_qdict(data);
> > +    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
> > +                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
> > +                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
> > +}
> > +
> > +void do_info_keyboard_print(Monitor *mon, const QObject *data)
> > +{
> > +    QList *kbd_list;
> > +
> > +    kbd_list = qobject_to_qlist(data);
> > +    if (qlist_empty(kbd_list)) {
> > +        monitor_printf(mon, "No keyboard devices connected\n");
> > +        return;
> > +    }
> > +
> > +    qlist_iter(kbd_list, info_keyboard_iter, mon);
> > +}
> > +
> > +/*
> > + * do_info_keyboard(): Show VM keyboard information
> > + *
> > + * Each keyboard is represented by a QDict, the returned QObject is
> > + * a QList of all keyboards.
> > + *
> > + * The keyboard QDict contains the following:
> > + *
> > + * - "name": keyboard's name
> > + * - "index": keyboard's index
> > + * - "current": true if this keyboard is receiving events, false otherwise
> > + *
> > + * Example:
> > + *
> > + * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
> > + *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
> > + */
> > +void do_info_keyboard(Monitor *mon, QObject **ret_data)
> > +{
> > +    QEMUPutKbdEntry *cursor;
> > +    QList *kbd_list;
> > +    int index = 0;
> > +
> > +    kbd_list = qlist_new();
> > +
> > +    if (!qemu_put_kbd_event_head) {
> > +        goto out;
> > +    }
> > +
> > +    cursor = qemu_put_kbd_event_head;
> > +    while (cursor != NULL) {
> > +        QObject *obj;
> > +        obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
> > +                                 cursor->qemu_put_kbd_name,
> > +                                 index, cursor == qemu_put_kbd_event_current);
> > +        qlist_append_obj(kbd_list, obj);
> > +        index++;
> > +        cursor = cursor->next;
> > +    }
> > +out:
> > +    *ret_data = QOBJECT(kbd_list);
> > +}
> 
> Keyboard indexes change when keyboards other than the last one get
> removed.  Hmm.
> 
> > +
> > +/*
> > + * do_keyboard_set(): Set active keyboard
> > + *
> > + * Argument qdict contains
> > + * - "index": the keyboard index to set
> > + *
> > + * Example:
> > + *
> > + * { "index": "0" }
> > + */
> > +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
> > +{
> > +    QEMUPutKbdEntry *cursor;
> > +    int i = 0;
> > +    int index = qdict_get_int(qdict, "index");
> > +
> > +    if (!qemu_put_kbd_event_head) {
> > +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
> > +        return -1;
> > +    }
> > +
> > +    cursor = qemu_put_kbd_event_head;
> > +    while (cursor != NULL && index != i) {
> > +        i++;
> > +        cursor = cursor->next;
> > +    }
> > +
> > +    if (cursor != NULL) {
> > +        qemu_put_kbd_event_current = cursor;
> > +    }
> > +    else {
> > +        qerror_report(QERR_INVALID_PARAMETER, "index");
> > +        return -1;
> > +    }
> > +    return 0;
> > +}
> 
> Since the index is not a stable identifier of keyboards, and we support
> multiple monitors, you're prone to remove the wrong keyboard.
> 
>     Monitor#1                           Monitor#2
>     "info keyboard" to find the index
>                                         unplug a keyboard, invalidating
>                                         index
>     keyboard_set <index>
> 
> I think it's best to use a stable ID, like we do in other places.  We
> commonly let the user specify it, e.g. as id=ID in -netdev, -device and
> elswhere.
What do we do when user not specify id for device?
> 
> > diff --git a/monitor.c b/monitor.c
> > index 0448a70..cc95b3d 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -2783,6 +2783,14 @@ static const mon_cmd_t info_cmds[] = {
> >          .mhandler.info_new = do_info_mice,
> >      },
> >      {
> > +        .name       = "keyboard",
> > +        .args_type  = "",
> > +        .params     = "",
> > +        .help       = "show which guest keyboard is receiving events",
> > +        .user_print = do_info_keyboard_print,
> > +        .mhandler.info_new = do_info_keyboard,
> > +    },
> > +    {
> >          .name       = "vnc",
> >          .args_type  = "",
> >          .params     = "",
> > diff --git a/qemu-monitor.hx b/qemu-monitor.hx
> > index 5308f36..e9beb12 100644
> > --- a/qemu-monitor.hx
> > +++ b/qemu-monitor.hx
> > @@ -659,6 +659,23 @@ info mice
> >  @end example
> >  ETEXI
> >  
> > +    {
> > +        .name       = "keyboard_set",
> > +        .args_type  = "index:i",
> > +        .params     = "index",
> > +        .help       = "set which keyboard device receives events",
> > +        .mhandler.cmd_new = do_keyboard_set,
> > +    },
> > +
> > +STEXI
> > +@item keyboard_set @var{index}
> > +@findex keyboard_set
> > +Set which keyboard device receives events at given @var{index}, index
> > +can be obtained with
> > +@example
> > +info keyboard
> > +@end example
> > +ETEXI
> >  #ifdef HAS_AUDIO
> >      {
> >          .name       = "wavcapture",
> > diff --git a/qerror.c b/qerror.c
> > index d0aba61..42a5cf7 100644
> > --- a/qerror.c
> > +++ b/qerror.c
> > @@ -172,6 +172,14 @@ static const QErrorStringTable qerror_table[] = {
> >          .error_fmt = QERR_VNC_SERVER_FAILED,
> >          .desc      = "Could not start VNC server on %(target)",
> >      },
> > +    {
> > +        .error_fmt = QERR_DEVICE_NOT_FOUND,
> > +        .desc      = "No keyboard device found",
> > +    },
> > +    {
> > +        .error_fmt = QERR_INVALID_PARAMETER,
> > +        .desc      = "Invalid index '%(name)' for keyboard device",
> > +    },
> >      {}
> >  };
> 
> I'm afraid you're breaking all other uses of these errors here.
you right, my bad - this errors where not meant to be in this patch.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices
  2010-03-26  9:46   ` Markus Armbruster
@ 2010-03-27 15:56     ` Shahar Havivi
  0 siblings, 0 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-27 15:56 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

On Fri, Mar 26, 2010 at 10:46:14AM +0100, Markus Armbruster wrote:
> > +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
> > +                                            void *opaque,
> > +                                            const char *name)
> > +{
> > +    QEMUPutKbdEntry *s, *cursor;
> > +
> > +    cursor = qemu_put_kbd_event_head;
> > +    while (cursor) {
> > +        if (cursor->qemu_put_kbd_event == func &&
> > +            cursor->qemu_put_kbd_event_opaque == opaque) {
> > +
> > +            qemu_put_kbd_event_current = cursor;
> > +            return cursor;
> > +        }
> > +        cursor = cursor->next;
> > +    }
> 
> You're chasing list pointers.  Why not use a suitable list type from
> qemu-queue.h?
> 
Change keyboard list to qemu tail queue.

---
 console.h            |   12 ++++++++++-
 hw/adb.c             |    2 +-
 hw/escc.c            |    3 +-
 hw/musicpal.c        |    2 +-
 hw/nseries.c         |    4 +-
 hw/palm.c            |    2 +-
 hw/ps2.c             |    2 +-
 hw/pxa2xx_keypad.c   |    2 +-
 hw/spitz.c           |    2 +-
 hw/stellaris_input.c |    2 +-
 hw/syborg_keyboard.c |    2 +-
 hw/usb-hid.c         |   10 ++++++--
 hw/xenfb.c           |    4 +-
 input.c              |   51 ++++++++++++++++++++++++++++++++++++++++---------
 14 files changed, 73 insertions(+), 27 deletions(-)

diff --git a/console.h b/console.h
index 6def115..7d19407 100644
--- a/console.h
+++ b/console.h
@@ -41,7 +41,17 @@ typedef struct QEMUPutLEDEntry {
     QTAILQ_ENTRY(QEMUPutLEDEntry) next;
 } QEMUPutLEDEntry;
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+typedef struct QEMUPutKbdEntry {
+    char *qemu_put_kbd_name;
+    QEMUPutKBDEvent *qemu_put_kbd_event;
+    void *qemu_put_kbd_event_opaque;
+    QTAILQ_ENTRY(QEMUPutKbdEntry) entry;
+} QEMUPutKbdEntry;
+
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
+                                            void *opaque,
+                                            const char *name);
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62..09afcf9 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -304,7 +304,7 @@ void adb_kbd_init(ADBBusState *bus)
     s = qemu_mallocz(sizeof(KBDState));
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
-    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
+    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d, "adb");
     register_savevm("adb_kbd", -1, 1, adb_kbd_save,
                     adb_kbd_load, s);
 }
diff --git a/hw/escc.c b/hw/escc.c
index 6d2fd36..2b21d98 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -919,7 +919,8 @@ static int escc_init1(SysBusDevice *dev)
                                      "QEMU Sun Mouse");
     }
     if (s->chn[1].type == kbd) {
-        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
+        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1],
+                                   "QEMU Sun Keyboard");
     }
 
     return 0;
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 7fc9fb3..aca8a88 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1447,7 +1447,7 @@ static int musicpal_key_init(SysBusDevice *dev)
 
     qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
 
-    qemu_add_kbd_event_handler(musicpal_key_event, s);
+    qemu_add_kbd_event_handler(musicpal_key_event, s, "Musicpal");
 
     return 0;
 }
diff --git a/hw/nseries.c b/hw/nseries.c
index 0273eee..abfcec3 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -262,7 +262,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
         if (n800_keys[i] >= 0)
             s->keymap[n800_keys[i]] = i;
 
-    qemu_add_kbd_event_handler(n800_key_event, s);
+    qemu_add_kbd_event_handler(n800_key_event, s, "Nokia n800");
 
     tsc210x_set_transform(s->ts.chip, &n800_pointercal);
 }
@@ -371,7 +371,7 @@ static void n810_kbd_setup(struct n800_s *s)
         if (n810_keys[i] > 0)
             s->keymap[n810_keys[i]] = i;
 
-    qemu_add_kbd_event_handler(n810_key_event, s);
+    qemu_add_kbd_event_handler(n810_key_event, s, "Nokia n810");
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
diff --git a/hw/palm.c b/hw/palm.c
index 6d19167..1b405d4 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -228,7 +228,7 @@ static void palmte_init(ram_addr_t ram_size,
 
     palmte_microwire_setup(cpu);
 
-    qemu_add_kbd_event_handler(palmte_button_event, cpu);
+    qemu_add_kbd_event_handler(palmte_button_event, cpu, "Palm Keyboard");
 
     palmte_gpio_setup(cpu);
 
diff --git a/hw/ps2.c b/hw/ps2.c
index f0b206a..886da37 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -596,7 +596,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
     vmstate_register(0, &vmstate_ps2_keyboard, s);
-    qemu_add_kbd_event_handler(ps2_put_keycode, s);
+    qemu_add_kbd_event_handler(ps2_put_keycode, s, "QEMU PS/2 Keyboard");
     qemu_register_reset(ps2_kbd_reset, s);
     return s;
 }
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 060df58..7fa5af9 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -332,5 +332,5 @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp, struct keymap *map,
     }
 
     kp->map = map;
-    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) pxa27x_keyboard_event, kp);
+    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) pxa27x_keyboard_event, kp, "PXA keypad");
 }
diff --git a/hw/spitz.c b/hw/spitz.c
index 564519b..64e8a6e 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -506,7 +506,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
         pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i], s->strobe[i]);
 
     spitz_keyboard_pre_map(s);
-    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
+    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s, "Spitz keyboard");
 
     register_savevm("spitz_keyboard", 0, 0,
                     spitz_keyboard_save, spitz_keyboard_load, s);
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 33395a4..775cb46 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -85,7 +85,7 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
         s->buttons[i].keycode = keycode[i];
     }
     s->num_buttons = n;
-    qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
+    qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s, "Stellaris Gamepad");
     register_savevm("stellaris_gamepad", -1, 1,
                     stellaris_gamepad_save, stellaris_gamepad_load, s);
 }
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 4a562f8..d1651b4 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -218,7 +218,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
     }
     s->key_fifo = qemu_mallocz(s->fifo_size * sizeof(s->key_fifo[0]));
 
-    qemu_add_kbd_event_handler(syborg_keyboard_event, s);
+    qemu_add_kbd_event_handler(syborg_keyboard_event, s, "Syborg Keyboard");
 
     register_savevm("syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8e6c6e0..dbab5d3 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -55,6 +55,7 @@ typedef struct USBKeyboardState {
     uint8_t leds;
     uint8_t key[16];
     int keys;
+    QEMUPutKbdEntry *eh_entry;
 } USBKeyboardState;
 
 typedef struct USBHIDState {
@@ -633,7 +634,8 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    qemu_add_kbd_event_handler(usb_keyboard_event, s);
+    s->kbd.eh_entry = qemu_add_kbd_event_handler(usb_keyboard_event, s,
+                                                 dev->product_desc);
     s->protocol = 1;
 }
 
@@ -854,9 +856,11 @@ static void usb_hid_handle_destroy(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    if (s->kind != USB_KEYBOARD)
+    if (s->kind != USB_KEYBOARD) {
         qemu_remove_mouse_event_handler(s->ptr.eh_entry);
-    /* TODO: else */
+    } else {
+        qemu_remove_kbd_event_handler(s->kbd.eh_entry);
+    }
 }
 
 static int usb_hid_initfn(USBDevice *dev, int kind)
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 422cd53..2c700bd 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -373,7 +373,7 @@ static int input_connect(struct XenDevice *xendev)
     if (rc != 0)
 	return rc;
 
-    qemu_add_kbd_event_handler(xenfb_key_event, in);
+    qemu_add_kbd_event_handler(xenfb_key_event, in, "Xen Keyboard");
     in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in,
 					      in->abs_pointer_wanted,
 					      "Xen PVFB Mouse");
@@ -388,7 +388,7 @@ static void input_disconnect(struct XenDevice *xendev)
 	qemu_remove_mouse_event_handler(in->qmouse);
 	in->qmouse = NULL;
     }
-    qemu_add_kbd_event_handler(NULL, NULL);
+    qemu_add_kbd_event_handler(NULL, NULL, NULL);
     common_unbind(&in->c);
 }
 
diff --git a/input.c b/input.c
index 8f0941e..c27a600 100644
--- a/input.c
+++ b/input.c
@@ -28,20 +28,15 @@
 #include "console.h"
 #include "qjson.h"
 
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
+static QTAILQ_HEAD(, QEMUPutKbdEntry) kbd_handlers =
+    QTAILQ_HEAD_INITIALIZER(kbd_handlers);
+static QEMUPutKbdEntry *kbd_current;
 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
 static NotifierList mouse_mode_notifiers = 
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-{
-    qemu_put_kbd_event_opaque = opaque;
-    qemu_put_kbd_event = func;
-}
-
 static void check_mode_change(void)
 {
     static int current_is_absolute, current_has_absolute;
@@ -60,6 +55,41 @@ static void check_mode_change(void)
     current_has_absolute = has_absolute;
 }
 
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
+                                            void *opaque,
+                                            const char *name)
+{
+    QEMUPutKbdEntry *s, *cursor;
+
+    QTAILQ_FOREACH(cursor, &kbd_handlers, entry) {
+        if (cursor->qemu_put_kbd_event == func &&
+            cursor->qemu_put_kbd_event_opaque == opaque) {
+            kbd_current = cursor;
+            return cursor;
+        }
+    }
+
+    s = qemu_mallocz(sizeof(QEMUPutKbdEntry));
+
+    s->qemu_put_kbd_event_opaque = opaque;
+    s->qemu_put_kbd_event = func;
+    s->qemu_put_kbd_name = qemu_strdup(name);
+
+    QTAILQ_INSERT_TAIL(&kbd_handlers, s, entry);
+    kbd_current = s;
+
+    return s;
+}
+
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
+{
+    QTAILQ_REMOVE(&kbd_handlers, entry, entry);
+    if (kbd_current == entry) {
+        kbd_current = QTAILQ_FIRST(&kbd_handlers);
+    }
+    qemu_free(entry);
+}
+
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name)
@@ -123,8 +153,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
 
 void kbd_put_keycode(int keycode)
 {
-    if (qemu_put_kbd_event) {
-        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+    if (kbd_current) {
+        kbd_current->qemu_put_kbd_event(
+            kbd_current->qemu_put_kbd_event_opaque, keycode);
     }
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-26  9:57   ` Markus Armbruster
  2010-03-26 18:40     ` Shahar Havivi
@ 2010-03-27 18:15     ` Shahar Havivi
  1 sibling, 0 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-27 18:15 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Fix to Markus comments. 

---
 console.h       |    6 +++
 input.c         |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 monitor.c       |    8 ++++
 qemu-monitor.hx |   17 ++++++++
 4 files changed, 141 insertions(+), 9 deletions(-)

diff --git a/console.h b/console.h
index 7d19407..c2af79c 100644
--- a/console.h
+++ b/console.h
@@ -45,6 +45,8 @@ typedef struct QEMUPutKbdEntry {
     char *qemu_put_kbd_name;
     QEMUPutKBDEvent *qemu_put_kbd_event;
     void *qemu_put_kbd_event_opaque;
+    int index;
+
     QTAILQ_ENTRY(QEMUPutKbdEntry) entry;
 } QEMUPutKbdEntry;
 
@@ -85,6 +87,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
 void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
+void do_info_keyboard_print(Monitor *mon, const QObject *data);
+void do_info_keyboard(Monitor *mon, QObject **ret_data);
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
diff --git a/input.c b/input.c
index c27a600..2af6e9d 100644
--- a/input.c
+++ b/input.c
@@ -30,7 +30,6 @@
 
 static QTAILQ_HEAD(, QEMUPutKbdEntry) kbd_handlers =
     QTAILQ_HEAD_INITIALIZER(kbd_handlers);
-static QEMUPutKbdEntry *kbd_current;
 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
@@ -59,12 +58,12 @@ QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
                                             void *opaque,
                                             const char *name)
 {
+    static int mouse_index = 0;
     QEMUPutKbdEntry *s, *cursor;
 
     QTAILQ_FOREACH(cursor, &kbd_handlers, entry) {
         if (cursor->qemu_put_kbd_event == func &&
             cursor->qemu_put_kbd_event_opaque == opaque) {
-            kbd_current = cursor;
             return cursor;
         }
     }
@@ -74,9 +73,9 @@ QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
     s->qemu_put_kbd_event_opaque = opaque;
     s->qemu_put_kbd_event = func;
     s->qemu_put_kbd_name = qemu_strdup(name);
+    s->index = mouse_index++;
 
     QTAILQ_INSERT_TAIL(&kbd_handlers, s, entry);
-    kbd_current = s;
 
     return s;
 }
@@ -84,9 +83,6 @@ QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
 void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
 {
     QTAILQ_REMOVE(&kbd_handlers, entry, entry);
-    if (kbd_current == entry) {
-        kbd_current = QTAILQ_FIRST(&kbd_handlers);
-    }
     qemu_free(entry);
 }
 
@@ -153,10 +149,14 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
 
 void kbd_put_keycode(int keycode)
 {
-    if (kbd_current) {
-        kbd_current->qemu_put_kbd_event(
-            kbd_current->qemu_put_kbd_event_opaque, keycode);
+    QEMUPutKbdEntry *entry;
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        return;
     }
+
+    entry = QTAILQ_FIRST(&kbd_handlers);
+    entry->qemu_put_kbd_event(entry->qemu_put_kbd_event_opaque, keycode);
 }
 
 void kbd_put_ledstate(int ledstate)
@@ -329,3 +329,104 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
 {
     notifier_list_remove(&mouse_mode_notifiers, notify);
 }
+
+static void info_keyboard_iter(QObject *data, void *opaque)
+{
+    QDict *kbd;
+    Monitor *mon = opaque;
+
+    kbd = qobject_to_qdict(data);
+    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
+                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
+                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
+}
+
+void do_info_keyboard_print(Monitor *mon, const QObject *data)
+{
+    QList *kbd_list;
+
+    kbd_list = qobject_to_qlist(data);
+    if (qlist_empty(kbd_list)) {
+        monitor_printf(mon, "No keyboard devices connected\n");
+        return;
+    }
+
+    qlist_iter(kbd_list, info_keyboard_iter, mon);
+}
+
+/*
+ * do_info_keyboard(): Show VM keyboard information
+ *
+ * Each keyboard is represented by a QDict, the returned QObject is
+ * a QList of all keyboards.
+ *
+ * The keyboard QDict contains the following:
+ *
+ * - "name": keyboard's name
+ * - "index": keyboard's index
+ * - "current": true if this keyboard is receiving events, false otherwise
+ *
+ * Example:
+ *
+ * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
+ *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
+ */
+void do_info_keyboard(Monitor *mon, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    QList *kbd_list;
+    int current;
+
+    kbd_list = qlist_new();
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        goto out;
+    }
+
+    current = QTAILQ_FIRST(&kbd_handlers)->index;
+    QTAILQ_FOREACH(cursor, &kbd_handlers, entry) {
+        QObject *obj;
+        obj = qobject_from_jsonf("{ 'name': %s,"
+                                 "  'index': %d,"
+                                 "  'current': %i }",
+                                 cursor->qemu_put_kbd_name,
+                                 cursor->index,
+                                 current == cursor->index);
+        qlist_append_obj(kbd_list, obj);
+    }
+out:
+    *ret_data = QOBJECT(kbd_list);
+}
+
+/*
+ * do_keyboard_set(): Set active keyboard
+ *
+ * Argument qdict contains
+ * - "index": the keyboard index to set
+ *
+ * Example:
+ *
+ * { "index": "0" }
+ */
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    int index = qdict_get_int(qdict, "index");
+    int found = 0;
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
+        return -1;
+    }
+
+    QTAILQ_FOREACH(cursor, &kbd_handlers, entry) {
+        if (cursor->index == index) {
+            QTAILQ_REMOVE(&kbd_handlers, cursor, entry);
+            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, entry);
+            found = 1;
+            break;
+        }
+    }
+
+    return 0;
+}
diff --git a/monitor.c b/monitor.c
index 0448a70..cc95b3d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2783,6 +2783,14 @@ static const mon_cmd_t info_cmds[] = {
         .mhandler.info_new = do_info_mice,
     },
     {
+        .name       = "keyboard",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show which guest keyboard is receiving events",
+        .user_print = do_info_keyboard_print,
+        .mhandler.info_new = do_info_keyboard,
+    },
+    {
         .name       = "vnc",
         .args_type  = "",
         .params     = "",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5308f36..e9beb12 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -659,6 +659,23 @@ info mice
 @end example
 ETEXI
 
+    {
+        .name       = "keyboard_set",
+        .args_type  = "index:i",
+        .params     = "index",
+        .help       = "set which keyboard device receives events",
+        .mhandler.cmd_new = do_keyboard_set,
+    },
+
+STEXI
+@item keyboard_set @var{index}
+@findex keyboard_set
+Set which keyboard device receives events at given @var{index}, index
+can be obtained with
+@example
+info keyboard
+@end example
+ETEXI
 #ifdef HAS_AUDIO
     {
         .name       = "wavcapture",
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-26 18:40     ` Shahar Havivi
@ 2010-03-31 15:10       ` Markus Armbruster
  2010-03-31 15:14         ` Shahar Havivi
  2010-03-31 15:19         ` [Qemu-devel] " Juan Quintela
  0 siblings, 2 replies; 20+ messages in thread
From: Markus Armbruster @ 2010-03-31 15:10 UTC (permalink / raw)
  To: Shahar Havivi; +Cc: qemu-devel

Shahar Havivi <shaharh@redhat.com> writes:

> On Fri, Mar 26, 2010 at 10:57:58AM +0100, Markus Armbruster wrote:
[...]
>> Since the index is not a stable identifier of keyboards, and we support
>> multiple monitors, you're prone to remove the wrong keyboard.
>> 
>>     Monitor#1                           Monitor#2
>>     "info keyboard" to find the index
>>                                         unplug a keyboard, invalidating
>>                                         index
>>     keyboard_set <index>
>> 
>> I think it's best to use a stable ID, like we do in other places.  We
>> commonly let the user specify it, e.g. as id=ID in -netdev, -device and
>> elswhere.
> What do we do when user not specify id for device?

Two obvious options: make one up (problem: clashes), or stipulate "if
you want to keyboard_set this keyboard, you must specify an id for it".

[...]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 15:10       ` Markus Armbruster
@ 2010-03-31 15:14         ` Shahar Havivi
  2010-03-31 15:19         ` [Qemu-devel] " Juan Quintela
  1 sibling, 0 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-31 15:14 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

On Wed, Mar 31, 2010 at 05:10:22PM +0200, Markus Armbruster wrote:
> Date: Wed, 31 Mar 2010 17:10:22 +0200
> From: Markus Armbruster <armbru@redhat.com>
> To: Shahar Havivi <shaharh@redhat.com>
> Cc: qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] [PATCH 2/2] Added monitor commands:
>  'keyboard_set' and 'info keybaord'
> 
> Shahar Havivi <shaharh@redhat.com> writes:
> 
> > On Fri, Mar 26, 2010 at 10:57:58AM +0100, Markus Armbruster wrote:
> [...]
> >> Since the index is not a stable identifier of keyboards, and we support
> >> multiple monitors, you're prone to remove the wrong keyboard.
> >> 
> >>     Monitor#1                           Monitor#2
> >>     "info keyboard" to find the index
> >>                                         unplug a keyboard, invalidating
> >>                                         index
> >>     keyboard_set <index>
> >> 
> >> I think it's best to use a stable ID, like we do in other places.  We
> >> commonly let the user specify it, e.g. as id=ID in -netdev, -device and
> >> elswhere.
> > What do we do when user not specify id for device?
> 
> Two obvious options: make one up (problem: clashes), or stipulate "if
> you want to keyboard_set this keyboard, you must specify an id for it".
> 
> [...]
How about static auto incremented id like the mouse does?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 15:10       ` Markus Armbruster
  2010-03-31 15:14         ` Shahar Havivi
@ 2010-03-31 15:19         ` Juan Quintela
  1 sibling, 0 replies; 20+ messages in thread
From: Juan Quintela @ 2010-03-31 15:19 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Shahar Havivi, qemu-devel

Markus Armbruster <armbru@redhat.com> wrote:
> Shahar Havivi <shaharh@redhat.com> writes:
>
>> On Fri, Mar 26, 2010 at 10:57:58AM +0100, Markus Armbruster wrote:
> [...]
>>> Since the index is not a stable identifier of keyboards, and we support
>>> multiple monitors, you're prone to remove the wrong keyboard.
>>> 
>>>     Monitor#1                           Monitor#2
>>>     "info keyboard" to find the index
>>>                                         unplug a keyboard, invalidating
>>>                                         index
>>>     keyboard_set <index>
>>> 
>>> I think it's best to use a stable ID, like we do in other places.  We
>>> commonly let the user specify it, e.g. as id=ID in -netdev, -device and
>>> elswhere.
>> What do we do when user not specify id for device?
>
> Two obvious options: make one up (problem: clashes), or stipulate "if
> you want to keyboard_set this keyboard, you must specify an id for it".

Second one is simpler, so .....

O:-)

Later, Juan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 17:04     ` Anthony Liguori
@ 2010-03-31 20:55       ` Shahar Havivi
  0 siblings, 0 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-31 20:55 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Juan Quintela

> >>+
> >>+    if (QTAILQ_EMPTY(&kbd_handlers)) {
> >>+        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
> >>+        return -1;
> >>+    }
> >>+
> >>+    QTAILQ_FOREACH(cursor,&kbd_handlers, node) {
> >>+        if (cursor->index == index) {
> >>+            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
> >>+            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
> >>+            found = 1;
> >well it is set :)
> 
> Please split out this bit into a qemu_activate_keyboard_handler()
> and plumb it with the usb device such that it's only used when a
> guest loads a driver for it.
> 
> It should be very symmetric to how the mouse driver works.
> 
> Regards,
> 
> Anthony Liguori
Anthony, 

Added qemu_activate_keyboard_event_handler, and use it with usb_keyboard_poll.
I test it with two usb keyboard devices, the last connected one is active.

Shahar.

Signed-off-by: Shahar Havivi <shaharh@redhat.com>
---
 console.h       |    5 ++
 hw/usb-hid.c    |    6 +++
 input.c         |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 monitor.c       |    8 ++++
 qemu-monitor.hx |   17 ++++++++
 5 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/console.h b/console.h
index 91b66ea..5d68cff 100644
--- a/console.h
+++ b/console.h
@@ -54,6 +54,7 @@ QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
                                             void *opaque,
                                             const char *name);
 void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
+void qemu_activate_keyboard_event_handler(QEMUPutKbdEntry *entry);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
@@ -87,6 +88,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
 void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
+void do_info_keyboard_print(Monitor *mon, const QObject *data);
+void do_info_keyboard(Monitor *mon, QObject **ret_data);
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index dbab5d3..88ef36c 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -55,6 +55,7 @@ typedef struct USBKeyboardState {
     uint8_t leds;
     uint8_t key[16];
     int keys;
+    int keyboard_grabbed;
     QEMUPutKbdEntry *eh_entry;
 } USBKeyboardState;
 
@@ -586,6 +587,11 @@ static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
     if (len < 2)
         return 0;
 
+    if (!s->keyboard_grabbed) {
+        qemu_activate_keyboard_event_handler(s->eh_entry);
+        s->keyboard_grabbed = 1;
+    }
+
     buf[0] = s->modifiers & 0xff;
     buf[1] = 0;
     if (s->keys > 6)
diff --git a/input.c b/input.c
index 18875a9..da43ee5 100644
--- a/input.c
+++ b/input.c
@@ -329,3 +329,114 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
 {
     notifier_list_remove(&mouse_mode_notifiers, notify);
 }
+
+static void info_keyboard_iter(QObject *data, void *opaque)
+{
+    QDict *kbd;
+    Monitor *mon = opaque;
+
+    kbd = qobject_to_qdict(data);
+    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
+                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
+                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
+}
+
+void do_info_keyboard_print(Monitor *mon, const QObject *data)
+{
+    QList *kbd_list;
+
+    kbd_list = qobject_to_qlist(data);
+    if (qlist_empty(kbd_list)) {
+        monitor_printf(mon, "No keyboard devices connected\n");
+        return;
+    }
+
+    qlist_iter(kbd_list, info_keyboard_iter, mon);
+}
+
+void qemu_activate_keyboard_event_handler(QEMUPutKbdEntry *entry)
+{
+    QTAILQ_REMOVE(&kbd_handlers, entry, node);
+    QTAILQ_INSERT_HEAD(&kbd_handlers, entry, node);
+}
+
+/*
+ * do_info_keyboard(): Show VM keyboard information
+ *
+ * Each keyboard is represented by a QDict, the returned QObject is
+ * a QList of all keyboards.
+ *
+ * The keyboard QDict contains the following:
+ *
+ * - "name": keyboard's name
+ * - "index": keyboard's index
+ * - "current": true if this keyboard is receiving events, false otherwise
+ *
+ * Example:
+ *
+ * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
+ *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
+ */
+void do_info_keyboard(Monitor *mon, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    QList *kbd_list;
+    int current;
+
+    kbd_list = qlist_new();
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        goto out;
+    }
+
+    current = QTAILQ_FIRST(&kbd_handlers)->index;
+    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
+        QObject *obj;
+        obj = qobject_from_jsonf("{ 'name': %s,"
+                                 "  'index': %d,"
+                                 "  'current': %i }",
+                                 cursor->qemu_put_kbd_name,
+                                 cursor->index,
+                                 current == cursor->index);
+        qlist_append_obj(kbd_list, obj);
+    }
+out:
+    *ret_data = QOBJECT(kbd_list);
+}
+
+/*
+ * do_keyboard_set(): Set active keyboard
+ *
+ * Argument qdict contains
+ * - "index": the keyboard index to set
+ *
+ * Example:
+ *
+ * { "index": "0" }
+ */
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    int index = qdict_get_int(qdict, "index");
+    int found = 0;
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
+        return -1;
+    }
+
+    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
+        if (cursor->index == index) {
+            qemu_activate_keyboard_event_handler(cursor);
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
+        qerror_report(QERR_INVALID_PARAMETER, "index");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/monitor.c b/monitor.c
index 822dc27..f5474b1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2781,6 +2781,14 @@ static const mon_cmd_t info_cmds[] = {
         .mhandler.info_new = do_info_mice,
     },
     {
+        .name       = "keyboard",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show which guest keyboard is receiving events",
+        .user_print = do_info_keyboard_print,
+        .mhandler.info_new = do_info_keyboard,
+    },
+    {
         .name       = "vnc",
         .args_type  = "",
         .params     = "",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5308f36..e9beb12 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -659,6 +659,23 @@ info mice
 @end example
 ETEXI
 
+    {
+        .name       = "keyboard_set",
+        .args_type  = "index:i",
+        .params     = "index",
+        .help       = "set which keyboard device receives events",
+        .mhandler.cmd_new = do_keyboard_set,
+    },
+
+STEXI
+@item keyboard_set @var{index}
+@findex keyboard_set
+Set which keyboard device receives events at given @var{index}, index
+can be obtained with
+@example
+info keyboard
+@end example
+ETEXI
 #ifdef HAS_AUDIO
     {
         .name       = "wavcapture",
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 19:52           ` Anthony Liguori
@ 2010-03-31 20:16             ` Juan Quintela
  0 siblings, 0 replies; 20+ messages in thread
From: Juan Quintela @ 2010-03-31 20:16 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Shahar Havivi, Markus Armbruster, qemu-devel

Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 03/31/2010 02:37 PM, Shahar Havivi wrote:
>> On Wed, Mar 31, 2010 at 06:58:14PM +0200, Juan Quintela wrote:
>>    
>>> Date: Wed, 31 Mar 2010 18:58:14 +0200
>>> From: Juan Quintela<quintela@redhat.com>
>>> To: Markus Armbruster<armbru@redhat.com>
>>> Cc: Shahar Havivi<shaharh@redhat.com>, qemu-devel@nongnu.org
>>> Subject: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set'
>>> 	and 'info keybaord'
>>>
>>> Markus Armbruster<armbru@redhat.com>  wrote:
>>>      
>>>> Juan Quintela<quintela@redhat.com>  writes:
>>>>        
>>>>> I still think that adding an "id" property as in markus proposal would
>>>>> be neat.  Otherwise I don't know how you are going to distinguish
>>>>> between two keyboards with the same name.
>>>>>          
>>>> If I understand the patch correctly (only time for a quick skim today),
>>>> the keyboard receives a numeric ID when it is created, and keyboard_set
>>>> identifies it by that ID.  Yes, a user-defined ID would be nicer, and
>>>> consistent with how similar things work.  But the numeric ID isn't
>>>> *wrong*, as far as I can see.
>>>>        
>>> my problem is that if you add two keyboards of the same type, they will
>>> receive random index (different ones), now you do info keyboard, and you
>>> see two keyboard with the same names and different numbers, how do you
>>> know which of the two given you want to choose?
>>>
>>> And no, I don't have magic bullet to make multimonitor/keyboard/mouse
>>> behave as expected out of given them right id's.
>>>
>>> Later, Juan.
>>>      
>> You right, this is a problem.
>> As I see it id cannot be force to receive by the user right?
>>    
>
> This is already the case with the mouse.
>
> Ultimately, I don't think it's a useful problem to attempt to solve.
> Why would there every be two keyboards of the same type (or two mice)?

I don't understand why somebody will want multiscreen+mouse+keyboard.

Once told that, if having more than one of any of them, then it is
better that keyboard_set

/*
 * do_keyboard_set(): Set active keyboard
 *
 * Argument qdict contains
 * - "index": the keyboard index to set

should take as a keyboard the string identifier and be done with that?
Instead of all this bussines of numbering/renumbering during hot [un]plug?

Later, Juan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 19:37         ` Shahar Havivi
@ 2010-03-31 19:52           ` Anthony Liguori
  2010-03-31 20:16             ` Juan Quintela
  0 siblings, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2010-03-31 19:52 UTC (permalink / raw)
  To: Shahar Havivi; +Cc: qemu-devel, Markus Armbruster, Juan Quintela

On 03/31/2010 02:37 PM, Shahar Havivi wrote:
> On Wed, Mar 31, 2010 at 06:58:14PM +0200, Juan Quintela wrote:
>    
>> Date: Wed, 31 Mar 2010 18:58:14 +0200
>> From: Juan Quintela<quintela@redhat.com>
>> To: Markus Armbruster<armbru@redhat.com>
>> Cc: Shahar Havivi<shaharh@redhat.com>, qemu-devel@nongnu.org
>> Subject: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set'
>> 	and 'info keybaord'
>>
>> Markus Armbruster<armbru@redhat.com>  wrote:
>>      
>>> Juan Quintela<quintela@redhat.com>  writes:
>>>        
>>>> I still think that adding an "id" property as in markus proposal would
>>>> be neat.  Otherwise I don't know how you are going to distinguish
>>>> between two keyboards with the same name.
>>>>          
>>> If I understand the patch correctly (only time for a quick skim today),
>>> the keyboard receives a numeric ID when it is created, and keyboard_set
>>> identifies it by that ID.  Yes, a user-defined ID would be nicer, and
>>> consistent with how similar things work.  But the numeric ID isn't
>>> *wrong*, as far as I can see.
>>>        
>> my problem is that if you add two keyboards of the same type, they will
>> receive random index (different ones), now you do info keyboard, and you
>> see two keyboard with the same names and different numbers, how do you
>> know which of the two given you want to choose?
>>
>> And no, I don't have magic bullet to make multimonitor/keyboard/mouse
>> behave as expected out of given them right id's.
>>
>> Later, Juan.
>>      
> You right, this is a problem.
> As I see it id cannot be force to receive by the user right?
>    

This is already the case with the mouse.

Ultimately, I don't think it's a useful problem to attempt to solve.  
Why would there every be two keyboards of the same type (or two mice)?

Regards,

Anthony Liguori

> Thanks, Shahar.
>
>
>    

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 16:58       ` Juan Quintela
@ 2010-03-31 19:37         ` Shahar Havivi
  2010-03-31 19:52           ` Anthony Liguori
  0 siblings, 1 reply; 20+ messages in thread
From: Shahar Havivi @ 2010-03-31 19:37 UTC (permalink / raw)
  To: Juan Quintela; +Cc: Markus Armbruster, qemu-devel

On Wed, Mar 31, 2010 at 06:58:14PM +0200, Juan Quintela wrote:
> Date: Wed, 31 Mar 2010 18:58:14 +0200
> From: Juan Quintela <quintela@redhat.com>
> To: Markus Armbruster <armbru@redhat.com>
> Cc: Shahar Havivi <shaharh@redhat.com>, qemu-devel@nongnu.org
> Subject: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set'
> 	and 'info keybaord'
> 
> Markus Armbruster <armbru@redhat.com> wrote:
> > Juan Quintela <quintela@redhat.com> writes:
> >> I still think that adding an "id" property as in markus proposal would
> >> be neat.  Otherwise I don't know how you are going to distinguish
> >> between two keyboards with the same name.
> >
> > If I understand the patch correctly (only time for a quick skim today),
> > the keyboard receives a numeric ID when it is created, and keyboard_set
> > identifies it by that ID.  Yes, a user-defined ID would be nicer, and
> > consistent with how similar things work.  But the numeric ID isn't
> > *wrong*, as far as I can see.
> 
> my problem is that if you add two keyboards of the same type, they will
> receive random index (different ones), now you do info keyboard, and you
> see two keyboard with the same names and different numbers, how do you
> know which of the two given you want to choose?
> 
> And no, I don't have magic bullet to make multimonitor/keyboard/mouse
> behave as expected out of given them right id's.
> 
> Later, Juan.
You right, this is a problem.
As I see it id cannot be force to receive by the user right?

Thanks, Shahar.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 10:20   ` [Qemu-devel] " Juan Quintela
  2010-03-31 15:31     ` Markus Armbruster
@ 2010-03-31 17:04     ` Anthony Liguori
  2010-03-31 20:55       ` Shahar Havivi
  1 sibling, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2010-03-31 17:04 UTC (permalink / raw)
  To: Juan Quintela; +Cc: Shahar Havivi, qemu-devel

On 03/31/2010 05:20 AM, Juan Quintela wrote:
> Shahar Havivi<shaharh@redhat.com>  wrote:
>    
>> Two new monitor commands: adding ability to handle which keyboard qemu will
>> use and to see which keyboard are currently available.
>>      
>    
>> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
>> +{
>> +    QEMUPutKbdEntry *cursor;
>> +    int index = qdict_get_int(qdict, "index");
>> +    int found = 0;
>>      
> found variable is not used.
>
>    
>> +
>> +    if (QTAILQ_EMPTY(&kbd_handlers)) {
>> +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
>> +        return -1;
>> +    }
>> +
>> +    QTAILQ_FOREACH(cursor,&kbd_handlers, node) {
>> +        if (cursor->index == index) {
>> +            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
>> +            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
>> +            found = 1;
>>      
> well it is set :)
>    

Please split out this bit into a qemu_activate_keyboard_handler() and 
plumb it with the usb device such that it's only used when a guest loads 
a driver for it.

It should be very symmetric to how the mouse driver works.

Regards,

Anthony Liguori

>> +            break;
>> +        }
>> +    }
>> +
>> +    return 0;
>>      
> I guess you want to return one error if the index don't exist.
>
>    
>> +}
>>      
> I still think that adding an "id" property as in markus proposal would
> be neat.  Otherwise I don't know how you are going to distinguish
> between two keyboards with the same name.
>
> Later, Juan.
>
>
>    

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 15:31     ` Markus Armbruster
  2010-03-31 15:42       ` Shahar Havivi
@ 2010-03-31 16:58       ` Juan Quintela
  2010-03-31 19:37         ` Shahar Havivi
  1 sibling, 1 reply; 20+ messages in thread
From: Juan Quintela @ 2010-03-31 16:58 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Shahar Havivi, qemu-devel

Markus Armbruster <armbru@redhat.com> wrote:
> Juan Quintela <quintela@redhat.com> writes:
>> I still think that adding an "id" property as in markus proposal would
>> be neat.  Otherwise I don't know how you are going to distinguish
>> between two keyboards with the same name.
>
> If I understand the patch correctly (only time for a quick skim today),
> the keyboard receives a numeric ID when it is created, and keyboard_set
> identifies it by that ID.  Yes, a user-defined ID would be nicer, and
> consistent with how similar things work.  But the numeric ID isn't
> *wrong*, as far as I can see.

my problem is that if you add two keyboards of the same type, they will
receive random index (different ones), now you do info keyboard, and you
see two keyboard with the same names and different numbers, how do you
know which of the two given you want to choose?

And no, I don't have magic bullet to make multimonitor/keyboard/mouse
behave as expected out of given them right id's.

Later, Juan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 15:31     ` Markus Armbruster
@ 2010-03-31 15:42       ` Shahar Havivi
  2010-03-31 16:58       ` Juan Quintela
  1 sibling, 0 replies; 20+ messages in thread
From: Shahar Havivi @ 2010-03-31 15:42 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Juan Quintela

On Wed, Mar 31, 2010 at 05:31:49PM +0200, Markus Armbruster wrote:
> Date: Wed, 31 Mar 2010 17:31:49 +0200
> From: Markus Armbruster <armbru@redhat.com>
> To: Juan Quintela <quintela@redhat.com>
> Cc: Shahar Havivi <shaharh@redhat.com>, qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands:
>  'keyboard_set' and 'info keybaord'
> 
> Juan Quintela <quintela@redhat.com> writes:
> 
> > Shahar Havivi <shaharh@redhat.com> wrote:
> >> Two new monitor commands: adding ability to handle which keyboard qemu will
> >> use and to see which keyboard are currently available.
> >
> >> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
> >> +{
> >> +    QEMUPutKbdEntry *cursor;
> >> +    int index = qdict_get_int(qdict, "index");
> >> +    int found = 0;
> >
> > found variable is not used.
> >
> >> +
> >> +    if (QTAILQ_EMPTY(&kbd_handlers)) {
> >> +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
> >> +        return -1;
> >> +    }
> >> +
> >> +    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
> >> +        if (cursor->index == index) {
> >> +            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
> >> +            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
> >> +            found = 1;
> >
> > well it is set :)
> >
> >> +            break;
> >> +        }
> >> +    }
> >> +
> >> +    return 0;
> >
> > I guess you want to return one error if the index don't exist.

Right about that, Thanks.

> >> +}
> >
> > I still think that adding an "id" property as in markus proposal would
> > be neat.  Otherwise I don't know how you are going to distinguish
> > between two keyboards with the same name.
> 
> If I understand the patch correctly (only time for a quick skim today),
> the keyboard receives a numeric ID when it is created, and keyboard_set
> identifies it by that ID.  Yes, a user-defined ID would be nicer, and
> consistent with how similar things work.  But the numeric ID isn't
> *wrong*, as far as I can see.

The index Id that I use is the same as I saw that the mouse devices do,
I will try to get it from the user as well (I guess you mean by command
line: 'qemu -device usb-kbd,id=kbd ...')

Signed-off-by: Shahar Havivi <shaharh@redhat.com>
---
 console.h       |    4 ++
 input.c         |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 monitor.c       |    8 ++++
 qemu-monitor.hx |   17 +++++++++
 4 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/console.h b/console.h
index 91b66ea..889f5d5 100644
--- a/console.h
+++ b/console.h
@@ -87,6 +87,10 @@ void do_info_mice_print(Monitor *mon, const QObject *data);
 void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
+void do_info_keyboard_print(Monitor *mon, const QObject *data);
+void do_info_keyboard(Monitor *mon, QObject **ret_data);
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
diff --git a/input.c b/input.c
index 18875a9..27ef8f9 100644
--- a/input.c
+++ b/input.c
@@ -329,3 +329,109 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
 {
     notifier_list_remove(&mouse_mode_notifiers, notify);
 }
+
+static void info_keyboard_iter(QObject *data, void *opaque)
+{
+    QDict *kbd;
+    Monitor *mon = opaque;
+
+    kbd = qobject_to_qdict(data);
+    monitor_printf(mon, "%c Keyboard #%" PRId64 ": %s\n",
+                  (qdict_get_bool(kbd, "current") ? '*' : ' '),
+                  qdict_get_int(kbd, "index"), qdict_get_str(kbd, "name"));
+}
+
+void do_info_keyboard_print(Monitor *mon, const QObject *data)
+{
+    QList *kbd_list;
+
+    kbd_list = qobject_to_qlist(data);
+    if (qlist_empty(kbd_list)) {
+        monitor_printf(mon, "No keyboard devices connected\n");
+        return;
+    }
+
+    qlist_iter(kbd_list, info_keyboard_iter, mon);
+}
+
+/*
+ * do_info_keyboard(): Show VM keyboard information
+ *
+ * Each keyboard is represented by a QDict, the returned QObject is
+ * a QList of all keyboards.
+ *
+ * The keyboard QDict contains the following:
+ *
+ * - "name": keyboard's name
+ * - "index": keyboard's index
+ * - "current": true if this keyboard is receiving events, false otherwise
+ *
+ * Example:
+ *
+ * [ { "name": "QEMU USB Keyboard", "index": 0, "current": false },
+ *   { "name": "QEMU PS/2 Keyboard", "index": 1, "current": true } ]
+ */
+void do_info_keyboard(Monitor *mon, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    QList *kbd_list;
+    int current;
+
+    kbd_list = qlist_new();
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        goto out;
+    }
+
+    current = QTAILQ_FIRST(&kbd_handlers)->index;
+    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
+        QObject *obj;
+        obj = qobject_from_jsonf("{ 'name': %s,"
+                                 "  'index': %d,"
+                                 "  'current': %i }",
+                                 cursor->qemu_put_kbd_name,
+                                 cursor->index,
+                                 current == cursor->index);
+        qlist_append_obj(kbd_list, obj);
+    }
+out:
+    *ret_data = QOBJECT(kbd_list);
+}
+
+/*
+ * do_keyboard_set(): Set active keyboard
+ *
+ * Argument qdict contains
+ * - "index": the keyboard index to set
+ *
+ * Example:
+ *
+ * { "index": "0" }
+ */
+int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    QEMUPutKbdEntry *cursor;
+    int index = qdict_get_int(qdict, "index");
+    int found = 0;
+
+    if (QTAILQ_EMPTY(&kbd_handlers)) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
+        return -1;
+    }
+
+    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
+        if (cursor->index == index) {
+            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
+            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
+        qerror_report(QERR_INVALID_PARAMETER, "index");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/monitor.c b/monitor.c
index 822dc27..f5474b1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2781,6 +2781,14 @@ static const mon_cmd_t info_cmds[] = {
         .mhandler.info_new = do_info_mice,
     },
     {
+        .name       = "keyboard",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show which guest keyboard is receiving events",
+        .user_print = do_info_keyboard_print,
+        .mhandler.info_new = do_info_keyboard,
+    },
+    {
         .name       = "vnc",
         .args_type  = "",
         .params     = "",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5308f36..e9beb12 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -659,6 +659,23 @@ info mice
 @end example
 ETEXI
 
+    {
+        .name       = "keyboard_set",
+        .args_type  = "index:i",
+        .params     = "index",
+        .help       = "set which keyboard device receives events",
+        .mhandler.cmd_new = do_keyboard_set,
+    },
+
+STEXI
+@item keyboard_set @var{index}
+@findex keyboard_set
+Set which keyboard device receives events at given @var{index}, index
+can be obtained with
+@example
+info keyboard
+@end example
+ETEXI
 #ifdef HAS_AUDIO
     {
         .name       = "wavcapture",
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31 10:20   ` [Qemu-devel] " Juan Quintela
@ 2010-03-31 15:31     ` Markus Armbruster
  2010-03-31 15:42       ` Shahar Havivi
  2010-03-31 16:58       ` Juan Quintela
  2010-03-31 17:04     ` Anthony Liguori
  1 sibling, 2 replies; 20+ messages in thread
From: Markus Armbruster @ 2010-03-31 15:31 UTC (permalink / raw)
  To: Juan Quintela; +Cc: Shahar Havivi, qemu-devel

Juan Quintela <quintela@redhat.com> writes:

> Shahar Havivi <shaharh@redhat.com> wrote:
>> Two new monitor commands: adding ability to handle which keyboard qemu will
>> use and to see which keyboard are currently available.
>
>> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
>> +{
>> +    QEMUPutKbdEntry *cursor;
>> +    int index = qdict_get_int(qdict, "index");
>> +    int found = 0;
>
> found variable is not used.
>
>> +
>> +    if (QTAILQ_EMPTY(&kbd_handlers)) {
>> +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
>> +        return -1;
>> +    }
>> +
>> +    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
>> +        if (cursor->index == index) {
>> +            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
>> +            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
>> +            found = 1;
>
> well it is set :)
>
>> +            break;
>> +        }
>> +    }
>> +
>> +    return 0;
>
> I guess you want to return one error if the index don't exist.
>
>> +}
>
> I still think that adding an "id" property as in markus proposal would
> be neat.  Otherwise I don't know how you are going to distinguish
> between two keyboards with the same name.

If I understand the patch correctly (only time for a quick skim today),
the keyboard receives a numeric ID when it is created, and keyboard_set
identifies it by that ID.  Yes, a user-defined ID would be nicer, and
consistent with how similar things work.  But the numeric ID isn't
*wrong*, as far as I can see.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] Re: [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord'
  2010-03-31  8:16 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
@ 2010-03-31 10:20   ` Juan Quintela
  2010-03-31 15:31     ` Markus Armbruster
  2010-03-31 17:04     ` Anthony Liguori
  0 siblings, 2 replies; 20+ messages in thread
From: Juan Quintela @ 2010-03-31 10:20 UTC (permalink / raw)
  To: Shahar Havivi; +Cc: qemu-devel

Shahar Havivi <shaharh@redhat.com> wrote:
> Two new monitor commands: adding ability to handle which keyboard qemu will
> use and to see which keyboard are currently available.

> +int do_keyboard_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
> +{
> +    QEMUPutKbdEntry *cursor;
> +    int index = qdict_get_int(qdict, "index");
> +    int found = 0;

found variable is not used.

> +
> +    if (QTAILQ_EMPTY(&kbd_handlers)) {
> +        qerror_report(QERR_DEVICE_NOT_FOUND, "keyboard");
> +        return -1;
> +    }
> +
> +    QTAILQ_FOREACH(cursor, &kbd_handlers, node) {
> +        if (cursor->index == index) {
> +            QTAILQ_REMOVE(&kbd_handlers, cursor, node);
> +            QTAILQ_INSERT_HEAD(&kbd_handlers, cursor, node);
> +            found = 1;

well it is set :)

> +            break;
> +        }
> +    }
> +
> +    return 0;

I guess you want to return one error if the index don't exist.

> +}

I still think that adding an "id" property as in markus proposal would
be neat.  Otherwise I don't know how you are going to distinguish
between two keyboards with the same name.

Later, Juan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2010-03-31 20:57 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-23 19:57 [Qemu-devel] [PATCH 0/2] Qemu support for multiple keyboard devices - v2 Shahar Havivi
2010-03-23 19:58 ` [Qemu-devel] [PATCH 1/2] Support for multiple keyboard devices Shahar Havivi
2010-03-26  9:46   ` Markus Armbruster
2010-03-27 15:56     ` Shahar Havivi
2010-03-23 19:58 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
2010-03-26  9:57   ` Markus Armbruster
2010-03-26 18:40     ` Shahar Havivi
2010-03-31 15:10       ` Markus Armbruster
2010-03-31 15:14         ` Shahar Havivi
2010-03-31 15:19         ` [Qemu-devel] " Juan Quintela
2010-03-27 18:15     ` [Qemu-devel] " Shahar Havivi
2010-03-31  8:15 [Qemu-devel] [PATCH 0/2 v3] Qemu support for multiple keyboard devices Shahar Havivi
2010-03-31  8:16 ` [Qemu-devel] [PATCH 2/2] Added monitor commands: 'keyboard_set' and 'info keybaord' Shahar Havivi
2010-03-31 10:20   ` [Qemu-devel] " Juan Quintela
2010-03-31 15:31     ` Markus Armbruster
2010-03-31 15:42       ` Shahar Havivi
2010-03-31 16:58       ` Juan Quintela
2010-03-31 19:37         ` Shahar Havivi
2010-03-31 19:52           ` Anthony Liguori
2010-03-31 20:16             ` Juan Quintela
2010-03-31 17:04     ` Anthony Liguori
2010-03-31 20:55       ` Shahar Havivi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.