Thursday, September 14, 2017

Keyboard - Layouts

For system administration, specially at a local or serial console, it is important to have a properly configured keyboard layout as in this case it's generally the only input device available to interact with the system. In such cases it would be unfortunate if one would find it out mis-configured under some emergency or critical condition.

This happened to me a few times where I had to interact locally on some special servers and have found that the datacenter where the machines were placed didn't have proper KVM switches but only a few keyboards left over to be physically connected to host in case of emergencies. What was particularly bad is that the keyboards were rather different among brands, versions and languages, so that once plugged in I had to abstract all physical keys markings and work base on the English layout on my mind although a few important keys were frequently missing or mis-configured.

On two older posts I started talking about a way to fix or mitigate this issue:

As an example I'll continue to work on a solution to the following keyboard, which is a Brazilian derivative re-branded by Dell as model KM-632 (BR) from a variant of the original Chicony Electronics model KG-1089:

With the exception of the keys in orange, all other keys' keystation have already been identified on an older post of this series. The main issues are the keys in green and cyan which are some sort of manufacturer pitfalls.

Before presenting the solution I'll just exhibit how choosing the Brazilian keyboard layout via kbd(1) or nlsadm(1M) aren't good solutions either. That is, both kbd -s Brazilian or nlsadm set-console-keymap Brazilian attempt to load the same flawed keymap from the files brazil or layout_110 located at /usr/share/lib/keytables/type_6.

NOTE
By the way the layout identification number is presented in different ways that might be a little misleading at first. The contents of the plain text file kbd_layouts at /usr/share/lib/keytables/type_6 uses decimal numbers, the layout files are actually named based on hexadecimal numbers and kbd -s presents the layouts in an ordinal order but omitting their actual numbers. For instance, the Brazilian layout number is decimal 272 but layout file is called layout_110 (in hexadecimal) although kbd -s presents it as option 3. On top of this there is an additional layout file named brazil which is an exact duplicate of layout_110.

The provided Brazilian layout as I said is bad and flawed because of:
  • It wrongly "guesses" some keystations not in the standards.
  • It enables the cedilla and the so-called "dead-keys" for diacritics.

