Commit 328f6f79 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/input-20171023-pull-request' into staging



input: fixes for ui input code and ps/2 keyboard (mostly sysrq key)

# gpg: Signature made Mon 23 Oct 2017 10:19:22 BST
# gpg:                using RSA key 0x4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/input-20171023-pull-request:
  ui: pull in latest keycodemapdb
  ui: normalize the 'sysrq' key into the 'print' key
  ps2: fix scancodes sent for Ctrl+Pause key combination
  ps2: fix scancodess sent for Pause key in AT set 1
  ps2: fix scancodes sent for Shift/Ctrl+Print key combination
  ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
  ui: use correct union field for key number
  ui: fix crash with sendkey and raw key numbers
  input: use hex in ps2 keycode trace events

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 3d7196d4 2182608f
Loading
Loading
Loading
Loading
+171 −36
Original line number Diff line number Diff line
@@ -78,6 +78,14 @@

#define PS2_QUEUE_SIZE 16  /* Buffer size required by PS/2 protocol */

/* Bits for 'modifiers' field in PS2KbdState */
#define MOD_CTRL_L  (1 << 0)
#define MOD_SHIFT_L (1 << 1)
#define MOD_ALT_L   (1 << 2)
#define MOD_CTRL_R  (1 << 3)
#define MOD_SHIFT_R (1 << 4)
#define MOD_ALT_R   (1 << 5)

typedef struct {
    /* Keep the data array 256 bytes long, which compatibility
     with older qemu versions. */
@@ -99,6 +107,7 @@ typedef struct {
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
    int ledstate;
    bool need_high_bit;
    unsigned int modifiers; /* bitmask of MOD_* constants above */
} PS2KbdState;

typedef struct {
@@ -545,6 +554,26 @@ static uint8_t translate_table[256] = {
    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};

static unsigned int ps2_modifier_bit(QKeyCode key)
{
    switch (key) {
    case Q_KEY_CODE_CTRL:
        return MOD_CTRL_L;
    case Q_KEY_CODE_CTRL_R:
        return MOD_CTRL_R;
    case Q_KEY_CODE_SHIFT:
        return MOD_SHIFT_L;
    case Q_KEY_CODE_SHIFT_R:
        return MOD_SHIFT_R;
    case Q_KEY_CODE_ALT:
        return MOD_ALT_L;
    case Q_KEY_CODE_ALT_R:
        return MOD_ALT_R;
    default:
        return 0;
    }
}

static void ps2_reset_queue(PS2State *s)
{
    PS2Queue *q = &s->queue;
@@ -596,22 +625,74 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
    InputKeyEvent *key = evt->u.key.data;
    int qcode;
    uint16_t keycode;
    int mod;

    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
    assert(evt->type == INPUT_EVENT_KIND_KEY);
    qcode = qemu_input_key_value_to_qcode(key->key);

    mod = ps2_modifier_bit(qcode);
    trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers);
    if (key->down) {
        s->modifiers |= mod;
    } else {
        s->modifiers &= ~mod;
    }

    if (s->scancode_set == 1) {
        if (qcode == Q_KEY_CODE_PAUSE) {
            if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x46);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xc6);
                }
            } else {
                if (key->down) {
                    ps2_put_keycode(s, 0xe1);
                    ps2_put_keycode(s, 0x1d);
                    ps2_put_keycode(s, 0x45);
                ps2_put_keycode(s, 0x91);
                    ps2_put_keycode(s, 0xe1);
                    ps2_put_keycode(s, 0x9d);
                    ps2_put_keycode(s, 0xc5);
                }
            }
        } else if (qcode == Q_KEY_CODE_PRINT) {
            if (s->modifiers & MOD_ALT_L) {
                if (key->down) {
                    ps2_put_keycode(s, 0xb8);
                    ps2_put_keycode(s, 0x38);
                    ps2_put_keycode(s, 0x54);
                } else {
                    ps2_put_keycode(s, 0xd4);
                    ps2_put_keycode(s, 0xb8);
                    ps2_put_keycode(s, 0x38);
                }
            } else if (s->modifiers & MOD_ALT_R) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xb8);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x38);
                    ps2_put_keycode(s, 0x54);
                } else {
                    ps2_put_keycode(s, 0xd4);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xb8);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x38);
                }
            } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
                                       MOD_SHIFT_R | MOD_CTRL_R)) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x37);
                } else {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xb7);
                }
            } else {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x2a);
