Project

General

Profile

Bug #11501

Scroll Lock translation to control sequence is patently unhelpful

Added by Joshua M. Clulow about 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Normal
Category:
kernel
Start date:
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

Overview

Most keyboards (using any interconnect) have a series of function keys beyond the alphanumeric; e.g., F1, F2, F3, Pause, Print Screen, etc. Some function keys are generally "sticky" and associated with an indicator light; e.g., Caps Lock, Scroll Lock, and Num Lock.

Of the sticky keys, the Scroll Lock key is the most archaic: its function is not standard across different operating systems, or even different terminal or windowing environments. On illumos, the key is not even sticky when using the framebuffer text console! Instead of acting as a modifier or even merely influencing the indicator light state, a control sequence is emitted as keyboard input: CSI 210 z. This control sequence is not, as near as I can tell, recognised by any software. A user pressing the Scroll Lock key will likely confuse whatever application (including the shell, or the kernel line discipline) is currently active.

The SPICE server code used for framebuffer and keyboard emulation in some hypervisors (e.g., QEMU/KVM on Linux) makes an unfortunately aggressive attempt to keep the emulated Scroll Lock indicator light (which we do not handle!) synchronised with the Scroll Lock state on the client keyboard. Every two seconds, it will produce an emulated press and release of the Scroll Lock key in the guest, making the console effectively unusable.

Keyboard Handling Background

The keyboard handling subsystem involves a number of modules and a somewhat impenetrable Rube Goldberg machine of STREAMS. Roughly, we're looking at this structure:

console stdin <- wc <-  conskbd  <- keyboard driver (kb8042, usbkbm, etc)
                       [kbtrans]       [kbtrans]

Drivers for physical keyboards (e.g., kb8042 on Intel, or usbkbm on all platforms for USB keyboards) start out by setting up an instance of the common kbtrans framework through kbtrans_streams_init(). This framework begins in the TR_ASCII translation mode. The keyboard drivers are capable of simulating either a native scancode set (e.g., PC AT keyboard for kb8042) or the USB HID scancode set; this can be set via the CONSSETKBDTYPE ioctl().

The conskbd module is pushed on top of the lower keyboard driver. While it initialises, it forces the underlying keyboard to use the USB scancode set via CONSSETKBDTYPE. It also disables translation to ASCII by switching to the TR_UNTRANS_EVENT mode via KIOCTRANS. This means that conskbd gets raw key press/release events from the keyboard driver. The conskbd module has its own kbtrans instance which remains in the TR_ASCII mode by default (for use on the text console) until a subsequent VUIDSFORMAT or KIOCTRANS ioctl(2) from, say, a windowing system.

In practice, a key press or release event is received by the keyboard driver which passes it to kbtrans_streams_key() where it is effectively handed on to conskbd unmodified. It is then passed again to kbtrans_streams_key() by conskbd, where it is:

  • transformed from a USB scancode to a symbolic key (see sys/kbd.h)
  • (for the console) transformed by kbtrans_ascii_keypressed() to an ASCII byte sequence to effectively be passed up to stdin

The structure of the key maps in sys/kbd.h appears to reflect a world centred around the old Sun Type 3/4 keyboards. There are some comments in the sys/kbd.h and terminfo.src that suggest that the function keys were considered in groups based on their location on keyboards from that era. Of particular note: R3, the third key from the left on the top row of the right hand bank on a Sun Type 4, was labelled Scroll Lock. As such, it is represented using the macro RF(3) in the tables that translate from scancodes to symbolic keys.

Proposed Fix

In the FUNCKEYS arm of kbtrans_ascii_keypressed(), we should just drop Scroll Lock key presses (i.e., RF(3)) on the floor. This is late enough in processing that if a windowing system takes over and disables TR_ASCII mode, the system can still receive the Scroll Lock presses and (hopefully) correctly control the indicator lights as SPICE expects. This also doesn't preclude subsequent reactivation of Scroll Lock processing on the text console if somebody wants to implement an actual scrolling lock of some kind, provided they are willing to absorb the keystrokes and toggle the indicator light as expected.

History

#1

Updated by Joshua M. Clulow about 1 year ago

  • Description updated (diff)
#2

Updated by Joshua M. Clulow about 1 year ago

Testing Notes

I have an OpenIndiana guest that I use for testing. Before rebooting, checked that pressing Scroll Lock emitted the sequence on the terminal as described in the bug (CSI 220 z). Built the change and rebooted, confirming that the sequence was no longer emitted. Confirmed with DTrace to make sure using this one-liner:

dtrace -qn '
    kbtrans_ascii_keypressed:entry {
        self->x = 1;
        printf("kbtrans_ascii_keypressed 0x%x\n", args[2]);
    }
    kbtrans_putbuf:entry /self->x/ {
        tracemem(args[0], 14, strlen((char *)args[0]));
    }
    kbtrans_ascii_keypressed:return {
        self->x = 0;
    }'

Pre-Change

On a system without the change, I pressed Print Screen twice and then Scroll Lock twice:

kbtrans_ascii_keypressed 0x46

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 30 39 7a                                .[209z
kbtrans_ascii_keypressed 0x46

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 30 39 7a                                .[209z
kbtrans_ascii_keypressed 0x47

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 31 30 7a                                .[210z
kbtrans_ascii_keypressed 0x47

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 31 30 7a                                .[210z

Post-Change

On the fixed system, I did the same thing:

kbtrans_ascii_keypressed 0x46

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 30 39 7a                                .[209z
kbtrans_ascii_keypressed 0x46

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 1b 5b 32 30 39 7a                                .[209z
kbtrans_ascii_keypressed 0x47
kbtrans_ascii_keypressed 0x47

Confirmed that other interaction with the framebuffer console still works as expected (including the numbered function keys, etc).

#4

Updated by Joshua M. Clulow about 1 year ago

Note that if you need the old behaviour back, there's a workaround variable you can set; i.e.,

mdb -kwe 'kbtrans_ignore_scroll_lock/W 0'

This will restore the original behaviour.

#5

Updated by Electric Monk about 1 year ago

  • Status changed from New to Closed
  • % Done changed from 0 to 100

git commit 7d724debd861d6eb53233974d0191aeef122cd23

commit  7d724debd861d6eb53233974d0191aeef122cd23
Author: Joshua M. Clulow <josh@sysmgr.org>
Date:   2019-08-01T22:05:50.000Z

    11501 Scroll Lock translation to control sequence is patently unhelpful
    Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
    Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk>
    Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
    Reviewed by: Toomas Soome <tsoome@me.com>
    Approved by: Richard Lowe <richlowe@richlowe.net>

Also available in: Atom PDF