Solaris Keyboard Howto

Recently I installed Solaris 11 Express in a VirtualBox VM on my MacBook Pro 3.1. Unfortunately my MacBook has a german keyboard (which is really strange BTW) and does not conform to the usual USB keyboards and thus there was no way to get the solid bar aka pipe symbol and some other essential signs printed on the command line (console). So I took some time to find out, how to make the keyboard behave as I want it to and here is, what I've found out.

Setting the default keyboard layout

If you have a standard keyboard, Solaris has usually all you need. If it did not find out automatically, what kind of keyboard is connected to the system, you may set it explictly by setting the keymap/layout property of the keymap:default service:

svccfg -s keymap:default setprop keymap/layout=German svcadm refresh keymap

To choose another keyboard layout on the fly, one may use:

kbd -s loadkeys

This tool shows you all available layout names (which can be used for the keymap/layout property of the keymap:default service as well) and lets you choose the one to use. The loadkeys command is required, to finally activate the new layout.

Another way to set the default keyboard layout is to set the appropriate eeprom/OBP property:

eeprom set keyboard-layout=German # and to avoid confusion svccfg -s keymap:default delprop keymap/layout svcadm refresh keymap

This works, since the keymap service starter first looks at the eeprom/OBP settings for the keyboard-layout property, and if its value is valid, kbd -s $value is used to set the default keyboard layout. If it the keymap:default service property keymap/layout is also set, the starter uses kbd -i to set the keyboard layout according to property value (otherwise the currently set keyboard layout will be kept). Last but not least it does a loadkeys to activate the layout.

Further information can be found in:

Defining a new keyboard layout

As mentioned before, many laptops have their "own" keyboard layout, and thus using a default keyboard layout coming with Solaris is quite a pain. In this case it is the best to create a new keyboard layout map and use this one instead. All you need to do for this is to add your layout name and ID to the file kbd_layouts in the /usr/share/lib/keytables/type_6 directory (the type_6 directory hosts all layouts for USB keyboards) and to add the file layout_HexID, which contains your modifications to the default keyboard layout.

However, before you go ahead, you should read the man page for kbd and keytables, since I'm not going to explain/repeat every tiny detail.

scancodes

The first thing to know wrt. defining a new keyboard layout are the scancodes, which are sent by each key. Usually each key sends always the same scancode, no matter which modifiers (CapsLock, Shift, Alt, AltGr, Meta, Command, etc.) are pressed down. However, some keyboards (especially laptops/notbooks) have special keys as well as a function key (fn), which cause some keys to emit a different scancode when they are pressed together. Also if no separate numeric keypad is available on the keyboard, there is usually a key combination, which lets you switch the keyboard into the numeric keypad mode, where some keys also emit different or no scancodes at all.

However, since scancodes are almost always an undocumented feature of the keyboard, keys are named different than in the USB specification 1.12, HID Usage Tables, KEYBOARD/KEYPAD PAGE (0X07), page 53ff., or keyboard emulation is buggy (as in VirtualBox 3.2.10 and 3.2.12), we need a reliable way to find them out. With Solaris it is easy to do that using the function probe provider of its wonder wappen dtrace:

dtrace -n 'fbt:kbtrans:kbtrans_translate:entry { printf("%d

",arg2) }'

Now you can press every key in each different keyboard mode, to see whether and which scancode gets emitted. For the MacBookPro 3.1 with the default german keyboard layout it may look like this table.

keyboard type

To determine the correct directory, where one needs to put the new keyboard definition file, one needs to get the type of keyboard in use. kbd -l shows, what you need to know. For later use, we store the type into the env variable KT :

KT=`kbd -l | fgrep type= | cut -f2 -d=`

For USB keyboards you will usually get type 6.

keytables directory

Now you should change your current working directoy to the directory, which contains the layout definitions for the type of keyboard in use:

cd /usr/share/lib/keytables/type_$KT

If it does not exist, create it, using mkdir -p and cd to it.

set the layout to use

To avoid a lot of typing, one should now choose a keyboard layout, which matches best your physical keyboard layout:

kbd -s

activate layout

When the keyboard layout to use has been set, one needs to activate it:

loadkeys

You may verify, that the changes are active, by pressing one of the "non-standard" keys wrt. your country (e.g. characters with diaresis aka umlaut or accent grave/acute).

layout name

To be able to select your keyboard layout with kbd -s and also to set it as default in eeprom or keymap:default service, one need to give it a name. It should be not longer than 30 characters. Also to avoid trouble, it is highly recommended to use ASCII letters, digits, underlines and hyphens, only and of course a name, which is not already defined in the file kbd_layouts. For later use, we store that name in the env variable KNAME :

KNAME='German-MacBook-Pro' grep "$KNAME=" kbd_layouts

layout ID

Also you need to assign an ID to your new keyboard layout. Of course you need to make sure again, that the new ID is not already in use. E.g.:

fgrep = kbd_layouts |sort -t= -k2n KNUM=333 KHEX=`printf '%02x' $KNUM`

For our convinience we store the new ID in the env variable KNUM and its hexadecimal value in the env variable KHEX .

dumping the active layout

