Bug #11501

Updated by Joshua M. Clulow about 3 years ago

h1. 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. 

 h1. 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@) @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. 

 h1. 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.