From: Shahar Havivi <shah...@redhat.com> Adding keyboard is done to the queue instead of "last added keyboard wins", when removing keyboard via device_del - previous keyboard is selected.
Signed-off-by: Shahar Havivi <shah...@redhat.com> --- 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 | 3 +- hw/spitz.c | 3 +- hw/stellaris_input.c | 3 +- hw/syborg_keyboard.c | 3 +- hw/usb-hid.c | 12 ++++++++- hw/xenfb.c | 5 ++- input.c | 63 +++++++++++++++++++++++++++++++++++++------------ 14 files changed, 90 insertions(+), 33 deletions(-) diff --git a/console.h b/console.h index 64d1f09..671390c 100644 --- a/console.h +++ b/console.h @@ -43,8 +43,20 @@ typedef struct QEMUPutLEDEntry { QTAILQ_ENTRY(QEMUPutLEDEntry) next; } QEMUPutLEDEntry; -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); -void qemu_remove_kbd_event_handler(void); +typedef struct QEMUPutKbdEntry { + char *qemu_put_kbd_name; + QEMUPutKBDEvent *qemu_put_kbd_event; + void *qemu_put_kbd_event_opaque; + int index; + + QTAILQ_ENTRY(QEMUPutKbdEntry) node; +} QEMUPutKbdEntry; + +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); diff --git a/hw/adb.c b/hw/adb.c index 7499cdc..7af5a0e 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -293,7 +293,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, "QEMU ADB Keyboard"); vmstate_register(NULL, -1, &vmstate_adb_kbd, s); } diff --git a/hw/escc.c b/hw/escc.c index f6fd919..d5d3297 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -928,7 +928,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 52b2931..723f94b 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1454,7 +1454,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, "QEMU Musicpal Keyboard"); return 0; } diff --git a/hw/nseries.c b/hw/nseries.c index 2f6f473..5a4e0e8 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, "QEMU Nokia N800 Keyboard"); 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, "QEMU Nokia N810 Keyboard"); /* 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 f22d777..ab60452 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -232,7 +232,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, "QEMU Palm Keyboard"); palmte_gpio_setup(cpu); diff --git a/hw/ps2.c b/hw/ps2.c index 91b73e0..b12a76f 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -610,7 +610,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(NULL, 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 10ef154..e032dfd 100644 --- a/hw/pxa2xx_keypad.c +++ b/hw/pxa2xx_keypad.c @@ -333,5 +333,6 @@ 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, + "QEMU PXA Keypad"); } diff --git a/hw/spitz.c b/hw/spitz.c index 006f7a9..5e9761d 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -487,7 +487,8 @@ static void spitz_keyboard_register(PXA2xxState *cpu) qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock)); - qemu_add_kbd_event_handler(spitz_keyboard_handler, s); + qemu_add_kbd_event_handler(spitz_keyboard_handler, s, + "QEMU Spitz Keyboard"); } static int spitz_keyboard_init(SysBusDevice *dev) diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c index 06c5f9d..64b9047 100644 --- a/hw/stellaris_input.c +++ b/hw/stellaris_input.c @@ -84,6 +84,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, + "QEMU Stellaris Gamepad"); vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s); } diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c index 706a039..a83d588 100644 --- a/hw/syborg_keyboard.c +++ b/hw/syborg_keyboard.c @@ -197,7 +197,8 @@ 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, + "QEMU Syborg Keyboard"); vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s); return 0; diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 89c293c..21c4b56 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -66,6 +66,8 @@ typedef struct USBKeyboardState { uint8_t leds; uint8_t key[16]; int32_t keys; + int keyboard_grabbed; + QEMUPutKbdEntry *eh_entry; } USBKeyboardState; typedef struct USBHIDState { @@ -663,6 +665,11 @@ static int usb_keyboard_poll(USBHIDState *hs, 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; + } + usb_keyboard_process_keycode(hs); buf[0] = s->modifiers & 0xff; @@ -710,7 +717,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); memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes)); s->head = 0; s->n = 0; @@ -845,7 +853,7 @@ static void usb_hid_handle_destroy(USBDevice *dev) switch(s->kind) { case USB_KEYBOARD: - qemu_remove_kbd_event_handler(); + qemu_remove_kbd_event_handler(s->kbd.eh_entry); break; default: qemu_remove_mouse_event_handler(s->ptr.eh_entry); diff --git a/hw/xenfb.c b/hw/xenfb.c index 1db75fb..80760e8 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -66,6 +66,7 @@ struct XenInput { int button_state; /* Last seen pointer button state */ int extended; QEMUPutMouseEntry *qmouse; + QEMUPutKbdEntry *qkbd; }; #define UP_QUEUE 8 @@ -371,7 +372,7 @@ static int input_connect(struct XenDevice *xendev) if (rc != 0) return rc; - qemu_add_kbd_event_handler(xenfb_key_event, in); + in->qkbd = 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"); @@ -386,7 +387,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_remove_kbd_event_handler(in->qkbd); common_unbind(&in->c); } diff --git a/input.c b/input.c index 5664d3a..efec56e 100644 --- a/input.c +++ b/input.c @@ -28,26 +28,14 @@ #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 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; -} - -void qemu_remove_kbd_event_handler(void) -{ - qemu_put_kbd_event_opaque = NULL; - qemu_put_kbd_event = NULL; -} - static void check_mode_change(void) { static int current_is_absolute, current_has_absolute; @@ -66,6 +54,44 @@ static void check_mode_change(void) current_has_absolute = has_absolute; } +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, + void *opaque, + const char *name) +{ + static int index; + QEMUPutKbdEntry *s, *cursor; + + QTAILQ_FOREACH(cursor, &kbd_handlers, node) { + if (cursor->qemu_put_kbd_event == func && + cursor->qemu_put_kbd_event_opaque == opaque) { + 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); + s->index = index++; + + QTAILQ_INSERT_TAIL(&kbd_handlers, s, node); + + return s; +} + +void qemu_activate_keyboard_event_handler(QEMUPutKbdEntry *entry) +{ + QTAILQ_REMOVE(&kbd_handlers, entry, node); + QTAILQ_INSERT_HEAD(&kbd_handlers, entry, node); +} + +void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) +{ + QTAILQ_REMOVE(&kbd_handlers, entry, node); + qemu_free(entry); +} + QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute, const char *name) @@ -129,9 +155,14 @@ 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); + 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) -- 1.7.1