From 2858ab09e6f708e381fc1a1cc87e747a690c4884 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Thu, 24 Apr 2014 20:06:19 +0800 Subject: [PATCH 01/10] ps2: set ps/2 output buffer size as the same as kernel According to the PS/2 Mouse/Keyboard Protocol, the keyboard outupt buffer size is 16 bytes. And the PS2_QUEUE_SIZE 256 was introduced in Qemu from the very beginning. When I started a redhat5.6 32bit guest, meanwhile tapped the keyboard as quickly as possible, the screen would show me "i8042.c: No controller found". As a result, I couldn't use the keyboard in the VNC client. Previous discussion about the issue in maillist: http://thread.gmane.org/gmane.comp.emulators.qemu/43294/focus=47180 This patch has been tested on redhat5.6 32-bit/suse11sp3 64-bit guests. More easy meathod to reproduce: 1.boot a guest with libvirt. 2.connect to VNC client. 3.as you see the BIOS, bootloader, Linux booting, run the follow simply shell script: for((i=0;i<10000000;i++)) do virsh send-key redhat5.6 KEY_A; done Actual results: dmesg show "i8042.c: No controller found." And the keyboard is out of work. Signed-off-by: Gonglei Reviewed-by: Juan Quintela Signed-off-by: Gerd Hoffmann --- hw/input/ps2.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 34120796b1..9a016eb843 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -71,10 +71,12 @@ #define MOUSE_STATUS_ENABLED 0x20 #define MOUSE_STATUS_SCALE21 0x10 -#define PS2_QUEUE_SIZE 256 +#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */ typedef struct { - uint8_t data[PS2_QUEUE_SIZE]; + /* Keep the data array 256 bytes long, which compatibility + with older qemu versions. */ + uint8_t data[256]; int rptr, wptr, count; } PS2Queue; @@ -137,7 +139,7 @@ void ps2_queue(void *opaque, int b) PS2State *s = (PS2State *)opaque; PS2Queue *q = &s->queue; - if (q->count >= PS2_QUEUE_SIZE) + if (q->count >= PS2_QUEUE_SIZE - 1) return; q->data[q->wptr] = b; if (++q->wptr == PS2_QUEUE_SIZE) @@ -374,9 +376,8 @@ static void ps2_mouse_event(void *opaque, qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); } - if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && - (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) { - for(;;) { + if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { + while (s->common.queue.count < PS2_QUEUE_SIZE - 4) { /* if not remote, send event. Multiple events are sent if too big deltas */ ps2_mouse_send_packet(s); @@ -528,6 +529,34 @@ static void ps2_common_reset(PS2State *s) s->update_irq(s->update_arg, 0); } +static void ps2_common_post_load(PS2State *s) +{ + PS2Queue *q = &s->queue; + int size; + int i; + int tmp_data[PS2_QUEUE_SIZE]; + + /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ + size = q->count > PS2_QUEUE_SIZE ? 0 : q->count; + + /* move the queue elements to the start of data array */ + if (size > 0) { + for (i = 0; i < size; i++) { + /* move the queue elements to the temporary buffer */ + tmp_data[i] = q->data[q->rptr]; + if (++q->rptr == 256) { + q->rptr = 0; + } + } + memcpy(q->data, tmp_data, size); + } + /* reset rptr/wptr/count */ + q->rptr = 0; + q->wptr = size; + q->count = size; + s->update_irq(s->update_arg, q->count != 0); +} + static void ps2_kbd_reset(void *opaque) { PS2KbdState *s = (PS2KbdState *) opaque; @@ -600,18 +629,31 @@ static const VMStateDescription vmstate_ps2_keyboard_ledstate = { static int ps2_kbd_post_load(void* opaque, int version_id) { PS2KbdState *s = (PS2KbdState*)opaque; + PS2State *ps2 = &s->common; if (version_id == 2) s->scancode_set=2; + + ps2_common_post_load(ps2); + return 0; } +static void ps2_kbd_pre_save(void *opaque) +{ + PS2KbdState *s = (PS2KbdState *)opaque; + PS2State *ps2 = &s->common; + + ps2_common_post_load(ps2); +} + static const VMStateDescription vmstate_ps2_keyboard = { .name = "ps2kbd", .version_id = 3, .minimum_version_id = 2, .minimum_version_id_old = 2, .post_load = ps2_kbd_post_load, + .pre_save = ps2_kbd_pre_save, .fields = (VMStateField []) { VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State), VMSTATE_INT32(scan_enabled, PS2KbdState), @@ -629,11 +671,31 @@ static const VMStateDescription vmstate_ps2_keyboard = { } }; +static int ps2_mouse_post_load(void *opaque, int version_id) +{ + PS2MouseState *s = (PS2MouseState *)opaque; + PS2State *ps2 = &s->common; + + ps2_common_post_load(ps2); + + return 0; +} + +static void ps2_mouse_pre_save(void *opaque) +{ + PS2MouseState *s = (PS2MouseState *)opaque; + PS2State *ps2 = &s->common; + + ps2_common_post_load(ps2); +} + static const VMStateDescription vmstate_ps2_mouse = { .name = "ps2mouse", .version_id = 2, .minimum_version_id = 2, .minimum_version_id_old = 2, + .post_load = ps2_mouse_post_load, + .pre_save = ps2_mouse_pre_save, .fields = (VMStateField []) { VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), VMSTATE_UINT8(mouse_status, PS2MouseState), From 02aa76c2ba5df8db7c968d92959af2a7c35690a8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 11 Mar 2014 12:15:39 +0100 Subject: [PATCH 02/10] input: key mapping helpers Add helper functions to translate KeyValue (qapi key representation) into other representations: traditional qemu key numbers, qapi key codes (Q_KEY_CODE_*) and scancode sequences. Signed-off-by: Gerd Hoffmann --- include/ui/input.h | 4 + ui/Makefile.objs | 3 +- ui/input-keymap.c | 210 +++++++++++++++++++++++++++++++++++++++++++++ ui/input-legacy.c | 181 ++------------------------------------ 4 files changed, 223 insertions(+), 175 deletions(-) create mode 100644 ui/input-keymap.c diff --git a/include/ui/input.h b/include/ui/input.h index 4976f3da2c..010c903e80 100644 --- a/include/ui/input.h +++ b/include/ui/input.h @@ -35,6 +35,10 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool down); void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down); void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down); void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down); +int qemu_input_key_value_to_number(const KeyValue *value); +int qemu_input_key_value_to_qcode(const KeyValue *value); +int qemu_input_key_value_to_scancode(const KeyValue *value, bool down, + int *codes); InputEvent *qemu_input_event_new_btn(InputButton btn, bool down); void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down); diff --git a/ui/Makefile.objs b/ui/Makefile.objs index 4af420bfa8..6afb52a93c 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -7,7 +7,8 @@ vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o vnc-obj-$(CONFIG_VNC_WS) += vnc-ws.o vnc-obj-y += vnc-jobs.o -common-obj-y += keymaps.o console.o cursor.o input.o input-legacy.o qemu-pixman.o +common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o +common-obj-y += input.o input-keymap.o input-legacy.o common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o sdl2.o common-obj-$(CONFIG_COCOA) += cocoa.o diff --git a/ui/input-keymap.c b/ui/input-keymap.c new file mode 100644 index 0000000000..67a3ea72eb --- /dev/null +++ b/ui/input-keymap.c @@ -0,0 +1,210 @@ +#include "sysemu/sysemu.h" +#include "ui/keymaps.h" +#include "ui/input.h" + +static const int qcode_to_number[] = { + [Q_KEY_CODE_SHIFT] = 0x2a, + [Q_KEY_CODE_SHIFT_R] = 0x36, + + [Q_KEY_CODE_ALT] = 0x38, + [Q_KEY_CODE_ALT_R] = 0xb8, + [Q_KEY_CODE_ALTGR] = 0x64, + [Q_KEY_CODE_ALTGR_R] = 0xe4, + [Q_KEY_CODE_CTRL] = 0x1d, + [Q_KEY_CODE_CTRL_R] = 0x9d, + + [Q_KEY_CODE_MENU] = 0xdd, + + [Q_KEY_CODE_ESC] = 0x01, + + [Q_KEY_CODE_1] = 0x02, + [Q_KEY_CODE_2] = 0x03, + [Q_KEY_CODE_3] = 0x04, + [Q_KEY_CODE_4] = 0x05, + [Q_KEY_CODE_5] = 0x06, + [Q_KEY_CODE_6] = 0x07, + [Q_KEY_CODE_7] = 0x08, + [Q_KEY_CODE_8] = 0x09, + [Q_KEY_CODE_9] = 0x0a, + [Q_KEY_CODE_0] = 0x0b, + [Q_KEY_CODE_MINUS] = 0x0c, + [Q_KEY_CODE_EQUAL] = 0x0d, + [Q_KEY_CODE_BACKSPACE] = 0x0e, + + [Q_KEY_CODE_TAB] = 0x0f, + [Q_KEY_CODE_Q] = 0x10, + [Q_KEY_CODE_W] = 0x11, + [Q_KEY_CODE_E] = 0x12, + [Q_KEY_CODE_R] = 0x13, + [Q_KEY_CODE_T] = 0x14, + [Q_KEY_CODE_Y] = 0x15, + [Q_KEY_CODE_U] = 0x16, + [Q_KEY_CODE_I] = 0x17, + [Q_KEY_CODE_O] = 0x18, + [Q_KEY_CODE_P] = 0x19, + [Q_KEY_CODE_BRACKET_LEFT] = 0x1a, + [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b, + [Q_KEY_CODE_RET] = 0x1c, + + [Q_KEY_CODE_A] = 0x1e, + [Q_KEY_CODE_S] = 0x1f, + [Q_KEY_CODE_D] = 0x20, + [Q_KEY_CODE_F] = 0x21, + [Q_KEY_CODE_G] = 0x22, + [Q_KEY_CODE_H] = 0x23, + [Q_KEY_CODE_J] = 0x24, + [Q_KEY_CODE_K] = 0x25, + [Q_KEY_CODE_L] = 0x26, + [Q_KEY_CODE_SEMICOLON] = 0x27, + [Q_KEY_CODE_APOSTROPHE] = 0x28, + [Q_KEY_CODE_GRAVE_ACCENT] = 0x29, + + [Q_KEY_CODE_BACKSLASH] = 0x2b, + [Q_KEY_CODE_Z] = 0x2c, + [Q_KEY_CODE_X] = 0x2d, + [Q_KEY_CODE_C] = 0x2e, + [Q_KEY_CODE_V] = 0x2f, + [Q_KEY_CODE_B] = 0x30, + [Q_KEY_CODE_N] = 0x31, + [Q_KEY_CODE_M] = 0x32, + [Q_KEY_CODE_COMMA] = 0x33, + [Q_KEY_CODE_DOT] = 0x34, + [Q_KEY_CODE_SLASH] = 0x35, + + [Q_KEY_CODE_ASTERISK] = 0x37, + + [Q_KEY_CODE_SPC] = 0x39, + [Q_KEY_CODE_CAPS_LOCK] = 0x3a, + [Q_KEY_CODE_F1] = 0x3b, + [Q_KEY_CODE_F2] = 0x3c, + [Q_KEY_CODE_F3] = 0x3d, + [Q_KEY_CODE_F4] = 0x3e, + [Q_KEY_CODE_F5] = 0x3f, + [Q_KEY_CODE_F6] = 0x40, + [Q_KEY_CODE_F7] = 0x41, + [Q_KEY_CODE_F8] = 0x42, + [Q_KEY_CODE_F9] = 0x43, + [Q_KEY_CODE_F10] = 0x44, + [Q_KEY_CODE_NUM_LOCK] = 0x45, + [Q_KEY_CODE_SCROLL_LOCK] = 0x46, + + [Q_KEY_CODE_KP_DIVIDE] = 0xb5, + [Q_KEY_CODE_KP_MULTIPLY] = 0x37, + [Q_KEY_CODE_KP_SUBTRACT] = 0x4a, + [Q_KEY_CODE_KP_ADD] = 0x4e, + [Q_KEY_CODE_KP_ENTER] = 0x9c, + [Q_KEY_CODE_KP_DECIMAL] = 0x53, + [Q_KEY_CODE_SYSRQ] = 0x54, + + [Q_KEY_CODE_KP_0] = 0x52, + [Q_KEY_CODE_KP_1] = 0x4f, + [Q_KEY_CODE_KP_2] = 0x50, + [Q_KEY_CODE_KP_3] = 0x51, + [Q_KEY_CODE_KP_4] = 0x4b, + [Q_KEY_CODE_KP_5] = 0x4c, + [Q_KEY_CODE_KP_6] = 0x4d, + [Q_KEY_CODE_KP_7] = 0x47, + [Q_KEY_CODE_KP_8] = 0x48, + [Q_KEY_CODE_KP_9] = 0x49, + + [Q_KEY_CODE_LESS] = 0x56, + + [Q_KEY_CODE_F11] = 0x57, + [Q_KEY_CODE_F12] = 0x58, + + [Q_KEY_CODE_PRINT] = 0xb7, + + [Q_KEY_CODE_HOME] = 0xc7, + [Q_KEY_CODE_PGUP] = 0xc9, + [Q_KEY_CODE_PGDN] = 0xd1, + [Q_KEY_CODE_END] = 0xcf, + + [Q_KEY_CODE_LEFT] = 0xcb, + [Q_KEY_CODE_UP] = 0xc8, + [Q_KEY_CODE_DOWN] = 0xd0, + [Q_KEY_CODE_RIGHT] = 0xcd, + + [Q_KEY_CODE_INSERT] = 0xd2, + [Q_KEY_CODE_DELETE] = 0xd3, +#ifdef NEED_CPU_H +#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64) + [Q_KEY_CODE_STOP] = 0xf0, + [Q_KEY_CODE_AGAIN] = 0xf1, + [Q_KEY_CODE_PROPS] = 0xf2, + [Q_KEY_CODE_UNDO] = 0xf3, + [Q_KEY_CODE_FRONT] = 0xf4, + [Q_KEY_CODE_COPY] = 0xf5, + [Q_KEY_CODE_OPEN] = 0xf6, + [Q_KEY_CODE_PASTE] = 0xf7, + [Q_KEY_CODE_FIND] = 0xf8, + [Q_KEY_CODE_CUT] = 0xf9, + [Q_KEY_CODE_LF] = 0xfa, + [Q_KEY_CODE_HELP] = 0xfb, + [Q_KEY_CODE_META_L] = 0xfc, + [Q_KEY_CODE_META_R] = 0xfd, + [Q_KEY_CODE_COMPOSE] = 0xfe, +#endif +#endif + [Q_KEY_CODE_MAX] = 0, +}; + +static int number_to_qcode[0xff]; + +int qemu_input_key_value_to_number(const KeyValue *value) +{ + if (value->kind == KEY_VALUE_KIND_QCODE) { + return qcode_to_number[value->qcode]; + } else { + assert(value->kind == KEY_VALUE_KIND_NUMBER); + return value->number; + } +} + +int qemu_input_key_value_to_qcode(const KeyValue *value) +{ + static int first = true; + + if (first) { + int qcode, number; + first = false; + for (qcode = 0; qcode < Q_KEY_CODE_MAX; qcode++) { + number = qcode_to_number[qcode]; + assert(number < ARRAY_SIZE(number_to_qcode)); + number_to_qcode[number] = qcode; + } + } + + if (value->kind == KEY_VALUE_KIND_QCODE) { + return value->qcode; + } else { + assert(value->kind == KEY_VALUE_KIND_NUMBER); + return number_to_qcode[value->number]; + } +} + +int qemu_input_key_value_to_scancode(const KeyValue *value, bool down, + int *codes) +{ + int keycode = qemu_input_key_value_to_number(value); + int count = 0; + + if (value->kind == KEY_VALUE_KIND_QCODE && + value->qcode == Q_KEY_CODE_PAUSE) { + /* specific case */ + int v = down ? 0 : 0x80; + codes[count++] = 0xe1; + codes[count++] = 0x1d | v; + codes[count++] = 0x45 | v; + return count; + } + if (keycode & SCANCODE_GREY) { + codes[count++] = SCANCODE_EMUL0; + keycode &= ~SCANCODE_GREY; + } + if (!down) { + keycode |= SCANCODE_UP; + } + codes[count++] = keycode; + + return count; +} diff --git a/ui/input-legacy.c b/ui/input-legacy.c index 1aa2605b75..ff85220a3a 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -60,152 +60,6 @@ static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = QTAILQ_HEAD_INITIALIZER(mouse_handlers); -static const int key_defs[] = { - [Q_KEY_CODE_SHIFT] = 0x2a, - [Q_KEY_CODE_SHIFT_R] = 0x36, - - [Q_KEY_CODE_ALT] = 0x38, - [Q_KEY_CODE_ALT_R] = 0xb8, - [Q_KEY_CODE_ALTGR] = 0x64, - [Q_KEY_CODE_ALTGR_R] = 0xe4, - [Q_KEY_CODE_CTRL] = 0x1d, - [Q_KEY_CODE_CTRL_R] = 0x9d, - - [Q_KEY_CODE_MENU] = 0xdd, - - [Q_KEY_CODE_ESC] = 0x01, - - [Q_KEY_CODE_1] = 0x02, - [Q_KEY_CODE_2] = 0x03, - [Q_KEY_CODE_3] = 0x04, - [Q_KEY_CODE_4] = 0x05, - [Q_KEY_CODE_5] = 0x06, - [Q_KEY_CODE_6] = 0x07, - [Q_KEY_CODE_7] = 0x08, - [Q_KEY_CODE_8] = 0x09, - [Q_KEY_CODE_9] = 0x0a, - [Q_KEY_CODE_0] = 0x0b, - [Q_KEY_CODE_MINUS] = 0x0c, - [Q_KEY_CODE_EQUAL] = 0x0d, - [Q_KEY_CODE_BACKSPACE] = 0x0e, - - [Q_KEY_CODE_TAB] = 0x0f, - [Q_KEY_CODE_Q] = 0x10, - [Q_KEY_CODE_W] = 0x11, - [Q_KEY_CODE_E] = 0x12, - [Q_KEY_CODE_R] = 0x13, - [Q_KEY_CODE_T] = 0x14, - [Q_KEY_CODE_Y] = 0x15, - [Q_KEY_CODE_U] = 0x16, - [Q_KEY_CODE_I] = 0x17, - [Q_KEY_CODE_O] = 0x18, - [Q_KEY_CODE_P] = 0x19, - [Q_KEY_CODE_BRACKET_LEFT] = 0x1a, - [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b, - [Q_KEY_CODE_RET] = 0x1c, - - [Q_KEY_CODE_A] = 0x1e, - [Q_KEY_CODE_S] = 0x1f, - [Q_KEY_CODE_D] = 0x20, - [Q_KEY_CODE_F] = 0x21, - [Q_KEY_CODE_G] = 0x22, - [Q_KEY_CODE_H] = 0x23, - [Q_KEY_CODE_J] = 0x24, - [Q_KEY_CODE_K] = 0x25, - [Q_KEY_CODE_L] = 0x26, - [Q_KEY_CODE_SEMICOLON] = 0x27, - [Q_KEY_CODE_APOSTROPHE] = 0x28, - [Q_KEY_CODE_GRAVE_ACCENT] = 0x29, - - [Q_KEY_CODE_BACKSLASH] = 0x2b, - [Q_KEY_CODE_Z] = 0x2c, - [Q_KEY_CODE_X] = 0x2d, - [Q_KEY_CODE_C] = 0x2e, - [Q_KEY_CODE_V] = 0x2f, - [Q_KEY_CODE_B] = 0x30, - [Q_KEY_CODE_N] = 0x31, - [Q_KEY_CODE_M] = 0x32, - [Q_KEY_CODE_COMMA] = 0x33, - [Q_KEY_CODE_DOT] = 0x34, - [Q_KEY_CODE_SLASH] = 0x35, - - [Q_KEY_CODE_ASTERISK] = 0x37, - - [Q_KEY_CODE_SPC] = 0x39, - [Q_KEY_CODE_CAPS_LOCK] = 0x3a, - [Q_KEY_CODE_F1] = 0x3b, - [Q_KEY_CODE_F2] = 0x3c, - [Q_KEY_CODE_F3] = 0x3d, - [Q_KEY_CODE_F4] = 0x3e, - [Q_KEY_CODE_F5] = 0x3f, - [Q_KEY_CODE_F6] = 0x40, - [Q_KEY_CODE_F7] = 0x41, - [Q_KEY_CODE_F8] = 0x42, - [Q_KEY_CODE_F9] = 0x43, - [Q_KEY_CODE_F10] = 0x44, - [Q_KEY_CODE_NUM_LOCK] = 0x45, - [Q_KEY_CODE_SCROLL_LOCK] = 0x46, - - [Q_KEY_CODE_KP_DIVIDE] = 0xb5, - [Q_KEY_CODE_KP_MULTIPLY] = 0x37, - [Q_KEY_CODE_KP_SUBTRACT] = 0x4a, - [Q_KEY_CODE_KP_ADD] = 0x4e, - [Q_KEY_CODE_KP_ENTER] = 0x9c, - [Q_KEY_CODE_KP_DECIMAL] = 0x53, - [Q_KEY_CODE_SYSRQ] = 0x54, - - [Q_KEY_CODE_KP_0] = 0x52, - [Q_KEY_CODE_KP_1] = 0x4f, - [Q_KEY_CODE_KP_2] = 0x50, - [Q_KEY_CODE_KP_3] = 0x51, - [Q_KEY_CODE_KP_4] = 0x4b, - [Q_KEY_CODE_KP_5] = 0x4c, - [Q_KEY_CODE_KP_6] = 0x4d, - [Q_KEY_CODE_KP_7] = 0x47, - [Q_KEY_CODE_KP_8] = 0x48, - [Q_KEY_CODE_KP_9] = 0x49, - - [Q_KEY_CODE_LESS] = 0x56, - - [Q_KEY_CODE_F11] = 0x57, - [Q_KEY_CODE_F12] = 0x58, - - [Q_KEY_CODE_PRINT] = 0xb7, - - [Q_KEY_CODE_HOME] = 0xc7, - [Q_KEY_CODE_PGUP] = 0xc9, - [Q_KEY_CODE_PGDN] = 0xd1, - [Q_KEY_CODE_END] = 0xcf, - - [Q_KEY_CODE_LEFT] = 0xcb, - [Q_KEY_CODE_UP] = 0xc8, - [Q_KEY_CODE_DOWN] = 0xd0, - [Q_KEY_CODE_RIGHT] = 0xcd, - - [Q_KEY_CODE_INSERT] = 0xd2, - [Q_KEY_CODE_DELETE] = 0xd3, -#ifdef NEED_CPU_H -#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64) - [Q_KEY_CODE_STOP] = 0xf0, - [Q_KEY_CODE_AGAIN] = 0xf1, - [Q_KEY_CODE_PROPS] = 0xf2, - [Q_KEY_CODE_UNDO] = 0xf3, - [Q_KEY_CODE_FRONT] = 0xf4, - [Q_KEY_CODE_COPY] = 0xf5, - [Q_KEY_CODE_OPEN] = 0xf6, - [Q_KEY_CODE_PASTE] = 0xf7, - [Q_KEY_CODE_FIND] = 0xf8, - [Q_KEY_CODE_CUT] = 0xf9, - [Q_KEY_CODE_LF] = 0xfa, - [Q_KEY_CODE_HELP] = 0xfb, - [Q_KEY_CODE_META_L] = 0xfc, - [Q_KEY_CODE_META_R] = 0xfd, - [Q_KEY_CODE_COMPOSE] = 0xfe, -#endif -#endif - [Q_KEY_CODE_MAX] = 0, -}; - int index_from_key(const char *key) { int i; @@ -224,16 +78,6 @@ static int *keycodes; static int keycodes_size; static QEMUTimer *key_timer; -static int keycode_from_keyvalue(const KeyValue *value) -{ - if (value->kind == KEY_VALUE_KIND_QCODE) { - return key_defs[value->qcode]; - } else { - assert(value->kind == KEY_VALUE_KIND_NUMBER); - return value->number; - } -} - static void free_keycodes(void) { g_free(keycodes); @@ -272,7 +116,7 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, for (p = keys; p != NULL; p = p->next) { /* key down events */ - keycode = keycode_from_keyvalue(p->value); + keycode = qemu_input_key_value_to_number(p->value); if (keycode < 0x01 || keycode > 0xff) { error_setg(errp, "invalid hex keycode 0x%x", keycode); free_keycodes(); @@ -294,28 +138,17 @@ static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) { QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev; - int keycode = keycode_from_keyvalue(evt->key->key); + int scancodes[3], i, count; if (!entry || !entry->put_kbd) { return; } - if (evt->key->key->kind == KEY_VALUE_KIND_QCODE && - evt->key->key->qcode == Q_KEY_CODE_PAUSE) { - /* specific case */ - int v = evt->key->down ? 0 : 0x80; - entry->put_kbd(entry->opaque, 0xe1); - entry->put_kbd(entry->opaque, 0x1d | v); - entry->put_kbd(entry->opaque, 0x45 | v); - return; + count = qemu_input_key_value_to_scancode(evt->key->key, + evt->key->down, + scancodes); + for (i = 0; i < count; i++) { + entry->put_kbd(entry->opaque, scancodes[i]); } - if (keycode & SCANCODE_GREY) { - entry->put_kbd(entry->opaque, SCANCODE_EMUL0); - keycode &= ~SCANCODE_GREY; - } - if (!evt->key->down) { - keycode |= SCANCODE_UP; - } - entry->put_kbd(entry->opaque, keycode); } static QemuInputHandler legacy_kbd_handler = { From 528728fd93df348f9003d1067fb26e79f377bfa9 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Sun, 16 Mar 2014 00:38:45 +0100 Subject: [PATCH 03/10] input: add qemu_input_handler_deactivate Signed-off-by: Gerd Hoffmann --- include/ui/input.h | 1 + ui/input.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/ui/input.h b/include/ui/input.h index 010c903e80..3d3d487f18 100644 --- a/include/ui/input.h +++ b/include/ui/input.h @@ -27,6 +27,7 @@ struct QemuInputHandler { QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev, QemuInputHandler *handler); void qemu_input_handler_activate(QemuInputHandlerState *s); +void qemu_input_handler_deactivate(QemuInputHandlerState *s); void qemu_input_handler_unregister(QemuInputHandlerState *s); void qemu_input_event_send(QemuConsole *src, InputEvent *evt); void qemu_input_event_sync(void); diff --git a/ui/input.c b/ui/input.c index 1ed0e783b1..fc91fba83c 100644 --- a/ui/input.c +++ b/ui/input.c @@ -39,6 +39,13 @@ void qemu_input_handler_activate(QemuInputHandlerState *s) qemu_input_check_mode_change(); } +void qemu_input_handler_deactivate(QemuInputHandlerState *s) +{ + QTAILQ_REMOVE(&handlers, s, node); + QTAILQ_INSERT_TAIL(&handlers, s, node); + qemu_input_check_mode_change(); +} + void qemu_input_handler_unregister(QemuInputHandlerState *s) { QTAILQ_REMOVE(&handlers, s, node); From ce53f2f98faa2f5aff3e7c841a12be187293db0d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 29 Apr 2014 13:17:43 +0200 Subject: [PATCH 04/10] input: use KeyValue directly in sendkey monitor command Signed-off-by: Gerd Hoffmann --- ui/input-legacy.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/ui/input-legacy.c b/ui/input-legacy.c index ff85220a3a..2a538607a2 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -74,38 +74,44 @@ int index_from_key(const char *key) return i; } -static int *keycodes; -static int keycodes_size; +static KeyValue **keyvalues; +static int keyvalues_size; static QEMUTimer *key_timer; -static void free_keycodes(void) +static void free_keyvalues(void) { - g_free(keycodes); - keycodes = NULL; - keycodes_size = 0; + g_free(keyvalues); + keyvalues = NULL; + keyvalues_size = 0; } static void release_keys(void *opaque) { - while (keycodes_size > 0) { - qemu_input_event_send_key_number(NULL, keycodes[--keycodes_size], - false); + while (keyvalues_size > 0) { + qemu_input_event_send_key(NULL, keyvalues[--keyvalues_size], + false); } - free_keycodes(); + free_keyvalues(); +} + +static KeyValue *copy_key_value(KeyValue *src) +{ + KeyValue *dst = g_new(KeyValue, 1); + memcpy(dst, src, sizeof(*src)); + return dst; } void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, Error **errp) { - int keycode; KeyValueList *p; if (!key_timer) { key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL); } - if (keycodes != NULL) { + if (keyvalues != NULL) { timer_del(key_timer); release_keys(NULL); } @@ -115,23 +121,16 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, } for (p = keys; p != NULL; p = p->next) { - /* key down events */ - keycode = qemu_input_key_value_to_number(p->value); - if (keycode < 0x01 || keycode > 0xff) { - error_setg(errp, "invalid hex keycode 0x%x", keycode); - free_keycodes(); - return; - } + qemu_input_event_send_key(NULL, copy_key_value(p->value), true); - qemu_input_event_send_key_number(NULL, keycode, true); - - keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1)); - keycodes[keycodes_size++] = keycode; + keyvalues = g_realloc(keyvalues, sizeof(KeyValue *) * + (keyvalues_size + 1)); + keyvalues[keyvalues_size++] = copy_key_value(p->value); } /* delayed key up events */ timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - muldiv64(get_ticks_per_sec(), hold_time, 1000)); + muldiv64(get_ticks_per_sec(), hold_time, 1000)); } static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, From 66e6536e0cdc8c1137230b1b935a5af693b5d9ca Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Mar 2014 12:39:38 +0100 Subject: [PATCH 05/10] input: switch ps/2 kbd to new input api Signed-off-by: Gerd Hoffmann --- hw/input/ps2.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 9a016eb843..9347a856c4 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -24,6 +24,7 @@ #include "hw/hw.h" #include "hw/input/ps2.h" #include "ui/console.h" +#include "ui/input.h" #include "sysemu/sysemu.h" /* debug PC keyboard */ @@ -172,6 +173,21 @@ static void ps2_put_keycode(void *opaque, int keycode) ps2_queue(&s->common, keycode); } +static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) +{ + PS2KbdState *s = (PS2KbdState *)dev; + int scancodes[3], i, count; + + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); + count = qemu_input_key_value_to_scancode(evt->key->key, + evt->key->down, + scancodes); + for (i = 0; i < count; i++) { + ps2_put_keycode(s, scancodes[i]); + } +} + uint32_t ps2_read_data(void *opaque) { PS2State *s = (PS2State *)opaque; @@ -712,6 +728,12 @@ static const VMStateDescription vmstate_ps2_mouse = { } }; +static QemuInputHandler ps2_keyboard_handler = { + .name = "QEMU PS/2 Keyboard", + .mask = INPUT_EVENT_MASK_KEY, + .event = ps2_keyboard_event, +}; + void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) { PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState)); @@ -720,7 +742,8 @@ 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_input_handler_register((DeviceState *)s, + &ps2_keyboard_handler); qemu_register_reset(ps2_kbd_reset, s); return s; } From 2a766d294ae0d4d2e9b178ce0b9a966bc678e7e6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Mar 2014 12:58:29 +0100 Subject: [PATCH 06/10] input: switch ps/2 mouse to new input api Signed-off-by: Gerd Hoffmann --- hw/input/ps2.c | 67 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 9347a856c4..22b77dfe5c 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -370,28 +370,55 @@ static void ps2_mouse_send_packet(PS2MouseState *s) s->mouse_dz -= dz1; } -static void ps2_mouse_event(void *opaque, - int dx, int dy, int dz, int buttons_state) +static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) { - PS2MouseState *s = opaque; + static const int bmap[INPUT_BUTTON_MAX] = { + [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, + [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, + [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, + }; + PS2MouseState *s = (PS2MouseState *)dev; /* check if deltas are recorded when disabled */ if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) return; - s->mouse_dx += dx; - s->mouse_dy -= dy; - s->mouse_dz += dz; - /* XXX: SDL sometimes generates nul events: we delete them */ - if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && - s->mouse_buttons == buttons_state) - return; - s->mouse_buttons = buttons_state; + switch (evt->kind) { + case INPUT_EVENT_KIND_REL: + if (evt->rel->axis == INPUT_AXIS_X) { + s->mouse_dx += evt->rel->value; + } else if (evt->rel->axis == INPUT_AXIS_Y) { + s->mouse_dy -= evt->rel->value; + } + break; - if (buttons_state) { + case INPUT_EVENT_KIND_BTN: + if (evt->btn->down) { + s->mouse_buttons |= bmap[evt->btn->button]; + if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) { + s->mouse_dz--; + } else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { + s->mouse_dz++; + } + } else { + s->mouse_buttons &= ~bmap[evt->btn->button]; + } + break; + + default: + /* keep gcc happy */ + break; + } +} + +static void ps2_mouse_sync(DeviceState *dev) +{ + PS2MouseState *s = (PS2MouseState *)dev; + + if (s->mouse_buttons) { qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); } - if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { while (s->common.queue.count < PS2_QUEUE_SIZE - 4) { /* if not remote, send event. Multiple events are sent if @@ -405,7 +432,9 @@ static void ps2_mouse_event(void *opaque, void ps2_mouse_fake_event(void *opaque) { - ps2_mouse_event(opaque, 1, 0, 0, 0); + PS2MouseState *s = opaque; + s->mouse_dx++; + ps2_mouse_sync(opaque); } void ps2_write_mouse(void *opaque, int val) @@ -748,6 +777,13 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) return s; } +static QemuInputHandler ps2_mouse_handler = { + .name = "QEMU PS/2 Mouse", + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, + .event = ps2_mouse_event, + .sync = ps2_mouse_sync, +}; + void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) { PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState)); @@ -755,7 +791,8 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) s->common.update_irq = update_irq; s->common.update_arg = update_arg; vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); - qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); + qemu_input_handler_register((DeviceState *)s, + &ps2_mouse_handler); qemu_register_reset(ps2_mouse_reset, s); return s; } From 65e7545ea3c65a6468fb59418a6dbe66ef71d6d1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Mar 2014 13:16:21 +0100 Subject: [PATCH 07/10] input: switch sparc32 kbd to new input api Nasty 0xe0 logic is gone. We map through QKeyCode now, giving us a nice, readable mapping table. Quick smoke test in OpenFirmware looks ok. Careful check from arch maintainers would be very nice, especially on the capslock and numlock logic. I'm not fully sure whenever I got it translated correctly and also what it is supposed to do in the first place ... Signed-off-by: Gerd Hoffmann --- hw/char/escc.c | 227 ++++++++++++++++++++++++++++++++++++------------- trace-events | 4 +- 2 files changed, 171 insertions(+), 60 deletions(-) diff --git a/hw/char/escc.c b/hw/char/escc.c index 6397f6f282..823fe8dc68 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -27,6 +27,7 @@ #include "hw/char/escc.h" #include "sysemu/char.h" #include "ui/console.h" +#include "ui/input.h" #include "trace.h" /* @@ -94,6 +95,7 @@ typedef struct ChannelState { ChnID chn; // this channel, A (base+4) or B (base+0) ChnType type; uint8_t rx, tx; + QemuInputHandlerState *hs; } ChannelState; #define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC) @@ -714,71 +716,179 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, return &d->mmio; } -static const uint8_t keycodes[128] = { - 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12, - 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112, - 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0, - 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66, - 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67, +static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = { + [Q_KEY_CODE_SHIFT] = 99, + [Q_KEY_CODE_SHIFT_R] = 110, + [Q_KEY_CODE_ALT] = 19, + [Q_KEY_CODE_ALT_R] = 13, + [Q_KEY_CODE_ALTGR] = 13, + [Q_KEY_CODE_CTRL] = 76, + [Q_KEY_CODE_CTRL_R] = 76, + [Q_KEY_CODE_ESC] = 29, + [Q_KEY_CODE_1] = 30, + [Q_KEY_CODE_2] = 31, + [Q_KEY_CODE_3] = 32, + [Q_KEY_CODE_4] = 33, + [Q_KEY_CODE_5] = 34, + [Q_KEY_CODE_6] = 35, + [Q_KEY_CODE_7] = 36, + [Q_KEY_CODE_8] = 37, + [Q_KEY_CODE_9] = 38, + [Q_KEY_CODE_0] = 39, + [Q_KEY_CODE_MINUS] = 40, + [Q_KEY_CODE_EQUAL] = 41, + [Q_KEY_CODE_BACKSPACE] = 43, + [Q_KEY_CODE_TAB] = 53, + [Q_KEY_CODE_Q] = 54, + [Q_KEY_CODE_W] = 55, + [Q_KEY_CODE_E] = 56, + [Q_KEY_CODE_R] = 57, + [Q_KEY_CODE_T] = 58, + [Q_KEY_CODE_Y] = 59, + [Q_KEY_CODE_U] = 60, + [Q_KEY_CODE_I] = 61, + [Q_KEY_CODE_O] = 62, + [Q_KEY_CODE_P] = 63, + [Q_KEY_CODE_BRACKET_LEFT] = 64, + [Q_KEY_CODE_BRACKET_RIGHT] = 65, + [Q_KEY_CODE_RET] = 89, + [Q_KEY_CODE_A] = 77, + [Q_KEY_CODE_S] = 78, + [Q_KEY_CODE_D] = 79, + [Q_KEY_CODE_F] = 80, + [Q_KEY_CODE_G] = 81, + [Q_KEY_CODE_H] = 82, + [Q_KEY_CODE_J] = 83, + [Q_KEY_CODE_K] = 84, + [Q_KEY_CODE_L] = 85, + [Q_KEY_CODE_SEMICOLON] = 86, + [Q_KEY_CODE_APOSTROPHE] = 87, + [Q_KEY_CODE_GRAVE_ACCENT] = 42, + [Q_KEY_CODE_BACKSLASH] = 88, + [Q_KEY_CODE_Z] = 100, + [Q_KEY_CODE_X] = 101, + [Q_KEY_CODE_C] = 102, + [Q_KEY_CODE_V] = 103, + [Q_KEY_CODE_B] = 104, + [Q_KEY_CODE_N] = 105, + [Q_KEY_CODE_M] = 106, + [Q_KEY_CODE_COMMA] = 107, + [Q_KEY_CODE_DOT] = 108, + [Q_KEY_CODE_SLASH] = 109, + [Q_KEY_CODE_ASTERISK] = 47, + [Q_KEY_CODE_SPC] = 121, + [Q_KEY_CODE_CAPS_LOCK] = 119, + [Q_KEY_CODE_F1] = 5, + [Q_KEY_CODE_F2] = 6, + [Q_KEY_CODE_F3] = 8, + [Q_KEY_CODE_F4] = 10, + [Q_KEY_CODE_F5] = 12, + [Q_KEY_CODE_F6] = 14, + [Q_KEY_CODE_F7] = 16, + [Q_KEY_CODE_F8] = 17, + [Q_KEY_CODE_F9] = 18, + [Q_KEY_CODE_F10] = 7, + [Q_KEY_CODE_NUM_LOCK] = 98, + [Q_KEY_CODE_SCROLL_LOCK] = 23, + [Q_KEY_CODE_KP_DIVIDE] = 109, + [Q_KEY_CODE_KP_MULTIPLY] = 47, + [Q_KEY_CODE_KP_SUBTRACT] = 71, + [Q_KEY_CODE_KP_ADD] = 125, + [Q_KEY_CODE_KP_ENTER] = 90, + [Q_KEY_CODE_KP_DECIMAL] = 50, + [Q_KEY_CODE_KP_0] = 94, + [Q_KEY_CODE_KP_1] = 112, + [Q_KEY_CODE_KP_2] = 113, + [Q_KEY_CODE_KP_3] = 114, + [Q_KEY_CODE_KP_4] = 91, + [Q_KEY_CODE_KP_5] = 92, + [Q_KEY_CODE_KP_6] = 93, + [Q_KEY_CODE_KP_7] = 68, + [Q_KEY_CODE_KP_8] = 69, + [Q_KEY_CODE_KP_9] = 70, + [Q_KEY_CODE_LESS] = 124, + [Q_KEY_CODE_F11] = 9, + [Q_KEY_CODE_F12] = 11, + [Q_KEY_CODE_HOME] = 68, + [Q_KEY_CODE_PGUP] = 70, + [Q_KEY_CODE_PGDN] = 114, + [Q_KEY_CODE_END] = 112, + [Q_KEY_CODE_LEFT] = 91, + [Q_KEY_CODE_UP] = 69, + [Q_KEY_CODE_DOWN] = 113, + [Q_KEY_CODE_RIGHT] = 93, + [Q_KEY_CODE_INSERT] = 94, + [Q_KEY_CODE_DELETE] = 50, + [Q_KEY_CODE_STOP] = 1, + [Q_KEY_CODE_AGAIN] = 3, + [Q_KEY_CODE_PROPS] = 25, + [Q_KEY_CODE_UNDO] = 26, + [Q_KEY_CODE_FRONT] = 49, + [Q_KEY_CODE_COPY] = 52, + [Q_KEY_CODE_OPEN] = 72, + [Q_KEY_CODE_PASTE] = 73, + [Q_KEY_CODE_FIND] = 97, + [Q_KEY_CODE_CUT] = 99, + [Q_KEY_CODE_LF] = 111, + [Q_KEY_CODE_HELP] = 118, + [Q_KEY_CODE_META_L] = 120, + [Q_KEY_CODE_META_R] = 122, + [Q_KEY_CODE_COMPOSE] = 67, }; -static const uint8_t e0_keycodes[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112, - 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0, -}; - -static void sunkbd_event(void *opaque, int ch) +static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) { - ChannelState *s = opaque; - int release = ch & 0x80; + ChannelState *s = (ChannelState *)dev; + int qcode, keycode; - trace_escc_sunkbd_event_in(ch); - switch (ch) { - case 58: // Caps lock press - s->caps_lock_mode ^= 1; - if (s->caps_lock_mode == 2) - return; // Drop second press - break; - case 69: // Num lock press - s->num_lock_mode ^= 1; - if (s->num_lock_mode == 2) - return; // Drop second press - break; - case 186: // Caps lock release - s->caps_lock_mode ^= 2; - if (s->caps_lock_mode == 3) - return; // Drop first release - break; - case 197: // Num lock release - s->num_lock_mode ^= 2; - if (s->num_lock_mode == 3) - return; // Drop first release - break; - case 0xe0: - s->e0_mode = 1; - return; - default: - break; + assert(evt->kind == INPUT_EVENT_KIND_KEY); + qcode = qemu_input_key_value_to_qcode(evt->key->key); + trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode], + evt->key->down); + + if (qcode == Q_KEY_CODE_CAPS_LOCK) { + if (evt->key->down) { + s->caps_lock_mode ^= 1; + if (s->caps_lock_mode == 2) { + return; /* Drop second press */ + } + } else { + s->caps_lock_mode ^= 2; + if (s->caps_lock_mode == 3) { + return; /* Drop first release */ + } + } } - if (s->e0_mode) { - s->e0_mode = 0; - ch = e0_keycodes[ch & 0x7f]; - } else { - ch = keycodes[ch & 0x7f]; + + if (qcode == Q_KEY_CODE_NUM_LOCK) { + if (evt->key->down) { + s->num_lock_mode ^= 1; + if (s->num_lock_mode == 2) { + return; /* Drop second press */ + } + } else { + s->num_lock_mode ^= 2; + if (s->num_lock_mode == 3) { + return; /* Drop first release */ + } + } } - trace_escc_sunkbd_event_out(ch); - put_queue(s, ch | release); + + keycode = qcode_to_keycode[qcode]; + if (!evt->key->down) { + keycode |= 0x80; + } + trace_escc_sunkbd_event_out(keycode); + put_queue(s, keycode); } +static QemuInputHandler sunkbd_handler = { + .name = "sun keyboard", + .mask = INPUT_EVENT_MASK_KEY, + .event = sunkbd_handle_event, +}; + static void handle_kbd_command(ChannelState *s, int val) { trace_escc_kbd_command(val); @@ -898,7 +1008,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]); + s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]), + &sunkbd_handler); } return 0; diff --git a/trace-events b/trace-events index 2c5b30763e..e12e3e59c0 100644 --- a/trace-events +++ b/trace-events @@ -862,8 +862,8 @@ escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d" escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x" escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d" escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d" -escc_sunkbd_event_in(int ch) "Untranslated keycode %2.2x" -escc_sunkbd_event_out(int ch) "Translated keycode %2.2x" +escc_sunkbd_event_in(int ch, const char *name, int down) "QKeyCode 0x%2.2x [%s], down %d" +escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x" escc_kbd_command(int val) "Command %d" escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" From 2ada510698acb68399f4b356386c2807cbac3b60 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Mar 2014 08:56:15 +0100 Subject: [PATCH 08/10] input: remove sparc keymap hack With sparc keyboard going directly from QKeyValue to sparc keycodes this should not be needed any more. Signed-off-by: Gerd Hoffmann --- ui/input-keymap.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/ui/input-keymap.c b/ui/input-keymap.c index 67a3ea72eb..6da4495103 100644 --- a/ui/input-keymap.c +++ b/ui/input-keymap.c @@ -126,25 +126,6 @@ static const int qcode_to_number[] = { [Q_KEY_CODE_INSERT] = 0xd2, [Q_KEY_CODE_DELETE] = 0xd3, -#ifdef NEED_CPU_H -#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64) - [Q_KEY_CODE_STOP] = 0xf0, - [Q_KEY_CODE_AGAIN] = 0xf1, - [Q_KEY_CODE_PROPS] = 0xf2, - [Q_KEY_CODE_UNDO] = 0xf3, - [Q_KEY_CODE_FRONT] = 0xf4, - [Q_KEY_CODE_COPY] = 0xf5, - [Q_KEY_CODE_OPEN] = 0xf6, - [Q_KEY_CODE_PASTE] = 0xf7, - [Q_KEY_CODE_FIND] = 0xf8, - [Q_KEY_CODE_CUT] = 0xf9, - [Q_KEY_CODE_LF] = 0xfa, - [Q_KEY_CODE_HELP] = 0xfb, - [Q_KEY_CODE_META_L] = 0xfc, - [Q_KEY_CODE_META_R] = 0xfd, - [Q_KEY_CODE_COMPOSE] = 0xfe, -#endif -#endif [Q_KEY_CODE_MAX] = 0, }; From 97256073b1a51ed0deb0bac7d4b5d88a90cc2939 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 29 Apr 2014 13:19:32 +0200 Subject: [PATCH 09/10] input: sparc32 kbd: fix some key mappings Reported-by: Olivier Danet Signed-off-by: Gerd Hoffmann --- hw/char/escc.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/char/escc.c b/hw/char/escc.c index 823fe8dc68..d7dff70b06 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -790,7 +790,7 @@ static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = { [Q_KEY_CODE_F10] = 7, [Q_KEY_CODE_NUM_LOCK] = 98, [Q_KEY_CODE_SCROLL_LOCK] = 23, - [Q_KEY_CODE_KP_DIVIDE] = 109, + [Q_KEY_CODE_KP_DIVIDE] = 46, [Q_KEY_CODE_KP_MULTIPLY] = 47, [Q_KEY_CODE_KP_SUBTRACT] = 71, [Q_KEY_CODE_KP_ADD] = 125, @@ -809,31 +809,33 @@ static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = { [Q_KEY_CODE_LESS] = 124, [Q_KEY_CODE_F11] = 9, [Q_KEY_CODE_F12] = 11, - [Q_KEY_CODE_HOME] = 68, - [Q_KEY_CODE_PGUP] = 70, - [Q_KEY_CODE_PGDN] = 114, - [Q_KEY_CODE_END] = 112, - [Q_KEY_CODE_LEFT] = 91, - [Q_KEY_CODE_UP] = 69, - [Q_KEY_CODE_DOWN] = 113, - [Q_KEY_CODE_RIGHT] = 93, - [Q_KEY_CODE_INSERT] = 94, - [Q_KEY_CODE_DELETE] = 50, + [Q_KEY_CODE_HOME] = 52, + [Q_KEY_CODE_PGUP] = 96, + [Q_KEY_CODE_PGDN] = 123, + [Q_KEY_CODE_END] = 74, + [Q_KEY_CODE_LEFT] = 24, + [Q_KEY_CODE_UP] = 20, + [Q_KEY_CODE_DOWN] = 27, + [Q_KEY_CODE_RIGHT] = 28, + [Q_KEY_CODE_INSERT] = 44, + [Q_KEY_CODE_DELETE] = 66, [Q_KEY_CODE_STOP] = 1, [Q_KEY_CODE_AGAIN] = 3, [Q_KEY_CODE_PROPS] = 25, [Q_KEY_CODE_UNDO] = 26, [Q_KEY_CODE_FRONT] = 49, - [Q_KEY_CODE_COPY] = 52, + [Q_KEY_CODE_COPY] = 51, [Q_KEY_CODE_OPEN] = 72, [Q_KEY_CODE_PASTE] = 73, - [Q_KEY_CODE_FIND] = 97, - [Q_KEY_CODE_CUT] = 99, + [Q_KEY_CODE_FIND] = 95, + [Q_KEY_CODE_CUT] = 97, [Q_KEY_CODE_LF] = 111, [Q_KEY_CODE_HELP] = 118, [Q_KEY_CODE_META_L] = 120, [Q_KEY_CODE_META_R] = 122, [Q_KEY_CODE_COMPOSE] = 67, + [Q_KEY_CODE_PRINT] = 22, + [Q_KEY_CODE_SYSRQ] = 21, }; static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src, From 59e7a130054b55fe15cdfdebf284332b04d990ef Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 6 May 2014 14:11:16 +0200 Subject: [PATCH 10/10] input: sparc32 kbd: claim en-us layout Reported-by: Olivier Danet Signed-off-by: Gerd Hoffmann --- hw/char/escc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/char/escc.c b/hw/char/escc.c index d7dff70b06..d9a20aa931 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -912,7 +912,7 @@ static void handle_kbd_command(ChannelState *s, int val) case 0xf: clear_queue(s); put_queue(s, 0xfe); - put_queue(s, 0); // XXX, layout? + put_queue(s, 0x21); /* en-us layout */ break; default: break;