The reasonable behavior is exactly the opposite of the above flaws. It's true that it's impossible to correctly guess the keystations not covered by the standards which each manufacture is free to drive us crazy, but better than doing wrong is not doing at all. At most a simple thoughtful warning message would be much better (and I wouldn't have to suffer for years until I find some time to write long blog posts to share my experience with others).

In practice, for the above keyboard, beyond the crazy cedilla and diacritics (dead-keys) the following misbehavior happens while using the out-of-the-box configuration options:
  • Pressing \ (at keystation 100) actually prints /
  • Both / and ? (at keystation 135) are dead
  • Keypad key , (at keystation 99) prints a .
  • Keypad key . (at keypad keystation 230) is dead
  • It seems impossible to get the ~ or ` (at keystations 52 and 47)

As seen important keys for system administration are in trouble. As mentioned, under such circumstances the only way out was to revert to the well-known (and memorized) English layout and forget as much as possible the other idiom markings on the physical keyboard. But a better solution is to eliminate the dead-keys, the cedilla and simply make the physical keys generate the corresponding chars hard-printed on them, isn't it?

In order to provide a correct layout mapping it's necessary to have a basic understanding of the layout files which is described under keytables(4) and some information from kb(7M).

A layout file describes up to 7 translation tables for each keystation.
Each translation table defines what action will occur as to when:
  • base  : no shifts are active
  • shift : "Shift" key is down
  • caps  : "CapsLock" is in effect
  • ctrl  : "Control" is down
  • altg  : "Alt_Gr" is down
  • numl  : "NumLock" is in effect
  • up    : a (general shift) key goes up

Each action maybe a keyword, a (short) C-string (usually an escape sequence) or an (8-bits) ISO 8859-1 character (Latin-1) possibly specified as a control character (^ prefixed alphabetic char) or an octal constant starting with a \ and having up to 3 octal digits (0 to 7) corresponding to a decimal number in the range of 0 to 255.

Instead of repeatedly specifying the same action for key translation table in turn, it's possible to use a shortcut with the keyword all meaning all translation tables except numl and up. For instance:
# All tables set to a shell continuation line
key   51   all " \\\r"   numl nonl   up nop

# Keystation 70 to produce no action at all

key   70   all hole

The preceding excerpt also presents another (subtle) rule:
When using the all keyword,
if the action is different from hole,
then numl nonl and up nop must be specified as well.

According to keytables(4) it's mandatory to have:
(go figure! I didn't notice side-effects of using just all hole instead)
key  126   all error   numl error   up hole
key  127   all idle    numl idle    up reset

You may also have noticed above that it's possible to override some translation table action even when the all keyword has been used as well.

With this basic information at hand it's now possible to establish a first version of the proposed solution to fix the layout issues of the sample keyboard:

#
# Type 6 (USB) layout for DELL KM632 (BR)

#
# This layout forms an extensive baseline.
# It provides no complex dead-keys or Alt_Gr sequences.

# Notes for function keys (BFn, TFn, LFn and RFn):
#        F1    ...    F12   ...    F16
#   L ESC[192z ... ESC[203z ... ESC[207z
#   R ESC[208z ... ESC[219z ... ESC[223z
#   T ESC[224z ... ESC[235z ... ESC[239z
#   B ESC[240z ... ESC[251z ... ESC[255z

# In theory I could use escape sequences similar to those above.
# Unfortunately, these would result in a "too many strings" error.
# It's important to know how to capture these in BASH READLINE.
# Whithin ~/.inputrc they should be referenced as "\e[XXXz": command/macro

# Still availables:
#   - functions: BF16, TF16, LF16.
#   - keystations: 35 (shift table), 51 (all tables)
#   - some ctrl / shift actions for keystations: 
#     -- 30 to 39, 40 to 44, 45 to 48, 50, 79 to 82, 100
#

key   0  all hole
key   1  all hole
key   2  all hole
key   3  all nonl
#
key   4  baseshiftcapsctrl ^A  altg nop
  numl nonl  up nop
key   5  baseshiftcapsctrl ^B  altg
nop  numl nonl  up nop
key   6  baseshiftcapsctrl ^C  altg
nop  numl nonl  up nop
key   7  baseshiftcapsctrl ^D  altg
nop  numl nonl  up nop
key   8  baseshiftcapsctrl ^E  altg
nop  numl nonl  up nop
key   9  baseshiftcapsctrl ^F  altg
nop  numl nonl  up nop
key  10  baseshiftcapsctrl ^G  altg
nop  numl nonl  up nop
key  11  baseshiftcapsctrl ^H  altg
nop  numl nonl  up nop
key  12  baseshiftcapsctrl ^I  altg
nop  numl nonl  up nop
key  13  baseshiftcapsctrl ^J  altg
nop  numl nonl  up nop
key  14  baseshiftcapsctrl ^K  altg
nop  numl nonl  up nop
key  15  baseshiftcapsctrl ^L  altg
nop  numl nonl  up nop
key  16  baseshiftcapsctrl ^M  altg
nop  numl nonl  up nop
key  17  baseshiftcapsctrl ^N  altg
nop  numl nonl  up nop
key  18  baseshiftcapsctrl ^O  altg
nop  numl nonl  up nop
key  19  baseshiftcapsctrl ^P  altg
nop  numl nonl  up nop
key  20  baseshiftcapsctrl ^Q  altg
nop  numl nonl  up nop
key  21  baseshiftcapsctrl ^R  altg
nop  numl nonl  up nop
key  22  baseshiftcapsctrl ^S  altg
nop  numl nonl  up nop
key  23  baseshiftcapsctrl ^T  altg
nop  numl nonl  up nop
key  24  baseshiftcapsctrl ^U  altg
nop  numl nonl  up nop
key  25  baseshiftcapsctrl ^V  altg
nop  numl nonl  up nop
key  26  baseshiftcapsctrl ^W  altg
nop  numl nonl  up nop
key  27  baseshiftcapsctrl ^X  altg
nop  numl nonl  up nop
key  28  baseshiftcapsctrl ^Y  altg
nop  numl nonl  up nop
key  29  baseshiftcapsctrl ^Z  altg
nop  numl nonl  up nop
#
key  30  base shift !    caps ctrl nop 
altg nop  numl nonl  up nop
key  31  base shift @    caps
ctrl nop  altg nop  numl nonl  up nop
key  32  base shift #    caps
ctrl nop  altg nop  numl nonl  up nop
key  33  base shift $    caps
ctrl nop  altg nop  numl nonl  up nop
key  34  base shift %    caps
ctrl nop  altg nop  numl nonl  up nop
key  35  base shift nop  caps
ctrl nop  altg nop  numl nonl  up nop
key  36  base shift &    caps
ctrl nop  altg nop  numl nonl  up nop
key  37  base shift *    caps
ctrl nop  altg nop  numl nonl  up nop
key  38  base shift (    caps
ctrl nop  altg nop  numl nonl  up nop
key  39  base shift )    caps
ctrl nop  altg nop  numl nonl  up nop

#   - For Backspace I have to use '\177' (octal) and not '\b':
#     -- Note that \177 (octal) = 7F (hexa) = 127 (decimal)
#     -- The terminal will see \177 as ^?, which is the correct thing.
#     -- The \b would be seen as ^H which isn't the default "stty erase".
#     -- This is important for the correct login prompt behavior
#        of the backspace (keystation 42) 
#
# Note: The escape sequence strings begin with ^[ 
#       which in VI/VIM is generated while in insert mode
#       by pressing ^V and then the Esc key. 
#       copy-and-paste may not work.

key  40  all '\r'    ctrl "^[[187z"   numl nonl  up nop
key  41  all ^[
      ctrl "^[[188z"   numl nonl  up nop
key  42  all '\177'  ctrl "^[[189z"   numl nonl  up nop
key  43  all '\t'
    ctrl "^[[190z"   numl nonl  up nop
key  44  all ' ' 
    ctrl "^[[191z"   numl nonl  up nop
#
key  45  base -    shift _   caps -   
ctrl nop  altg nop  numl nonl  up nop
key  46  base =    shift +   caps =   
ctrl nop  altg nop  numl nonl  up nop
key  47  base '\'' shift '`' caps '\''
ctrl nop  altg nop  numl nonl  up nop
key  48  base [    shift {   caps [   
ctrl nop  altg nop  numl nonl  up nop
#
key  49  all hole 
#
key  50  base ]    shift }   caps ]   
ctrl nop  altg nop  numl nonl  up nop  
#
# keystation 51 is cedilla
# Yet to decide what to do 
#
key  51  all hole
#
key  52  base ~    shift '^'  caps ~     ctrl nop  altg nop  numl nonl  up nop
key  53  base '\'' shift '"'  caps '\''  ctrl nop  altg nop  numl nonl  up nop
key  54  base ,    shift <    caps ,     ctrl nop  altg nop  numl nonl  up nop
key  55  base .    shift >    caps .    
ctrl nop  altg nop  numl nonl  up nop
key  56  base ;    shift :    caps ;     ctrl nop  altg nop  numl nonl  up nop
#
key  57  all shiftkeys+capslock
#
# keystations 58 thru 69 are F1 thru F12 respectively

# Decision:
#   -         Fn = bf(n)
#   - Shift + Fn = lf(n)
#   - Ctrl  + Fn = tf(n) --> to not conflict with VT-n shortcuts
#
key  58  base bf(1)  shift lf(1)  caps bf(1)  ctrl tf(1)  altg nop  numl nonl  up nop
key  59  base bf(2)  shift lf(2)  caps bf(2)  ctrl tf(2)  altg nop  numl nonl  up nop
key  60 
base bf(3)  shift lf(3)  caps bf(3)  ctrl tf(3)  altg nop  numl nonl  up nop
key  61 
base bf(4)  shift lf(4)  caps bf(4)  ctrl tf(4)  altg nop  numl nonl  up nop
key  62 
base bf(5)  shift lf(5)  caps bf(5)  ctrl tf(5)  altg nop  numl nonl  up nop
key  63 
base bf(6)  shift lf(6)  caps bf(6)  ctrl tf(6)  altg nop  numl nonl  up nop
key  64 
base bf(7)  shift lf(7)  caps bf(7)  ctrl tf(7)  altg nop  numl nonl  up nop
key  65 
base bf(8)  shift lf(8)  caps bf(8)  ctrl tf(8)  altg nop  numl nonl  up nop
key  66 
base bf(9)  shift lf(9)  caps bf(9)  ctrl tf(9)  altg nop  numl nonl  up nop
key  67 
base bf(10) shift lf(10) caps bf(10) ctrl tf(10) altg nop  numl nonl  up nop
key  68 
base bf(11) shift lf(11) caps bf(11) ctrl tf(11) altg nop  numl nonl  up nop
key  69 
base bf(12) shift lf(12) caps bf(12) ctrl tf(12) altg nop  numl nonl  up nop
#
# PtrScn=70, Ins=73, Home=74, PgUp=75, Del=76, End=77, PgDn=78

# Decisions:
#   - For PrtScn, just use it as F13 similarly as above.
#   - For the other special keys I'll have to use RFn keys.
#     At first I'm interested only on Ctrl modifications. 
#
key  70  base bf(13) shift lf(13) caps bf(13) ctrl tf(13) altg nop  numl nonl  up nop
# 
key  71  all hole
key  72 
all hole 
#
key  73  all rf(1)   ctrl rf(2)   numl nonl  up nop
key  74  all rf(3)   ctrl rf(4)   numl nonl  up nop
key  75  all rf(5)   ctrl rf(6)   numl nonl  up nop 
key  76  all rf(7)   ctrl rf(8)   numl nonl  up nop
key  77  all rf(9)   ctrl rf(10)  numl nonl  up nop 
key  78  all rf(11)  ctrl rf(12)  numl nonl  up nop
#
key  79  all string+rightarrow 
ctrl rf(13)  numl nonl  up nop
key  80  all string+leftarrow   ctrl rf(14)  numl nonl  up nop
key  81  all string+downarrow   ctrl rf(15)  numl nonl  up nop
key  82  all string+uparrow     ctrl rf(16)  numl nonl  up nop 
#
# This keyboard has no NumLock toggle (by default it's always on)

# But it must be declared as present for proper /dev/kbd operation
# This is particularly necessary across reboots or the flag may be lost
#
key  83  all shiftkeys+numlock
# 
# paddot clashes with AltGr, both are keystation 230
# Yet to decide what to do
#
# This keyboard has no padequal

#
key  84  all hole  numl padslash  up nop
key  85  all hole  numl padstar  
up nop
key  86  all hole  numl padminus 
up nop
key  87  all hole  numl padplus  
up nop
key  88  all hole  numl padenter 
up nop
key  89  all hole  numl pad1     
up nop
key  90  all hole  numl pad2     
up nop
key  91  all hole  numl pad3     
up nop
key  92  all hole  numl pad4     
up nop
key  93  all hole  numl pad5     
up nop
key  94  all hole  numl pad6     
up nop
key  95  all hole  numl pad7     
up nop
key  96  all hole  numl pad8     
up nop
key  97  all hole  numl pad9     
up nop
key  98  all hole  numl pad0     
up nop
key  99  all hole  numl padsep   
up nop
#
key 100  base '\\'  shift caps '\\' 
ctrl nop  altg nop  numl nonl  up nop
#
# Keystation 101 is Menu

# Decision:
#   - For now, use as F14
#
key 101
 base bf(14) shift lf(14) caps bf(14) ctrl tf(14) altg nop numl nonl up nop
#
key 102  all hole
key 103 
all hole
key 104 
all hole
key 105 
all hole
key 106 
all hole
key 107 
all hole
key 108 
all hole
key 109 
all hole
key 110 
all hole
key 111 
all hole
key 112 
all hole
key 113 
all hole
key 114 
all hole
key 115 
all hole
key 116 
all hole
key 117 
all hole
key 118 
all hole
key 119 
all hole
key 120 
all hole
key 121 
all hole
key 122 
all hole
key 123 
all hole
key 124 
all hole
key 125 
all hole 
#
key 126  all error  numl error  up hole
key 127 
all idle   numl idle   up reset

key 128  all hole
key 129 
all hole
key 130 
all hole
key 131 
all hole
key 132 
all hole
key 133 
all hole
key 134 
all hole
#
key 135  base shift caps
ctrl nop  altg nop  numl nonl  up nop
#
key 136 
all hole
key 137 
all hole
key 138 
all hole
key 139 
all hole
key 140 
all hole
key 141 
all hole
key 142 
all hole
key 143 
all hole
key 144 
all hole
key 145 
all hole
key 146 
all hole
key 147 
all hole
key 148 
all hole
key 149 
all hole
key 150 
all hole
key 151 
all hole
key 152 
all hole
key 153 
all hole
key 154 
all hole
key 155 
all hole
key 156 
all hole
key 157 
all hole
key 158 
all hole
key 159 
all hole
key 160 
all hole
key 161 
all hole
key 162 
all hole
key 163 
all hole
key 164 
all hole
key 165 
all hole
key 166 
all hole
key 167 
all hole
key 168 
all hole
key 169 
all hole
key 170 
all hole
key 171 
all hole
key 172 
all hole
key 173 
all hole
key 174 
all hole
key 175 
all hole
key 176 
all hole
key 177 
all hole
key 178 
all hole
key 179 
all hole
key 180 
all hole
key 181 
all hole
key 182 
all hole
key 183 
all hole
key 184 
all hole
key 185 
all hole
key 186 
all hole
key 187 
all hole
key 188 
all hole
key 189 
all hole
key 190 
all hole
key 191 
all hole
key 192 
all hole
key 193 
all hole
key 194 
all hole
key 195 
all hole
key 196 
all hole
key 197 
all hole
key 198 
all hole
key 199 
all hole
key 200 
all hole
key 201 
all hole
key 202 
all hole
key 203 
all hole
key 204 
all hole
key 205 
all hole
key 206 
all hole
key 207 
all hole
key 208 
all hole
key 209 
all hole
key 210 
all hole
key 211 
all hole
key 212 
all hole
key 213 
all hole
key 214 
all hole
key 215 
all hole
key 216 
all hole
key 217 
all hole
key 218 
all hole
key 219 
all hole
key 220 
all hole
key 221 
all hole
key 222 
all hole
key 223 
all hole
#
key 224  all shiftkeys+leftctrl   up shiftkeys+leftctrl
key 225  all shiftkeys+leftshift  up shiftkeys+leftshift
key 226  all shiftkeys+alt        up shiftkeys+alt
#
# Keystation 227 is Super (Win)

# Wondered about: "all compose  numl nonl  up nop" 
# Decision:
#   - For now, use as F15

key 227  base bf(15) shift lf(15) caps bf(15) ctrl tf(15) altg nop numl nonl up nop
#
key 228  all shiftkeys+rightctrl   up shiftkeys+rightctrl
key 229  all shiftkeys+rightshift  up shiftkeys+rightshift

#
# Alt_Gr clashes with paddot
# Yet to decide what to do
#
key 230  all shiftkeys+altgraph    up shiftkeys+altgraph
#
key 231 
all hole
key 232 
all hole
key 233 
all hole
key 234 
all hole
key 235 
all hole
key 236 
all hole
key 237 
all hole
key 238  all hole
key 239 
all hole
key 240 
all hole
key 241 
all hole
key 242 
all hole
key 243 
all hole
key 244 
all hole
key 245 
all hole
key 246 
all hole
key 247 
all hole
key 248 
all hole
key 249 
all hole
key 250 
all hole
key 251 
all hole
key 252 
all hole
key 253 
all hole
key 254 
all hole

At anytime to apply this new layout shown above it suffices to use the loadkeys(1) command. Suppose the layout is saved to a file called layout-DELL-KM632-BR located in /tmp. Then to apply it one would do:

$ loadkeys /tmp/layout-DELL-KM632-BR

But if the layout is to be automatically applied every time the system boots, then two steps are necessary:
  1. It must be added to the layouts database, which for general USB keyboards is the file kbd_layouts located at /usr/share/lib/keytables/type_6:
     
    # cd /usr/share/lib/keytables/type_6
    # cp /tmp/layout-DELL-KM632-BR .
    # ln -s layout-DELL-KM6332-BR layout_200
    # grep Brazilian kbd_layouts

    Brazilian=272
    Brazilian-DELL-KM632=512

     
    The addition must be inserted (edited in) respecting an order as described by the comments on top of the database file.

    Note that the suffix _200 is the hexa representation of 512 decimal. I chose this number because it seemed free. I also chose to name the new layout as Brazilian-DELL-KM632. The almost useless generic Brazilian layout is number 272 = 110 hexa.

    Confirming:

    $ kbd -s
    USB keyboard
     1. Arabic                        15. Japanese 
     2. Belgian                       16. Korean 
     3. Brazilian                     17. Latin-American  
     4. Brazilian-DELL-KM632          18. Norwegian  
        ...
    14. Japanese-type6                28. US-English 

    To select the keyboard layout, enter a number [default 28]:

    ^C
      
  2. Finally, once the new keyboard layout is properly registered into the keyboard layouts database, it suffices to activate it as follows:

    $ nlsadm set-console-keymap Brazilian-DELL-KM632
    Setting ... keymap/layout with ...: Brazilian-DELL-KM632
    Successfully set


    As long as the user posesses the necessary authorization:

    $ profiles |grep National
    National Languages Support Management

NOTE
Step 2 above works under Solaris 11.3 but that may not be the case under older Solaris 11 versions, such as the very first Solaris 11 Express. For older versions, it's probably necessary to manually edit the corresponding SMF keymap:default property:

# svccfg -s keymap:default
svc:/system/keymap:default>

 
...>
listprop keymap/*
keymap/console_beeper_freq  integer  900
keymap/kbd_beeper_freq      integer  2000
keymap/keyboard_abort       astring  enable
keymap/keyclick             boolean  false
keymap/repeat_delay         integer  500
keymap/repeat_rate          integer  40
keymap/layout               astring  US-English


...> setprop keymap/layout = \
     astring: "Brazilian-DELL-KM632"
 

...> refresh
...>
end

 
# svcadm restart keymap:default


The above sample layout is intended to be a sort of baseline. As seen it doesn't attempt to enable dead-keys for some diacritics and the cedilla, Alt_Gr for some other special symbols, or even some odd particularities of the specific physical keyboard at hand.

But each of this cases could be treated as a whole or as independent use cases by crafting additional layout fragments to be manually loaded as needed. For instance, let me give some examples:

EXAMPLE 1:

Turning Alt_Gr on and off in favor of a fully keypad setup (that is, making the blue key in the image below work); a particularity of the specific physical keyboard at hand (for reference, see the image of the physical layout and keystations presented at Keyboard - Keystations). Recall that in this particular keyboard the blue key (keystation 230) below clashes with the Alt_Gr key which uses the same keystation number, so it makes more sense to enable this blue key only under special circunstances that would require a fully functional keypad to easy some sort of data entry or edition.


The following could be on file DELL-KM632-BR-keypad-dot:

#
# Type 6 (USB) layout for DELL KM632 (BR) - fragment

# Disabling Alt_Gr sequences in favor of keypad.
#
key 230  all hole  numl paddot    up nop

The following could be on file DELL-KM632-BR-keypad-basic:

#
# Type 6 (USB) layout for DELL KM632 (BR) - fragment

# Restoring Alt_Gr sequences.
#
key 230  all shiftkeys+altgraph   up shiftkeys+altgraph

The following command could temporarily activate the layout which includes paddot:

$ loadkeys DELL-KM632-BR-keypad-dot

EXAMPLE 2:

As previously remarked, keystation 51, which correspondig physical key in this keyboard is hard-printed as the cedilla (ç) character is pretty much useless at a console scenario, hence the baseline file to the top of this post just mutes it. But due to its very confortable physical location on the physical keyboard it could be assigned some frequent action of choice, for instance:
  • the escape character (cloning keystation 41)
  • the padequal keyword (or cloning keystation 46)
  • the dash and underline characters (cloning keystation 45)
  • and so on...

Let's say for instance that due to an intensive use of VI / VIM it would be more convenient to clone keystation 41 to keystation 51. This setting could be on the layout fragment file DELL-KM632-BR-cedilla-esc:

#
# Type 6 (USB) layout for DELL KM632 (BR) - fragment

# Cloning action of the Esc key to the ç key.
#
key  51  same as  41

EXAMPLE 3:

On some legacy Sun keyboards the Caps key and the (left) Ctrl key were reversed. Perhaps one would like to emulate that situation on the sample keyboard above by basing the choice upon an old habit, easier key access in relation to its frequency of use or even that due to a lot of VI / VIM editing it's safer move Caps out of the way where it may accidentally change an intended command after some mixed-case typing, and so on... This setting could be on the layout fragment file DELL-KM632-BR-reverse-caps-ctrl:

#
# Type 6 (USB) layout for DELL KM632 (BR) - fragment

# Reverses action between the Caps key and the left Ctrl key.
#
swap  57  with  224

EXAMPLE 4:

On another keyboard the NumLock key may be present. Of course in this case the initially configured keystations' actions while NumLock is OFF should be the standard ones, that is, duplicating the functionality of the enhanced keyboard keys such as the arrow keys, Home, End and so on... This is different from what is shown on this post sample keyboard as it doesn't have a NumLock key. But in case of a different keyboard with the NumLock key, one might have chosen different actions for the keystations while NumLock is OFF. Hence, to temporarily restore the standard behavior there could be a layout fragment file such as VENDOR-MODEL-BR-keypad-full:

#
# Standard actions when NumLock is OFF

#
key  89  all rf(9)              ctrl rf(10)  numl pad1    up nop
key  90  all string+downarrow  
ctrl rf(15)  numl pad2    up nop
key  91  all rf(11)            
ctrl rf(12)  numl pad3    up nop
key  92  all string+leftarrow  
ctrl rf(14)  numl pad4    up nop
key  93  all hole                           
numl pad5    up nop
key  94  all string+rightarrow 
ctrl rf(13)  numl pad6    up nop
key  95  all rf(3)             
ctrl rf(4)   numl pad7    up nop
key  96  all string+uparrow    
ctrl rf(16)  numl pad8    up nop
key  97  all rf(5)             
ctrl rf(6)   numl pad9    up nop
key  98  all rf(1)             
ctrl rf(2)   numl pad0    up nop
key  99  all rf(7)             
ctrl rf(8)   numl padsep  up nop

EXAMPLE 5:

If another similar (physical) keyboard becomes temporarily available, then, instead of  providing a whole complete definition to it as demonstrated above, it may be easier and more convenient to have just a fragment that adjusts the minor differences. For instance, I have an old Microsoft Wireless Keyboard 1000 which keystations are very similar to the Dell KM-632. Thus I just need the following layout fragment file MS-WK1000-BR:

key  49  base ]    shift }   caps ]    ctrl nop  altg nop  numl nonl  up nop
key  50  same as  49


# 71=ScrLk, 72=Pause
key  71  all  "^[[185z"  numl nonl  up nop
key  72  all 
"^[[186z"  numl nonl  up nop
 

NOTE
It is convenient to have such layout fragments given in pairs, where one sets the change and the other reverses the change. Of course, the one that reverses the change is just a copy of a portion of the original whole baseline.

Strictly speaking, that's it for the console keyboard configuration. But, in practice, to take advantage of it there comes into play how the shell may respond to it. For BASH(1) this means duly configuring key bindings via the per user, local ~/.inputrc. But this is subject to another post: The .inputrc revisited.