提交 5a37532d 编写于 作者: G Gerd Hoffmann 提交者: Anthony Liguori

input: introduce keyboard handler list

Add a linked list of keyboard handlers.  Added handlers will go
to the head of the list.  Removed handlers will be zapped from
the list.  The head of the list will be used for events.

This fixes the keyboard-dead-after-usb-kbd-unplug issue, key events
will be re-routed to the ps/2 kbd instead of being discarded.

[ v2: fix cut+paste bug found my Markus ]
Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
Message-id: 1366798118-3248-3-git-send-email-kraxel@redhat.com
Signed-off-by: NAnthony Liguori <aliguori@us.ibm.com>
上级 72711efb
...@@ -415,7 +415,7 @@ void hid_free(HIDState *hs) ...@@ -415,7 +415,7 @@ void hid_free(HIDState *hs)
{ {
switch (hs->kind) { switch (hs->kind) {
case HID_KEYBOARD: case HID_KEYBOARD:
qemu_remove_kbd_event_handler(); qemu_remove_kbd_event_handler(hs->kbd.eh_entry);
break; break;
case HID_MOUSE: case HID_MOUSE:
case HID_TABLET: case HID_TABLET:
...@@ -431,7 +431,7 @@ void hid_init(HIDState *hs, int kind, HIDEventFunc event) ...@@ -431,7 +431,7 @@ void hid_init(HIDState *hs, int kind, HIDEventFunc event)
hs->event = event; hs->event = event;
if (hs->kind == HID_KEYBOARD) { if (hs->kind == HID_KEYBOARD) {
qemu_add_kbd_event_handler(hid_keyboard_event, hs); hs->kbd.eh_entry = qemu_add_kbd_event_handler(hid_keyboard_event, hs);
} else if (hs->kind == HID_MOUSE) { } else if (hs->kind == HID_MOUSE) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs, hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0, "QEMU HID Mouse"); 0, "QEMU HID Mouse");
......
...@@ -31,6 +31,7 @@ typedef struct HIDKeyboardState { ...@@ -31,6 +31,7 @@ typedef struct HIDKeyboardState {
uint8_t leds; uint8_t leds;
uint8_t key[16]; uint8_t key[16];
int32_t keys; int32_t keys;
QEMUPutKbdEntry *eh_entry;
} HIDKeyboardState; } HIDKeyboardState;
struct HIDState { struct HIDState {
......
...@@ -29,10 +29,12 @@ typedef void QEMUPutLEDEvent(void *opaque, int ledstate); ...@@ -29,10 +29,12 @@ typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
typedef struct QEMUPutMouseEntry QEMUPutMouseEntry; typedef struct QEMUPutMouseEntry QEMUPutMouseEntry;
typedef struct QEMUPutKbdEntry QEMUPutKbdEntry;
typedef struct QEMUPutLEDEntry QEMUPutLEDEntry; typedef struct QEMUPutLEDEntry QEMUPutLEDEntry;
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
void qemu_remove_kbd_event_handler(void); void *opaque);
void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
void *opaque, int absolute, void *opaque, int absolute,
const char *name); const char *name);
......
...@@ -41,18 +41,25 @@ struct QEMUPutMouseEntry { ...@@ -41,18 +41,25 @@ struct QEMUPutMouseEntry {
QTAILQ_ENTRY(QEMUPutMouseEntry) node; QTAILQ_ENTRY(QEMUPutMouseEntry) node;
}; };
struct QEMUPutKbdEntry {
QEMUPutKBDEvent *put_kbd;
void *opaque;
QTAILQ_ENTRY(QEMUPutKbdEntry) next;
};
struct QEMUPutLEDEntry { struct QEMUPutLEDEntry {
QEMUPutLEDEvent *put_led; QEMUPutLEDEvent *put_led;
void *opaque; void *opaque;
QTAILQ_ENTRY(QEMUPutLEDEntry) next; QTAILQ_ENTRY(QEMUPutLEDEntry) next;
}; };
static QEMUPutKBDEvent *qemu_put_kbd_event; static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
static void *qemu_put_kbd_event_opaque; QTAILQ_HEAD_INITIALIZER(led_handlers);
static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers); static QTAILQ_HEAD(, QEMUPutKbdEntry) kbd_handlers =
QTAILQ_HEAD_INITIALIZER(kbd_handlers);
static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
QTAILQ_HEAD_INITIALIZER(mouse_handlers); QTAILQ_HEAD_INITIALIZER(mouse_handlers);
static NotifierList mouse_mode_notifiers = static NotifierList mouse_mode_notifiers =
NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
static const int key_defs[] = { static const int key_defs[] = {
...@@ -304,16 +311,20 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, ...@@ -304,16 +311,20 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
muldiv64(get_ticks_per_sec(), hold_time, 1000)); muldiv64(get_ticks_per_sec(), hold_time, 1000));
} }
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{ {
qemu_put_kbd_event_opaque = opaque; QEMUPutKbdEntry *entry;
qemu_put_kbd_event = func;
entry = g_malloc0(sizeof(QEMUPutKbdEntry));
entry->put_kbd = func;
entry->opaque = opaque;
QTAILQ_INSERT_HEAD(&kbd_handlers, entry, next);
return entry;
} }
void qemu_remove_kbd_event_handler(void) void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
{ {
qemu_put_kbd_event_opaque = NULL; QTAILQ_REMOVE(&kbd_handlers, entry, next);
qemu_put_kbd_event = NULL;
} }
static void check_mode_change(void) static void check_mode_change(void)
...@@ -397,11 +408,13 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) ...@@ -397,11 +408,13 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
void kbd_put_keycode(int keycode) void kbd_put_keycode(int keycode)
{ {
QEMUPutKbdEntry *entry = QTAILQ_FIRST(&kbd_handlers);
if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
return; return;
} }
if (qemu_put_kbd_event) { if (entry) {
qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode); entry->put_kbd(entry->opaque, keycode);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册