@@ -623,6 +704,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xaa);
                }
            }
        } else {
            keycode = qcode_to_keycode_set1[qcode];
            if (keycode) {
@@ -640,6 +722,15 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
        }
    } else if (s->scancode_set == 2) {
        if (qcode == Q_KEY_CODE_PAUSE) {
            if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x7e);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x7e);
                }
            } else {
                if (key->down) {
                    ps2_put_keycode(s, 0xe1);
                    ps2_put_keycode(s, 0x14);
@@ -650,7 +741,49 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x77);
                }
            }
        } else if (qcode == Q_KEY_CODE_PRINT) {
            if (s->modifiers & MOD_ALT_L) {
                if (key->down) {
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0x84);
                } else {
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x84);
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0x11);
                }
            } else if (s->modifiers & MOD_ALT_R) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0x84);
                } else {
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x84);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x11);
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x11);
                }
            } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
                                       MOD_SHIFT_R | MOD_CTRL_R)) {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x7c);
                } else {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x7c);
                }
            } else {
                if (key->down) {
                    ps2_put_keycode(s, 0xe0);
                    ps2_put_keycode(s, 0x12);
@@ -664,6 +797,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
                    ps2_put_keycode(s, 0xf0);
                    ps2_put_keycode(s, 0x12);
                }
            }
        } else {
            keycode = qcode_to_keycode_set2[qcode];
            if (keycode) {
@@ -1125,6 +1259,7 @@ static void ps2_kbd_reset(void *opaque)
    s->scan_enabled = 0;
    s->translate = 0;
    s->scancode_set = 2;
    s->modifiers = 0;
}

static void ps2_mouse_reset(void *opaque)
+2 −1
Original line number Diff line number Diff line
# See docs/devel/tracing.txt for syntax documentation.

# hw/input/ps2.c
ps2_put_keycode(void *opaque, int keycode) "%p keycode %d"
ps2_put_keycode(void *opaque, int keycode) "%p keycode 0x%02x"
ps2_keyboard_event(void *opaque, int qcode, int down, unsigned int modifier, unsigned int modifiers) "%p qcode %d down %d modifier 0x%x modifiers 0x%x"
ps2_read_data(void *opaque) "%p"
ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d"
ps2_reset_keyboard(void *s) "%p"
+7 −0
Original line number Diff line number Diff line
@@ -748,6 +748,13 @@
# @ac_bookmarks: since 2.10
# altgr, altgr_r: dropped in 2.10
#
# 'sysrq' was mistakenly added to hack around the fact that
# the ps2 driver was not generating correct scancodes sequences
# when 'alt+print' was pressed. This flaw is now fixed and the
# 'sysrq' key serves no further purpose. Any further use of
# 'sysrq' will be transparently changed to 'print', so they
# are effectively synonyms.
#
# Since: 1.3.0
#
##
+5 −0
Original line number Diff line number Diff line
@@ -76,6 +76,11 @@ static KeyValue *copy_key_value(KeyValue *src)
{
    KeyValue *dst = g_new(KeyValue, 1);
    memcpy(dst, src, sizeof(*src));
    if (dst->type == KEY_VALUE_KIND_NUMBER) {
        QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number.data);
        dst->type = KEY_VALUE_KIND_QCODE;
        dst->u.qcode.data = code;
    }
    return dst;
}

+15 −1
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ void qmp_input_send_event(bool has_device, const char *device,
        if (evt->type == INPUT_EVENT_KIND_KEY &&
            evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
            KeyValue *key = evt->u.key.data->key;
            QKeyCode code = qemu_input_key_number_to_qcode(key->u.qcode.data);
            QKeyCode code = qemu_input_key_number_to_qcode(key->u.number.data);
            qemu_input_event_send_key_qcode(con, code, evt->u.key.data->down);
        } else {
            qemu_input_event_send(con, evt);
@@ -353,6 +353,20 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
    assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
             evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));


    /*
     * 'sysrq' was mistakenly added to hack around the fact that
     * the ps2 driver was not generating correct scancodes sequences
     * when 'alt+print' was pressed. This flaw is now fixed and the
     * 'sysrq' key serves no further purpose. We normalize it to
     * 'print', so that downstream receivers of the event don't
     * neeed to deal with this mistake
     */
    if (evt->type == INPUT_EVENT_KIND_KEY &&
        evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {
        evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;
    }

    if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
        return;
    }
Loading