Scroll Lock translation to control sequence is patently unhelpful
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
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
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
conskbd, where it is:
- transformed from a USB scancode to a symbolic key (see
- (for the console) transformed by
kbtrans_ascii_keypressed()to an ASCII byte sequence to effectively be passed up to
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
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.
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.