On 24/04/2014 12:37, Gerd Hoffmann wrote: > 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 <kra...@redhat.com> > --- > hw/char/escc.c | 229 > ++++++++++++++++++++++++++++++++++++++++++--------------- > trace-events | 4 +- > 2 files changed, 172 insertions(+), 61 deletions(-) > > diff --git a/hw/char/escc.c b/hw/char/escc.c > index 6397f6f..f8aebae 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, > }; This mapping does not look good on some details.
COPY, FIND and CUT does not match the standard : [Q_KEY_CODE_COPY] = 52 : Should be 0x33=51 [Q_KEY_CODE_FIND] = 97 : Should be 0x5F=95 [Q_KEY_CODE_CUT] = 99 : Should be 0x61=97 (see : http://www.sparc.org/wp-content/uploads/2014/01/KBD.pdf.gz) QEMU declares a "Type 4" keyboard. maybe we should switch to a "Type 5/6" with separate arrows and keypad which resembles more closely to current 102/103 keys extended keyboards. I will try on actual HW asap. > > -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; > - > - 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; > + ChannelState *s = (ChannelState *)dev; > + int qcode, keycode; > + > + 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 */ > + } > + } > + } > + > + keycode = qcode_to_keycode[qcode]; > + if (evt->key->down) { > + keycode |= 0x80; > } Instead : if (!evt->key->down) { keycode |= 0x80; } keycode +0x80 is for KeyUp events. > - trace_escc_sunkbd_event_out(ch); > - put_queue(s, ch | release); > + 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 9303245..49e326a 100644 > --- a/trace-events > +++ b/trace-events > @@ -838,8 +838,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" > > You can do some tests with "sparc-test-0.2.tar.gz" on qemu.org Regards Olivier