Now dump the the keyboard layout, which is currently active, to the new layout file to use: it must have a name in the format layout_ ID , whereby the ID must be the hexadecimal value with at least two digits of the layout ID you have choosen in the previous step. E.g.:

dumpkeys >layout_$KHEX

publish keyboard layout name and ID

A you probably already guessed, to make the new layout available to the kbd -s as well as the keymap:default service, one needs to "publish" its name and ID. This can be done by just adding a new entry to the kbd_layouts in the appropriate keyboard type directory. The format of the entry is simple: layoutName = ID . Obviously the layoutName is the name you have choosen for your new keyboard layout, and the ID is the ID of the layout - this time in decimal (see above). E.g.:

echo "$KNAME=$KNUM" >>kbd_layouts

Finally try, whether the previously dumped layout works, using the kbd -s and loadkeys command. If you see any errors, just comment out the line in question by inserting a # at the start of the line (i.e. column 0) and try again.

If it finally works without any error message, you have now a starting point and shoud be able to modify the layout as you like (see man page keytables) and set it as the default keyboard layout to use as described above.

Solaris 11 Express seems to have bug wrt. the swap number1 with number2 instruction: it assigns the values for keystation number1 to keystation number2, but keystation number1 is set to an empty value aka 'all hole' and not to the previous values of number2!

Function key names

When defining a new keyboard layout, you probably get curious, what strings to use for the top ( tf ), left ( lf ), bottom ( bf ) and right ( rf ) function keys or what these keys are actually supposed to be. Actually, under the hood this is a block of 4*16=64 scancodes, where lf(1) marks the start of the first, rf(1) the start of the second, tf(1) the start of the third and bf(1) the start of the last block (see /usr/include/sys/kbd.h and the man page for kb). The corresponding Escape Sequences start at 192 for lf(1) and stop at 255 for bf(15) .

Unfortuetaly I haven't found a reliable source yet, which lets you determine easily, which function is assigned to the Escape Sequences mentioned above, and also no source, which defines, what ?f(n) to use for which "special key". So I took an original SUN keyboard, dumped its keyboard layout and assigned they names on those keys to the used ?f(n) code via their scancode:

Function Names and Scancodes for a SUN™ keyboard Key Code fn Name Escape Seq. Notes Left Function block Stop 120 buckybits+systembit Again 121 lf(2) ^[[193z Props 118 lf(3) ^[[194z Undo 122 lf(4) ^[[195z Front 119 lf(5) ^[[196z Copy 124 lf(6) ^[[197z Open 116 lf(7) ^[[198z Paste 125 lf(8) ^[[199z Find 126 lf(9) ^[[200z Cut 123 lf(10) ^[[201z Help 117 lf(16) ^[[207z Right Function block Pause 72 rf(1) ^[[208z Print 70 rf(2) ^[[209z ScrollLock 71 rf(3) ^[[210z Speaker toggle/Degauss 127 rf(4) ^[[211z : 84 rf(5) ^[[212z keypad * 85 rf(6) ^[[213z keypad Home / Pos 1 74 rf(7) ^[[214z Home / Pos 1 95 rf(7) ^[[214z keypad Page Up 75 rf(9) ^[[216z Page Up 97 rf(9) ^[[216z keypad 93 rf(11) ^[[218z keypad (on 5) End 77 rf(13) ^[[220z End 89 rf(13) ^[[220z keypad Page Down 78 rf(15) ^[[222z Page Down 91 rf(15) ^[[222z keypad Top Function block F1 58 tf(1) ^[[224z F2 59 tf(2) ^[[225z F3 60 tf(3) ^[[226z F4 61 tf(4) ^[[227z F5 62 tf(5) ^[[228z F6 63 tf(6) ^[[229z F7 64 tf(7) ^[[230z F8 65 tf(8) ^[[231z F9 66 tf(9) ^[[232z F10 67 tf(10) ^[[233z F11 68 tf(11) ^[[234z F12 69 tf(12) ^[[235z Bottom Function block Ins 73 bf(8) ^[[247z Ins 98 bf(8) ^[[247z keypad Del 99 bf(10) ^[[249z keypad Enter 88 bf(11) ^[[250z keypad Sleep/Suspend 102 bf(13) ^[[252z + 87 bf(14) ^[[253z keypad - 86 bf(15) ^[[254z keypad Other Volume/Contrast decrease 129 Volume/Contrast increase 128 NumLock 83 shiftkeys+numlock arrow up 82 string+uparrow ^[[A arrow left 81 string+downarrow ^[[B arrow right 79 string+rightarrow ^[[C arrow left 80 string+leftarrow ^[[D Del 76 '\177' Ctrl left 224 shiftkeys+leftctrl Alt 226 shiftkeys+alt Meta right 231 buckybits+metabit Meta left 227 buckybits+metabit Compose 101 0x309 AltGr 230 shiftkeys+altgraph Esc 41 ^[ Tab 43 '\t' CapsLock 57 shiftkeys+capslock Shift left 225 shiftkeys+leftshift Shift right 229 shiftkeys+rightshift Enter 40 '\r' Backspace 42 '\b'

Resources