From nobody Tue Feb 10 00:59:04 2026 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1508750843133365.8640825753988; Mon, 23 Oct 2017 02:27:23 -0700 (PDT) Received: from localhost ([::1]:37660 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e6Z0b-0003Cz-66 for importer@patchew.org; Mon, 23 Oct 2017 05:26:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36839) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e6Ytp-0005y4-3n for qemu-devel@nongnu.org; Mon, 23 Oct 2017 05:19:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e6Ytm-0005Yx-Ib for qemu-devel@nongnu.org; Mon, 23 Oct 2017 05:19:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:23514) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e6Ytm-0005Yk-8z for qemu-devel@nongnu.org; Mon, 23 Oct 2017 05:19:54 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 604455D9E7 for ; Mon, 23 Oct 2017 09:19:53 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-117-195.ams2.redhat.com [10.36.117.195]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB2F979838; Mon, 23 Oct 2017 09:19:49 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id D6A024FD7E; Mon, 23 Oct 2017 11:19:47 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 604455D9E7 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=kraxel@redhat.com From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Mon, 23 Oct 2017 11:19:42 +0200 Message-Id: <20171023091947.20771-5-kraxel@redhat.com> In-Reply-To: <20171023091947.20771-1-kraxel@redhat.com> References: <20171023091947.20771-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 23 Oct 2017 09:19:53 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 4/9] ps2: fix scancodes sent for Alt-Print key combination (aka SysRq) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_6 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "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. 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 resu= lts 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 con= sider the Alt modifiers, way back, a patch was commited that defined an extra 'sy= srq' key name: commit f2289cb6924afc97b2a75d21bfc9217024d11741 Author: balrog 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. Signed-off-by: Ryan Harper 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 releas= ing the original modifier & pressing it again afterwards. In addition the origi= nal 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 sequen= ce tot he guest os (bare 0x54) To deal with this mess we make these changes to the ps2 code, so that we tr= ack 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, Fr= eeBSD and OpenSolaris), none of them actually bother to validate the full sequenc= es 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 keybo= ards send with 'Print' is combined with 'Shift' or 'Ctrl' modifiers. Signed-off-by: Daniel P. Berrange Message-id: 20171019142848.572-5-berrange@redhat.com Signed-off-by: Gerd Hoffmann --- hw/input/ps2.c | 137 ++++++++++++++++++++++++++++++++++++++++++----= ---- hw/input/trace-events | 1 + 2 files changed, 118 insertions(+), 20 deletions(-) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index dff3f1e024..1e6f6ae9b6 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -78,6 +78,14 @@ =20 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */ =20 +/* 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=3DXT, 2=3DAT, 3=3DPS/2 */ int ledstate; bool need_high_bit; + unsigned int modifiers; /* bitmask of MOD_* constants above */ } PS2KbdState; =20 typedef struct { @@ -545,6 +554,26 @@ static uint8_t translate_table[256] =3D { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }; =20 +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 =3D &s->queue; @@ -596,11 +625,20 @@ static void ps2_keyboard_event(DeviceState *dev, Qemu= Console *src, InputKeyEvent *key =3D evt->u.key.data; int qcode; uint16_t keycode; + int mod; =20 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); assert(evt->type =3D=3D INPUT_EVENT_KIND_KEY); qcode =3D qemu_input_key_value_to_qcode(key->key); =20 + mod =3D ps2_modifier_bit(qcode); + trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers); + if (key->down) { + s->modifiers |=3D mod; + } else { + s->modifiers &=3D ~mod; + } + if (s->scancode_set =3D=3D 1) { if (qcode =3D=3D Q_KEY_CODE_PAUSE) { if (key->down) { @@ -612,16 +650,42 @@ static void ps2_keyboard_event(DeviceState *dev, Qemu= Console *src, ps2_put_keycode(s, 0xc5); } } else if (qcode =3D=3D 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 =3D qcode_to_keycode_set1[qcode]; @@ -651,18 +715,50 @@ static void ps2_keyboard_event(DeviceState *dev, Qemu= Console *src, ps2_put_keycode(s, 0x77); } } else if (qcode =3D=3D 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 =3D qcode_to_keycode_set2[qcode]; @@ -1125,6 +1221,7 @@ static void ps2_kbd_reset(void *opaque) s->scan_enabled =3D 0; s->translate =3D 0; s->scancode_set =3D 2; + s->modifiers =3D 0; } =20 static void ps2_mouse_reset(void *opaque) diff --git a/hw/input/trace-events b/hw/input/trace-events index d04132d342..88150ef7a6 100644 --- a/hw/input/trace-events +++ b/hw/input/trace-events @@ -2,6 +2,7 @@ =20 # 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 modifie= r, 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" --=20 2.9.3