aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-10-24 16:55:56 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-10-24 16:55:56 +0100
commit328f6f79e9916deb6e5649499f7439b0262f6f9e (patch)
tree930ed413bf74b126079c64a400bce9d43938962e /hw
parent3d7196d43bfe12efe98568cb60057e273652b99b (diff)
parent2182608f1ca00f4559486e9173a8e4242dd2d65d (diff)
downloadqemu-328f6f79e9916deb6e5649499f7439b0262f6f9e.zip
qemu-328f6f79e9916deb6e5649499f7439b0262f6f9e.tar.gz
qemu-328f6f79e9916deb6e5649499f7439b0262f6f9e.tar.bz2
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: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/input/ps2.c207
-rw-r--r--hw/input/trace-events3
2 files changed, 173 insertions, 37 deletions
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index dff3f1e..f388a23 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -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,32 +625,85 @@ 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 (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, 0x9d);
- ps2_put_keycode(s, 0xc5);
+ 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, 0xe1);
+ ps2_put_keycode(s, 0x9d);
+ ps2_put_keycode(s, 0xc5);
+ }
}
} else if (qcode == Q_KEY_CODE_PRINT) {
- if (key->down) {
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0x2a);
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0x37);
+ 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 {
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0xb7);
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0xaa);
+ if (key->down) {
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0x2a);
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0x37);
+ } else {
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0xb7);
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0xaa);
+ }
}
} else {
keycode = qcode_to_keycode_set1[qcode];
@@ -640,29 +722,81 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
}
} else if (s->scancode_set == 2) {
if (qcode == Q_KEY_CODE_PAUSE) {
- if (key->down) {
- ps2_put_keycode(s, 0xe1);
- ps2_put_keycode(s, 0x14);
- ps2_put_keycode(s, 0x77);
- ps2_put_keycode(s, 0xe1);
- ps2_put_keycode(s, 0xf0);
- ps2_put_keycode(s, 0x14);
- ps2_put_keycode(s, 0xf0);
- ps2_put_keycode(s, 0x77);
+ 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);
+ ps2_put_keycode(s, 0x77);
+ ps2_put_keycode(s, 0xe1);
+ ps2_put_keycode(s, 0xf0);
+ ps2_put_keycode(s, 0x14);
+ ps2_put_keycode(s, 0xf0);
+ ps2_put_keycode(s, 0x77);
+ }
}
} else if (qcode == Q_KEY_CODE_PRINT) {
- if (key->down) {
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0x12);
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0x7c);
+ 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 {
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0xf0);
- ps2_put_keycode(s, 0x7c);
- ps2_put_keycode(s, 0xe0);
- ps2_put_keycode(s, 0xf0);
- ps2_put_keycode(s, 0x12);
+ if (key->down) {
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0x12);
+ 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);
+ ps2_put_keycode(s, 0xe0);
+ ps2_put_keycode(s, 0xf0);
+ ps2_put_keycode(s, 0x12);
+ }
}
} else {
keycode = qcode_to_keycode_set2[qcode];
@@ -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)
diff --git a/hw/input/trace-events b/hw/input/trace-events
index 6fcb3c0..88150ef 100644
--- a/hw/input/trace-events
+++ b/hw/input/trace-events
@@ -1,7 +1,8 @@
# 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"