From nobody Sat Dec 24 08:36:52 2022 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NfHTc39tjz1HSbf; Sat, 24 Dec 2022 08:36:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NfHTc2FTRz3NH6; Sat, 24 Dec 2022 08:36:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671871012; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=D9KkB6ssYaQhc8qMCrNU4TQzWlch9FIH/FIex/Oo5ms=; b=FmFwK4TKMRWid08+BcPK01G2ca7+fa7MA5qI0qhL59F1UuZEM1NVskY5TSFgdAd8dPO8Ww lO9RU2DKzbqPRagNvqPt4qKonnO7cOwwgi9Cl60vSTKwsoG0tNzTWxrCQfO2bqN4OVOgb2 AdjtSya6JUGWkr8+lkOIMlvj5dFfulztd0SiwkU6t6PPTbuEIhn98z9jxileOS/ByhNn3k v/jg12JmTaRfP9xyQjGJ1FcmxO/yy+HKBKxmoYpjMXoovQuSk1f692ocqlmFkbts135F/A yXX/+2AO3D9tEEem6OND6ODgvSkUCkZvtTR1BOAYBW/OKzpbsuBoF/KN6TCjXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671871012; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=D9KkB6ssYaQhc8qMCrNU4TQzWlch9FIH/FIex/Oo5ms=; b=FiW0N0fVsj5auzr01OM5g3P767uJ6lRjVs/mXHd9IJNKftNwNkoZ9digqhqYq8Bymp7qBJ 7mF42otVST1ccTWfRiUt93/XZH63VeGfZUzvKVz4J3L5vwRJKcOMA6HRxp+ld4xS93wONF o6YKQRuVQmvdM4YmSMM48UzZekIw0AYThbelJDMyCMnqGoLB4ePHbp82/3EeKmZQLw0VD9 Xf2ndv7lSWEW8DqSFMP6KJAHh04wji8hjn96psvusWf63nWwxwR1rv0OPH8FgrvLuvt2EZ /CcHkm2wOO3Ey66O+erp6R4t+h3qFSdzJ0Wdy0+axyvwe035vK5sdvwjHc5JoA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1671871012; a=rsa-sha256; cv=none; b=sE26Xu9eVgvAWEdaDNI+CAGt+0ckWMpN/4EzsTqM6zZs+S7LhoXXWbvRwMH2fhAxj/yLEJ v1pS5SQpQjGa/dPw06kRR/bw8cgkPO3KzC487w90mTsXEAi4sp9GXQYrcTgS//SOONGam+ 5/N+uJM6Kzy2SekICc4dh0uMMPwJs0VR7rYVOp2GNFG4QSQ/SzNV2ugO8N5nXLKnz3JWGE Gu+UCqYobhn7QiCFX9qHTaZwCwV3CUuMh2yzpwXjs/X4kckiABaHoR3lA9DHvjS36Egaq+ XCvmJTBHk7wkp90wzOdoLe2QpKUWHu/h0AJhLL30P9fRdQ79PQWq1hkFczumQw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NfHTc1Hx8z16Wf; Sat, 24 Dec 2022 08:36:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2BO8aqr7083247; Sat, 24 Dec 2022 08:36:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2BO8aqsT083246; Sat, 24 Dec 2022 08:36:52 GMT (envelope-from git) Date: Sat, 24 Dec 2022 08:36:52 GMT Message-Id: <202212240836.2BO8aqsT083246@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Vladimir Kondratyev Subject: git: 591cb25fc5dd - stable/13 - hv_kbd: Add support for K_XLATE and K_CODE modes for gen 2 VMs List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wulf X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 591cb25fc5ddf78c4b39d5ea0dbd86580acec7ff Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=591cb25fc5ddf78c4b39d5ea0dbd86580acec7ff commit 591cb25fc5ddf78c4b39d5ea0dbd86580acec7ff Author: Vladimir Kondratyev AuthorDate: 2021-04-11 23:08:36 +0000 Commit: Vladimir Kondratyev CommitDate: 2022-12-24 08:10:02 +0000 hv_kbd: Add support for K_XLATE and K_CODE modes for gen 2 VMs That fixes disabled keyboard input after Xorg server has been stopped. (cherry picked from commit e4643aa4c4ffd385a5be635a488cf10fb6d6cf68) --- sys/dev/hyperv/input/hv_kbd.c | 326 ++++++++++++++++++++++++++++++++++------- sys/dev/hyperv/input/hv_kbdc.h | 3 + 2 files changed, 273 insertions(+), 56 deletions(-) diff --git a/sys/dev/hyperv/input/hv_kbd.c b/sys/dev/hyperv/input/hv_kbd.c index b1b0760ba13c..52ce621b2a89 100644 --- a/sys/dev/hyperv/input/hv_kbd.c +++ b/sys/dev/hyperv/input/hv_kbd.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -81,6 +82,7 @@ __FBSDID("$FreeBSD$"); #define HVKBD_UNLOCK() HVKBD_MTX_UNLOCK(&Giant) #define HVKBD_LOCK_ASSERT() HVKBD_MTX_ASSERT(&Giant, MA_OWNED) +#define HVKBD_FLAG_COMPOSE 0x00000001 /* compose char flag */ #define HVKBD_FLAG_POLLING 0x00000002 #ifdef EVDEV_SUPPORT @@ -237,6 +239,8 @@ hvkbd_check_char_locked(keyboard_t *kbd) return (FALSE); hv_kbd_sc *sc = kbd->kb_data; + if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE) && sc->sc_composed_char != 0) + return (TRUE); if (sc->sc_flags & HVKBD_FLAG_POLLING) hvkbd_do_poll(sc, 0); if (hv_kbd_prod_is_ready(sc)) { @@ -262,6 +266,7 @@ static uint32_t hvkbd_read_char_locked(keyboard_t *kbd, int wait) { uint32_t scancode = NOKEY; + uint32_t action; keystroke ks; hv_kbd_sc *sc = kbd->kb_data; #ifdef EVDEV_SUPPORT @@ -271,67 +276,268 @@ hvkbd_read_char_locked(keyboard_t *kbd, int wait) if (!KBD_IS_ACTIVE(kbd) || !hv_kbd_prod_is_ready(sc)) return (NOKEY); - if (sc->sc_mode == K_RAW) { - if (hv_kbd_fetch_top(sc, &ks)) { - return (NOKEY); + +next_code: + + /* do we have a composed char to return? */ + if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE) && sc->sc_composed_char > 0) { + action = sc->sc_composed_char; + sc->sc_composed_char = 0; + if (action > UCHAR_MAX) { + return (ERRKEY); } - if ((ks.info & IS_E0) || (ks.info & IS_E1)) { - /** - * Emulate the generation of E0 or E1 scancode, - * the real scancode will be consumed next time. - */ - if (ks.info & IS_E0) { - scancode = XTKBD_EMUL0; - ks.info &= ~IS_E0; - } else if (ks.info & IS_E1) { - scancode = XTKBD_EMUL1; - ks.info &= ~IS_E1; - } - /** - * Change the top item to avoid encountering - * E0 or E1 twice. - */ - hv_kbd_modify_top(sc, &ks); - } else if (ks.info & IS_UNICODE) { - /** - * XXX: Hyperv host send unicode to VM through - * 'Type clipboard text', the mapping from - * unicode to scancode depends on the keymap. - * It is so complicated that we do not plan to - * support it yet. - */ - if (bootverbose) - device_printf(sc->dev, "Unsupported unicode\n"); - hv_kbd_remove_top(sc); - return (NOKEY); - } else { - scancode = ks.makecode; - if (ks.info & IS_BREAK) { - scancode |= XTKBD_RELEASE; - } - hv_kbd_remove_top(sc); + return (action); + } + + if (hv_kbd_fetch_top(sc, &ks)) { + return (NOKEY); + } + if ((ks.info & IS_E0) || (ks.info & IS_E1)) { + /** + * Emulate the generation of E0 or E1 scancode, + * the real scancode will be consumed next time. + */ + if (ks.info & IS_E0) { + scancode = XTKBD_EMUL0; + ks.info &= ~IS_E0; + } else if (ks.info & IS_E1) { + scancode = XTKBD_EMUL1; + ks.info &= ~IS_E1; } + /** + * Change the top item to avoid encountering + * E0 or E1 twice. + */ + hv_kbd_modify_top(sc, &ks); + } else if (ks.info & IS_UNICODE) { + /** + * XXX: Hyperv host send unicode to VM through + * 'Type clipboard text', the mapping from + * unicode to scancode depends on the keymap. + * It is so complicated that we do not plan to + * support it yet. + */ + if (bootverbose) + device_printf(sc->dev, "Unsupported unicode\n"); + hv_kbd_remove_top(sc); + return (NOKEY); + } else { + scancode = ks.makecode; + if (ks.info & IS_BREAK) { + scancode |= XTKBD_RELEASE; + } + hv_kbd_remove_top(sc); + } #ifdef EVDEV_SUPPORT - /* push evdev event */ - if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && - sc->ks_evdev != NULL) { - keycode = evdev_scancode2key(&sc->ks_evdev_state, - scancode); - - if (keycode != KEY_RESERVED) { - evdev_push_event(sc->ks_evdev, EV_KEY, - (uint16_t)keycode, scancode & 0x80 ? 0 : 1); - evdev_sync(sc->ks_evdev); - } + /* push evdev event */ + if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && + sc->ks_evdev != NULL) { + keycode = evdev_scancode2key(&sc->ks_evdev_state, + scancode); + + if (keycode != KEY_RESERVED) { + evdev_push_event(sc->ks_evdev, EV_KEY, + (uint16_t)keycode, scancode & 0x80 ? 0 : 1); + evdev_sync(sc->ks_evdev); } -#endif - } else { - if (bootverbose) - device_printf(sc->dev, "Unsupported mode: %d\n", sc->sc_mode); } +#endif ++kbd->kb_count; DEBUG_HVKBD(kbd, "read scan: 0x%x\n", scancode); - return scancode; + + /* return the byte as is for the K_RAW mode */ + if (sc->sc_mode == K_RAW) + return scancode; + + /* translate the scan code into a keycode */ + keycode = scancode & 0x7F; + switch (sc->sc_prefix) { + case 0x00: /* normal scancode */ + switch(scancode) { + case 0xB8: /* left alt (compose key) released */ + if (sc->sc_flags & HVKBD_FLAG_COMPOSE) { + sc->sc_flags &= ~HVKBD_FLAG_COMPOSE; + if (sc->sc_composed_char > UCHAR_MAX) + sc->sc_composed_char = 0; + } + break; + case 0x38: /* left alt (compose key) pressed */ + if (!(sc->sc_flags & HVKBD_FLAG_COMPOSE)) { + sc->sc_flags |= HVKBD_FLAG_COMPOSE; + sc->sc_composed_char = 0; + } + break; + case 0xE0: + case 0xE1: + sc->sc_prefix = scancode; + goto next_code; + } + break; + case 0xE0: /* 0xE0 prefix */ + sc->sc_prefix = 0; + switch (keycode) { + case 0x1C: /* right enter key */ + keycode = 0x59; + break; + case 0x1D: /* right ctrl key */ + keycode = 0x5A; + break; + case 0x35: /* keypad divide key */ + keycode = 0x5B; + break; + case 0x37: /* print scrn key */ + keycode = 0x5C; + break; + case 0x38: /* right alt key (alt gr) */ + keycode = 0x5D; + break; + case 0x46: /* ctrl-pause/break on AT 101 (see below) */ + keycode = 0x68; + break; + case 0x47: /* grey home key */ + keycode = 0x5E; + break; + case 0x48: /* grey up arrow key */ + keycode = 0x5F; + break; + case 0x49: /* grey page up key */ + keycode = 0x60; + break; + case 0x4B: /* grey left arrow key */ + keycode = 0x61; + break; + case 0x4D: /* grey right arrow key */ + keycode = 0x62; + break; + case 0x4F: /* grey end key */ + keycode = 0x63; + break; + case 0x50: /* grey down arrow key */ + keycode = 0x64; + break; + case 0x51: /* grey page down key */ + keycode = 0x65; + break; + case 0x52: /* grey insert key */ + keycode = 0x66; + break; + case 0x53: /* grey delete key */ + keycode = 0x67; + break; + /* the following 3 are only used on the MS "Natural" keyboard */ + case 0x5b: /* left Window key */ + keycode = 0x69; + break; + case 0x5c: /* right Window key */ + keycode = 0x6a; + break; + case 0x5d: /* menu key */ + keycode = 0x6b; + break; + case 0x5e: /* power key */ + keycode = 0x6d; + break; + case 0x5f: /* sleep key */ + keycode = 0x6e; + break; + case 0x63: /* wake key */ + keycode = 0x6f; + break; + default: /* ignore everything else */ + goto next_code; + } + break; + case 0xE1: /* 0xE1 prefix */ + /* + * The pause/break key on the 101 keyboard produces: + * E1-1D-45 E1-9D-C5 + * Ctrl-pause/break produces: + * E0-46 E0-C6 (See above.) + */ + sc->sc_prefix = 0; + if (keycode == 0x1D) + sc->sc_prefix = 0x1D; + goto next_code; + /* NOT REACHED */ + case 0x1D: /* pause / break */ + sc->sc_prefix = 0; + if (keycode != 0x45) + goto next_code; + keycode = 0x68; + break; + } + + /* XXX assume 101/102 keys AT keyboard */ + switch (keycode) { + case 0x5c: /* print screen */ + if (sc->sc_flags & ALTS) + keycode = 0x54; /* sysrq */ + break; + case 0x68: /* pause/break */ + if (sc->sc_flags & CTLS) + keycode = 0x6c; /* break */ + break; + } + + /* return the key code in the K_CODE mode */ + if (sc->sc_mode == K_CODE) + return (keycode | (scancode & 0x80)); + + /* compose a character code */ + if (sc->sc_flags & HVKBD_FLAG_COMPOSE) { + switch (keycode | (scancode & 0x80)) { + /* key pressed, process it */ + case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ + sc->sc_composed_char *= 10; + sc->sc_composed_char += keycode - 0x40; + if (sc->sc_composed_char > UCHAR_MAX) + return ERRKEY; + goto next_code; + case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ + sc->sc_composed_char *= 10; + sc->sc_composed_char += keycode - 0x47; + if (sc->sc_composed_char > UCHAR_MAX) + return ERRKEY; + goto next_code; + case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ + sc->sc_composed_char *= 10; + sc->sc_composed_char += keycode - 0x4E; + if (sc->sc_composed_char > UCHAR_MAX) + return ERRKEY; + goto next_code; + case 0x52: /* keypad 0 */ + sc->sc_composed_char *= 10; + if (sc->sc_composed_char > UCHAR_MAX) + return ERRKEY; + goto next_code; + + /* key released, no interest here */ + case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ + case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ + case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ + case 0xD2: /* keypad 0 */ + goto next_code; + + case 0x38: /* left alt key */ + break; + + default: + if (sc->sc_composed_char > 0) { + sc->sc_flags &= ~HVKBD_FLAG_COMPOSE; + sc->sc_composed_char = 0; + return (ERRKEY); + } + break; + } + } + + /* keycode to key action */ + action = genkbd_keyaction(kbd, keycode, scancode & 0x80, + &sc->sc_state, &sc->sc_accents); + if (action == NOKEY) + goto next_code; + else + return (action); } /* Currently wait is always false. */ @@ -353,7 +559,9 @@ hvkbd_clear_state(keyboard_t *kbd) { hv_kbd_sc *sc = kbd->kb_data; sc->sc_state &= LOCK_MASK; /* preserve locking key state */ - sc->sc_flags &= ~HVKBD_FLAG_POLLING; + sc->sc_flags &= ~(HVKBD_FLAG_POLLING | HVKBD_FLAG_COMPOSE); + sc->sc_accents = 0; + sc->sc_composed_char = 0; } static int @@ -453,6 +661,12 @@ hvkbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg) #endif KBD_LED_VAL(kbd) = *(int *)arg; break; + case PIO_KEYMAP: /* set keyboard translation table */ + case OPIO_KEYMAP: /* set keyboard translation table (compat) */ + case PIO_KEYMAPENT: /* set keyboard translation table entry */ + case PIO_DEADKEYMAP: /* set accent key translation table */ + sc->sc_accents = 0; + /* FALLTHROUGH */ default: return (genkbd_commonioctl(kbd, cmd, arg)); } @@ -578,7 +792,7 @@ hv_kbd_drv_attach(device_t dev) hvkbd_clear_state(kbd); KBD_PROBE_DONE(kbd); KBD_INIT_DONE(kbd); - sc->sc_mode = K_RAW; + sc->sc_mode = K_XLATE; (*sw->enable)(kbd); #ifdef EVDEV_SUPPORT diff --git a/sys/dev/hyperv/input/hv_kbdc.h b/sys/dev/hyperv/input/hv_kbdc.h index 562009df9a94..7effa6b8a49b 100644 --- a/sys/dev/hyperv/input/hv_kbdc.h +++ b/sys/dev/hyperv/input/hv_kbdc.h @@ -90,6 +90,9 @@ typedef struct hv_kbd_sc_t { keyboard_t sc_kbd; int sc_mode; int sc_state; + uint32_t sc_accents; /* accent key index (> 0) */ + uint32_t sc_composed_char; /* composed char code */ + uint8_t sc_prefix; /* AT scan code prefix */ int sc_polling; /* polling recursion count */ uint32_t sc_flags; int debug;