Various fixes for input/ps2 handling
cover Various fixes for input/ps2 handling
While preparing to send the rest of my keycodemapdb patches I identified some problems in the input code and particularly in the ps2 device handling of the pause & print / sysrq key that needed fixing.
Daniel P. Berrange (9):
input: use hex in ps2 keycode trace events
ui: fix crash with sendkey and raw key numbers
ui: use correct union field for key number
ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
ps2: fix scancodes sent for Shift/Ctrl+Print key combination
ps2: fix scancodess sent for Pause key in AT set 1
ps2: fix scancodes sent for Ctrl+Pause key combination
ui: normalize the 'sysrq' key into the 'print' key
ui: pull in latest keycodemapdb
hw/input/ps2.c | 207 +++++++++++++++++++++++++++++++++++++++++--------- hw/input/trace-events | 3 +- qapi/ui.json | 7 ++ ui/input-legacy.c | 5 ++ ui/input.c | 16 +++- ui/keycodemapdb | 2 +- 6 files changed, 201 insertions(+), 39 deletions(-)
Signature · 1 line
2.13.6
PATCH 1/9 input: use hex in ps2 keycode trace events
Hardware scancodes are all documented in hex, so use that in trace events to make it easier to understand.
--- hw/input/trace-events | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/input/trace-events +1 -1
@@ -1,7 +1,7 @@ # 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_read_data(void *opaque) "%p" ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d" ps2_reset_keyboard(void *s) "%p"
Signature · 1 line
2.13.6
Re: [Qemu-devel] [PATCH v1 1/9] input: use hex in ps2 keycode trace events
Quoted 7 lines · Daniel P. Berrange
Hardware scancodes are all documented in hex, so use that in trace events to make it easier to understand.
Signed-off-by Daniel P. Berrange <[email protected]>--- hw/input/trace-events | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 15 lines
hw/input/trace-events +1
-1@@ -1,7 +1,7 @@ # 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_read_data(void *opaque) "%p" ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d" ps2_reset_keyboard(void *s) "%p"
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
PATCH 2/9 ui: fix crash with sendkey and raw key numbers
In reply to Daniel P. BerrangePreviously we enforced that all key events are using QKeyCodes at time they are sent:
commit af07e5ff02ae6d4258fc5331007811d0b1c4d35a
Author: Daniel P. Berrange <[email protected]>
Date: Fri Sep 29 11:12:00 2017 +0100
ui: convert key events to QKeyCodes immediately
This commit forget to fix the code for the legacy 'sendkey' command which still accepts key numbers from the user, which then need converting to QKeyCodes
--- ui/input-legacy.c | 5 +++++ 1 file changed, 5 insertions(+)
ui/input-legacy.c +5 -0
@@ -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; }
Signature · 1 line
2.13.6
Re: [Qemu-devel] [PATCH v1 2/9] ui: fix crash with sendkey and raw key numbers
Quoted 9 lines · Daniel P. Berrange
Previously we enforced that all key events are using QKeyCodes at time they are sent:
commit
af07e5ff02ae6d4258fc5331007811d0b1c4d35a
Author: Daniel P. Berrange <[email protected]>
Date: Fri Sep 29 11:12:00 2017 +0100ui: convert key events to QKeyCodes immediately
Quoted 8 lines
This commit forget to fix the code for the legacy 'sendkey' command which still accepts key numbers from the user, which then need converting to QKeyCodes
Signed-off-by Daniel P. Berrange <[email protected]>--- ui/input-legacy.c | 5 +++++ 1 file changed, 5 insertions(+)
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
PATCH 3/9 ui: use correct union field for key number
In reply to Daniel P. BerrangeThe code converting key numbers to QKeyCode in the 'input-send-event' command mistakenly accessed the key->u.qcode union field instead of the key->u.number field. This is harmless because the fields use the same size datatype in both cases, but none the less it should be fixed to avoid confusion.
--- ui/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ui/input.c +1 -1
@@ -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);
Signature · 1 line
2.13.6
Re: [Qemu-devel] [PATCH v1 3/9] ui: use correct union field for key number
Quoted 10 lines · Daniel P. Berrange
The code converting key numbers to QKeyCode in the 'input-send-event' command mistakenly accessed the
key->u.qcodeunion field instead of thekey->u.numberfield. This is harmless because the fields use the same size datatype in both cases, but none the less it should be fixed to avoid confusion.Signed-off-by Daniel P. Berrange <[email protected]>--- ui/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 15 lines
ui/input.c +1
-1@@ -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);
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
PATCH 4/9 ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
In reply to Daniel P. BerrangeThe 'Print' key is special in the AT set 1 / set 2 scancode definitions.
An unmodified 'Print' key is supposed to send
AT Set 1: e0 2a e0 37 (Down) e0 b7 e0 aa (Up) AT Set 2: e0 12 e0 7c (Down) e0 f0 7c e0 f0 12 (Up)
which QEMU gets right. When pressed in combination with the 'Alt_L' or 'Alt_R' keys (which signify SysRq), the scancodes are required to follow a different scheme. With Alt_L, the expected sequences are
AT set 1: 38, 54 (Down) d4, b8 (Up)
AT set 2: 11, 84 (Down) f0 84, f0 11 (Up)
And with Alt_R
AT set 1: e0 38, 54 (Down) d4, e0 b8 (Up)
AT set 2: e0 11, 84 (Down) f0 84, f0 e0 11 (Up)
It is actually slightly more complicated than that, because (according results of 'showkey -s', keyboards will in fact first release the currently pressed modifier before sending the sequence above (which effectively re-presses & then releases the modifier) and finally re-press the original modifier afterwards. IOW, with Alt_L we need to send
AT set 1: b8, 38, 54 (Down) d4, b8, 38 (Up) AT set 2: f0 11, 11, 84 (Down) f0 84, f0 11, 11 (Up)
And with Alt_R
AT set 1: e0 b8, e0 38, 54 (Down) d4, e0 b8, e0 38 (Up) AT set 2: e0 f0 11, e0 11, 84 (Down) f0 84, e0 f0 11, e0 11 (Up)
The AT set 3 scancodes have no special handling for Alt-Print.
Rather than fixing the handling of the 'print' key in the ps2 driver to consider the Alt modifiers, way back, a patch was commited that defined an extra 'sysrq' key name:
commit f2289cb6924afc97b2a75d21bfc9217024d11741
Author: balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Wed Jun 4 10:14:16 2008 +0000
Add sysrq to key names known by "sendkey".
Adding sysrq keycode to the table enabling running sysrq debugging in the guest via the monitor sendkey command, like:
(qemu) sendkey alt-sysrq-t
Tested on x86-64 target and Linux guest.
With this patch QEMU would send
AT set 1: 38, 54 (Down) d4, b8 (Up)
AT set 2: 11, 84 (Down) f0 84, f0 11 (Up)
but this doesn't match what actual real keyboards send, as it is not releasing the original modifier & pressing it again afterwards. In addition the original problem remains, and a new problem was added:
- The sequence 'alt-print-t' is still broken, acting as if 'print-t' was requested
- The sequence 'sysrq-t' is broken, injecting an undefine scancode sequence
tot he guest os (bare 0x54)
To deal with this mess we make these changes to the ps2 code, so that we track the state of modifier keys (Alt, Shift, Ctrl - both left & right). Then we can vary what scancodes are sent for Q_KEY_CODE_PRINT according to the Alt key modifier state
Interestingly, it appears that of operating systems I've checked (Linux, FreeBSD and OpenSolaris), none of them actually bother to validate the full sequences for a unmodified 'Print' key. They all just ignore the leading "e0 2a" and trigger based off "e0 37" alone. The latter two byte sequence is what keyboards send with 'Print' is combined with 'Shift' or 'Ctrl' modifiers.
--- hw/input/ps2.c | 137 ++++++++++++++++++++++++++++++++++++++++++-------- hw/input/trace-events | 1 + 2 files changed, 118 insertions(+), 20 deletions(-)
hw/input/ps2.c +117 -20
@@ -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,11 +625,20 @@ 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) {
@@ -612,16 +650,42 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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 { -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];
@@ -651,18 +715,50 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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 { -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 +1221,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)
hw/input/trace-events +1 -0
@@ -2,6 +2,7 @@ # hw/input/ps2.c 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"
Signature · 1 line
2.13.6
Re: [Qemu-devel] [PATCH v1 4/9] ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
Quoted 105 lines · Daniel P. Berrange
The 'Print' key is special in the AT set 1 / set 2 scancode definitions.
An unmodified 'Print' key is supposed to send
AT Set 1: e0 2a e0 37 (Down) e0 b7 e0 aa (Up) AT Set 2: e0 12 e0 7c (Down) e0 f0 7c e0 f0 12 (Up)which QEMU gets right. When pressed in combination with the '
Alt_L' or 'Alt_R' keys (which signify SysRq), the scancodes are required to follow a different scheme. WithAlt_L, the expected sequences areAT set 1: 38, 54 (Down) d4, b8 (Up)
AT set 2: 11, 84 (Down) f0 84, f0 11 (Up)And with
Alt_RAT set 1: e0 38, 54 (Down) d4, e0 b8 (Up)
AT set 2: e0 11, 84 (Down) f0 84, f0 e0 11 (Up)It is actually slightly more complicated than that, because (according results of 'showkey -s', keyboards will in fact first release the currently pressed modifier before sending the sequence above (which effectively re-presses & then releases the modifier) and finally re-press the original modifier afterwards. IOW, with
Alt_Lwe need to sendAT set 1: b8, 38, 54 (Down) d4, b8, 38 (Up) AT set 2: f0 11, 11, 84 (Down) f0 84, f0 11, 11 (Up)
And with
Alt_RAT set 1: e0 b8, e0 38, 54 (Down) d4, e0 b8, e0 38 (Up) AT set 2: e0 f0 11, e0 11, 84 (Down) f0 84, e0 f0 11, e0 11 (Up)
The AT set 3 scancodes have no special handling for Alt-Print.
Rather than fixing the handling of the 'print' key in the ps2 driver to consider the Alt modifiers, way back, a patch was commited that defined an extra 'sysrq' key name:
commit
f2289cb6924afc97b2a75d21bfc9217024d11741
Author: balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Wed Jun 4 10:14:16 2008 +0000Add sysrq to key names known by "sendkey".
Adding sysrq keycode to the table enabling running sysrq debugging in the guest via the monitor sendkey command, like:
(qemu) sendkey alt-sysrq-t
Tested on x86-64 target and Linux guest.
Signed-off-by Ryan Harper <[email protected]>With this patch QEMU would send
AT set 1: 38, 54 (Down) d4, b8 (Up)
AT set 2: 11, 84 (Down) f0 84, f0 11 (Up)but this doesn't match what actual real keyboards send, as it is not releasing the original modifier & pressing it again afterwards. In addition the original problem remains, and a new problem was added:
- The sequence 'alt-print-t' is still broken, acting as if 'print-t' was requested
- The sequence 'sysrq-t' is broken, injecting an undefine scancode sequencetot he guest os (bare 0x54)To deal with this mess we make these changes to the ps2 code, so that we track the state of modifier keys (Alt, Shift, Ctrl - both left & right). Then we can vary what scancodes are sent for
Q_KEY_CODE_PRINTaccording to the Alt key modifier stateInterestingly, it appears that of operating systems I've checked (Linux, FreeBSD and OpenSolaris), none of them actually bother to validate the full sequences for a unmodified 'Print' key. They all just ignore the leading "e0 2a" and trigger based off "e0 37" alone. The latter two byte sequence is what keyboards send with 'Print' is combined with 'Shift' or 'Ctrl' modifiers.
Signed-off-by Daniel P. Berrange <[email protected]>--- hw/input/ps2.c | 137 ++++++++++++++++++++++++++++++++++++++++++-------- hw/input/trace-events | 1 + 2 files changed, 118 insertions(+), 20 deletions(-)hw/input/ps2.c +8
-0@@ -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. */
hw/input/ps2.c typedef struct { · line 111
Quoted 5 lines
hw/input/ps2.c +1
-0@@ -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;
Presumably the addition of this field means I should do something with the vmstate for migration. I'm unclear exactly how to modify that data in the right way that correctly preserves back compatibility ?
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
PATCH 5/9 ps2: fix scancodes sent for Shift/Ctrl+Print key combination
In reply to Daniel P. BerrangeThe 'Print' key is special in the AT set 1 / set 2 scancode definitions.
An unmodified 'Print' key is supposed to send
AT Set 1: e0 2a e0 37 (Down) e0 b7 e0 aa (Up) AT Set 2: e0 12 e0 7c (Down) e0 f0 7c e0 f0 12 (Up)
which QEMU gets right. When combined with Shift/Ctrl (both left and right variants), the leading two bytes should be dropped, resulting in
AT Set 1: e0 37 (Down) e0 b7 (Up) AT Set 2: e0 7c (Down) e0 f0 7c (Up)
This difference is pretty benign, since of all the operating systems I have checked (Linux, FreeBSD and OpenStack), none bother to check the leading two bytes anyway. This change none the less makes the ps2 device better follow real hardware behaviour.
--- hw/input/ps2.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
hw/input/ps2.c +19 -0
@@ -674,6 +674,15 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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 );
@@ -745,6 +754,16 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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 );
Signature · 1 line
2.13.6
PATCH 6/9 ps2: fix scancodess sent for Pause key in AT set 1
In reply to Daniel P. BerrangeThe ps2 device was previously fixed to send the special Pause/Print scancode sequences in:
commit 8c10e0baf0260b59a4e984744462a18016662e3e
Author: Hervé Poussineau <[email protected]>
Date: Thu Sep 15 22:06:26 2016 +0200
ps2: use QEMU qcodes instead of scancodes
The sequence used for Pause had a small typo in the AT set 1, with a 0xe1 accidentally changed to 0x91. This is not immediately visible with Linux guests since they run the ps2 device with AT set 2 scancodes.
--- hw/input/ps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/input/ps2.c +1 -1
@@ -645,7 +645,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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 ); }
Signature · 1 line
2.13.6
PATCH 7/9 ps2: fix scancodes sent for Ctrl+Pause key combination
In reply to Daniel P. BerrangeThe 'Pause' key is special in the AT set 1 / set 2 scancode definitions.
An unmodified 'Pause' key is supposed to send
AT Set 1: e1 1d 45 91 9d c5 (Down) <nothing> (Up) AT Set 2: e1 14 77 e1 f0 14 f0 77 (Down) <nothing> (Up)
which QEMU gets right. When combined with Ctrl (both left and right variants), a different sequence is expected
AT Set 1: e0 46 e0 c6 (Down) <nothing> (Up)
AT Set 2: e0 7e e0 f0 73 (Down) <nothing> (Up)
--- hw/input/ps2.c | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-)
hw/input/ps2.c +35 -16
@@ -641,13 +641,22 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,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,0xe1 ); -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 (s->modifiers &MOD_ALT_L ) {
@@ -713,15 +722,25 @@ 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 (s->modifiers &MOD_ALT_L ) {
Signature · 1 line
2.13.6
PATCH 8/9 ui: normalize the 'sysrq' key into the 'print' key
In reply to Daniel P. BerrangeThe 'sysrq' key was mistakenly added to QEMU to deal with incorrect handling of the 'print' key in the ps2 device:
commit f2289cb6924afc97b2a75d21bfc9217024d11741
Author: balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Wed Jun 4 10:14:16 2008 +0000
Add sysrq to key names known by "sendkey".
Adding sysrq keycode to the table enabling running sysrq debugging in the guest via the monitor sendkey command, like:
(qemu) sendkey alt-sysrq-t
Tested on x86-64 target and Linux guest.
The ps2 device is now fixed wrt modifiers and the 'print' key. Further the handling of the 'sysrq' key has some problems of its own, documented in the previous commit. To cleanup this mess, we convert any use of 'sysrq' into 'print' prior to dispatching the event to device models.
--- qapi/ui.json | 7 +++++++ ui/input.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+)
qapi/ui.json +7 -0
@@ -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 # ##
ui/input.c +14 -0
@@ -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 ; }
Signature · 1 line
2.13.6
PATCH 9/9 ui: pull in latest keycodemapdb
In reply to Daniel P. BerrangeLatest keycodemapdb has a fix for Sun keyboard Pause mapping and backcompat fix for QEMU's treatment of 0xb7 as an alternative to 0x54 for triggering Print/SysRq
--- ui/keycodemapdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ui/keycodemapdb +1 -1
@@ -1 +1 @@ -Subproject commit 56ce5650d2c6ea216b4580df44b9a6dd3bc92c3b +Subproject commit 10739aa26051a5d49d88132604539d3ed085e72e
Signature · 1 line
2.13.6