input: fixes for ui input code and ps/2 keyboard (mostly sysrq key)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJZ7bQaAAoJEEy22O7T6HE4pAIP/RiPkPy3tcYh/+Z34EWn7bS9 EWNnubKD4NooyCkcZ0nvT+RvHqz7n8M9IH2CguRMlGN4jDO/HxfXOTlEvOfy4IQv hYDfnzNWAVWNUlumEIqewhPaj6oeSNRUGSKadR/6GZh72sOggIsgbC/yXzoOHLLU Akqd7Y+cDl7nD7mIqSNZZdy3UzyPItTHDRRN48Bove8JPmrolZGs/0pEzuVfAblv fcav9ydCuk0iRquMsnV1p5njiYq4dXH62SbQKfelXJ7PTsNbHQN9Dmys616NzqG+ fqPVg0zSuSDEYNxs5YxeBB+P/SNfzxoiBIyQ8d4zIEhoZGDcDze/JniVtpbtocrt +z89FU1oryee5eWZRuFQBrUpei+1rXAbhQKU4NfkpNN78Sx/vxckBKEtFRFR1khT N7dIgc8rdObcVudLAV+/gYRpeN2v149AsRCGXshBTRsLmXT/3hQfFCPm6Jhmrqus XbS0T2FMELUIIdg51R1hNjRObvJwCyZGq9ZNoYlm6q20H6y188flnIVCuWq1DCLG 5DheppbZHB2UsgHA6SjaonsyPy+0St8RGJMc1c0OU33TzhYGHCxdl9NAZHUbQWCl rcVI1S1uMapUZ71v99zCpPWqbsect5MZzadjxAW1U4xL7BZouUWVpIYRZUsS4OM3 EiuzwnizRaJIuQpAT4Rn =2X2B -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
328f6f79e9
207
hw/input/ps2.c
207
hw/input/ps2.c
|
@ -78,6 +78,14 @@
|
||||||
|
|
||||||
#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
|
#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 {
|
typedef struct {
|
||||||
/* Keep the data array 256 bytes long, which compatibility
|
/* Keep the data array 256 bytes long, which compatibility
|
||||||
with older qemu versions. */
|
with older qemu versions. */
|
||||||
|
@ -99,6 +107,7 @@ typedef struct {
|
||||||
int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
|
int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
|
||||||
int ledstate;
|
int ledstate;
|
||||||
bool need_high_bit;
|
bool need_high_bit;
|
||||||
|
unsigned int modifiers; /* bitmask of MOD_* constants above */
|
||||||
} PS2KbdState;
|
} PS2KbdState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -545,6 +554,26 @@ static uint8_t translate_table[256] = {
|
||||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
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)
|
static void ps2_reset_queue(PS2State *s)
|
||||||
{
|
{
|
||||||
PS2Queue *q = &s->queue;
|
PS2Queue *q = &s->queue;
|
||||||
|
@ -596,32 +625,85 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||||
InputKeyEvent *key = evt->u.key.data;
|
InputKeyEvent *key = evt->u.key.data;
|
||||||
int qcode;
|
int qcode;
|
||||||
uint16_t keycode;
|
uint16_t keycode;
|
||||||
|
int mod;
|
||||||
|
|
||||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
||||||
assert(evt->type == INPUT_EVENT_KIND_KEY);
|
assert(evt->type == INPUT_EVENT_KIND_KEY);
|
||||||
qcode = qemu_input_key_value_to_qcode(key->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 (s->scancode_set == 1) {
|
||||||
if (qcode == Q_KEY_CODE_PAUSE) {
|
if (qcode == Q_KEY_CODE_PAUSE) {
|
||||||
if (key->down) {
|
if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
|
||||||
ps2_put_keycode(s, 0xe1);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0x1d);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0x45);
|
ps2_put_keycode(s, 0x46);
|
||||||
ps2_put_keycode(s, 0x91);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0x9d);
|
ps2_put_keycode(s, 0xc6);
|
||||||
ps2_put_keycode(s, 0xc5);
|
}
|
||||||
|
} 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) {
|
} else if (qcode == Q_KEY_CODE_PRINT) {
|
||||||
if (key->down) {
|
if (s->modifiers & MOD_ALT_L) {
|
||||||
ps2_put_keycode(s, 0xe0);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0x2a);
|
ps2_put_keycode(s, 0xb8);
|
||||||
ps2_put_keycode(s, 0xe0);
|
ps2_put_keycode(s, 0x38);
|
||||||
ps2_put_keycode(s, 0x37);
|
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 {
|
} else {
|
||||||
ps2_put_keycode(s, 0xe0);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0xb7);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0xe0);
|
ps2_put_keycode(s, 0x2a);
|
||||||
ps2_put_keycode(s, 0xaa);
|
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 {
|
} else {
|
||||||
keycode = qcode_to_keycode_set1[qcode];
|
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) {
|
} else if (s->scancode_set == 2) {
|
||||||
if (qcode == Q_KEY_CODE_PAUSE) {
|
if (qcode == Q_KEY_CODE_PAUSE) {
|
||||||
if (key->down) {
|
if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
|
||||||
ps2_put_keycode(s, 0xe1);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0x14);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0x77);
|
ps2_put_keycode(s, 0x7e);
|
||||||
ps2_put_keycode(s, 0xe1);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0xf0);
|
ps2_put_keycode(s, 0xf0);
|
||||||
ps2_put_keycode(s, 0x14);
|
ps2_put_keycode(s, 0x7e);
|
||||||
ps2_put_keycode(s, 0xf0);
|
}
|
||||||
ps2_put_keycode(s, 0x77);
|
} 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) {
|
} else if (qcode == Q_KEY_CODE_PRINT) {
|
||||||
if (key->down) {
|
if (s->modifiers & MOD_ALT_L) {
|
||||||
ps2_put_keycode(s, 0xe0);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0x12);
|
ps2_put_keycode(s, 0xf0);
|
||||||
ps2_put_keycode(s, 0xe0);
|
ps2_put_keycode(s, 0x11);
|
||||||
ps2_put_keycode(s, 0x7c);
|
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 {
|
} else {
|
||||||
ps2_put_keycode(s, 0xe0);
|
if (key->down) {
|
||||||
ps2_put_keycode(s, 0xf0);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0x7c);
|
ps2_put_keycode(s, 0x12);
|
||||||
ps2_put_keycode(s, 0xe0);
|
ps2_put_keycode(s, 0xe0);
|
||||||
ps2_put_keycode(s, 0xf0);
|
ps2_put_keycode(s, 0x7c);
|
||||||
ps2_put_keycode(s, 0x12);
|
} 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 {
|
} else {
|
||||||
keycode = qcode_to_keycode_set2[qcode];
|
keycode = qcode_to_keycode_set2[qcode];
|
||||||
|
@ -1125,6 +1259,7 @@ static void ps2_kbd_reset(void *opaque)
|
||||||
s->scan_enabled = 0;
|
s->scan_enabled = 0;
|
||||||
s->translate = 0;
|
s->translate = 0;
|
||||||
s->scancode_set = 2;
|
s->scancode_set = 2;
|
||||||
|
s->modifiers = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps2_mouse_reset(void *opaque)
|
static void ps2_mouse_reset(void *opaque)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# See docs/devel/tracing.txt for syntax documentation.
|
# See docs/devel/tracing.txt for syntax documentation.
|
||||||
|
|
||||||
# hw/input/ps2.c
|
# 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_read_data(void *opaque) "%p"
|
||||||
ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d"
|
ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d"
|
||||||
ps2_reset_keyboard(void *s) "%p"
|
ps2_reset_keyboard(void *s) "%p"
|
||||||
|
|
|
@ -748,6 +748,13 @@
|
||||||
# @ac_bookmarks: since 2.10
|
# @ac_bookmarks: since 2.10
|
||||||
# altgr, altgr_r: dropped in 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
|
# Since: 1.3.0
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
|
|
|
@ -76,6 +76,11 @@ static KeyValue *copy_key_value(KeyValue *src)
|
||||||
{
|
{
|
||||||
KeyValue *dst = g_new(KeyValue, 1);
|
KeyValue *dst = g_new(KeyValue, 1);
|
||||||
memcpy(dst, src, sizeof(*src));
|
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;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
ui/input.c
16
ui/input.c
|
@ -162,7 +162,7 @@ void qmp_input_send_event(bool has_device, const char *device,
|
||||||
if (evt->type == INPUT_EVENT_KIND_KEY &&
|
if (evt->type == INPUT_EVENT_KIND_KEY &&
|
||||||
evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
|
evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
|
||||||
KeyValue *key = evt->u.key.data->key;
|
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);
|
qemu_input_event_send_key_qcode(con, code, evt->u.key.data->down);
|
||||||
} else {
|
} else {
|
||||||
qemu_input_event_send(con, evt);
|
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 &&
|
assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
|
||||||
evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));
|
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)) {
|
if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 56ce5650d2c6ea216b4580df44b9a6dd3bc92c3b
|
Subproject commit 10739aa26051a5d49d88132604539d3ed085e72e
|
Loading…
Reference in a new issue