Update 2004

This page is discontinued and remains here for reference. No updates will be made in the future.

Update July 2003

This patch is not being maintained anymore. It has proven too cumbersome to patch every X server SRPM of my favourite Linux distro. A colleague has found another way of getting the keyboard to work without touching the X server. It's still in the works. In case he releases it to the public I'll post a reference here. Anyway, the approach as described below still works, although the patches have to be adjusted slightly to match the current XFree release.

Using a Sun Type 6 USB keyboard on Linux systems

This page explains the steps to get a Sun Type 6 USB keyboard configured under Linux/XFree86 4.0.1 and 4.0.3 The work is based on Andy Isaacson's start as described on his web page. Many thanks to him for this, it saved me a lot of work. Although these guidelines are sometimes specific to my hardware, people with other (even non-USB) fancy (aka "internet-") keyboards should get an idea how to do it (see section "Some Background" below).

As a side note, there's an alternative for doing all this (I didn't try): the funky package provides a kernel daemon and a kernel patch to get function keys recognized under XFree. I didn't pursue this because kernel patches have the habit of aging quite fast and I wanted to have a long term solution (although I have to admit that patching X isn't that much better :-).

Overview:

You need ...
  1. ... a Sun Type 6 USB keyboard.
  2. ... a USB capable Linux kernel.
  3. ... to patch the Xserver to recognize additional keycodes.
  4. ... to configure XKB to match the keyboard.
  5. ... to configure your window manager to make use of the additional key events. (not described here)

Getting a keyboard

The Sun Type 6 USB keyboard (part number possibly 320-1273, 320-1275, or else) is a USB keyboard with the same key layout as the much-loved Sun Type 5 UNIX keyboard, but with the added advantage of having a USB plug which is supported by most PCs nowadays (or Mac, for that matter). Unfortunately, pressing the keys feels much more PC-like compared to the old Type5, but even the standard Sun Type 6 keyboards (no USB) feel the same. :-(

Part number 320-1275 is in Sun's Sun Ray 1 Spare Parts list. However, it's not on the store.sun.com web site. National keyboards have different part no's, of course.

Making a USB keyboard work with Linux

First, you need a USB capable kernel.

The USB support in 2.2 kernels is mostly non-existent, but you can use the backport patch from pre-2.4. It available from Suse's page. I'm running this with 2.2.16. Andy installed 2.3.99-pre3, as that was the most recent version available at the time he installed. His .config is available.

Update Apr 2001: I'm running 2.2.18 now and was told that kernels from then on include the backport of the 2.4 USB driver. No further patching should be necessary. 2.4.x should work anyway.

The backport patch works OK. FYI, here's the list of currently installed modules on my working system:

$ /sbin/lsmod 
Module                  Size  Used by
keybdev                 1736   0 (unused)
hid                    11168   0 (unused)
input                   2940   0 [keybdev hid]
nfs                    78036   3 (autoclean)
usb-uhci               21320   0 (unused)
usbcore                45704   0 [hid usb-uhci]
autofs                  9356   4 (autoclean)
lockd                  37672   1 (autoclean) [nfs]
sunrpc                 54948   1 (autoclean) [nfs lockd]
3c59x                  19268   1 (autoclean)
es1371                 27268   0
soundcore               2628   4 [es1371]
The standard PC-subset of your keyboard should work now if your BIOS is recent. In console mode, you can get the scancodes the keyboard sends to the system on key press using the command showkey -s. Note that a key press generates two events, the press and the release. The scancode for the latter is the first increased by 0x80. Some scancodes consist of more than one byte. All these scancodes are being mapped onto "keycodes" (only one byte). They describe the key on the keyboard that was pressed. One or a combination of them (think of SHIFT) may yield finally a "keysym", which is a actual character. The mapping from scancodes to keycodes can be viewed with getkeycodes, being changed with setkeycodes (beware: this is broken on RedHat 6.2; you need to install a newer version of these two). Finally, you use loadkeys to map keycodes to keysyms. If you're interested, this page has a detailed description of how it works.

Using these tools it's not too difficult to get all fancy keyboards to work on the console, whether they're USB or not.

How to set up XFree86

Now to the difficult part. XFree86 is independent of the above mechanism. Note that the terms keycode and keysym under X refer to a different mechanism and therefore to different values compared to the previously mentioned kernel mapping table (which is only used for console mode).

Some Background

You still need a USB capable kernel and it's probably still a good idea first to set up the keyboard in console mode to verify that it works.

The translation of scancodes to X keycodes is hard wired into the X server and there's no mechanism like setkeycodes for the user to change it. The way it normally works is this: the X server receives a scancode from the kernel. It maps them onto X keycodes which are sent to the XKB mechanism. XKB (among other things) maps these keycodes to X keysyms that are visible by applications. (Note: X keycodes and keysyms can be observed with xev, the scancodes are not visible under X).

The problem is that the X server's scancode->keycode mapping deals with a standard PC keyboard. If you have additional keys (like on the Type 6 keyboard, or any new internet keyboard), the result of this mapping may yield arbitrary values for additional keys (the "normal" subset works fine). This is bad in case you have a conflict: with my Type 6 keyboard, two different scancodes are being mapped on the same keycode (e.g., Insert (0xe0 0x52) and SunFront (0x62) are both mapped onto keycode 106); they can't be distinguished anymore by XKB. If we didn't have a conflict, all we'd need to do is to modify XKB to make sense (i.e. assign a sensible keysym) of the additional keycodes. But with the conflict, that's not enough - XKB cannot know whether Insert of SunFront have been pressed.

So what I did was to change the scancode->keycode mapping of X to remap the scancodes of our additional keys onto unused keycodes that can then be unambiguously recognized by XKB. Details here.

I hope the XFree people will change this in the future and make the scancode->keycode mapping customizable, or even better, base it on the kernel table. So far, the have declined to do it.

Therefore, setting up the keyboard under XFree requires two steps:

  1. Change the hardwired scancode translation in xc/programs/Xserver/hw/xfree86/common/xf86Events.c so that there are no conflicts.
  2. Use the X keyboard extension (XKB) mechanism to configure the keycodes, geometry and keysyms. You should verify the events with xev.
Once this has been done, xev and your window manager recognize your new keys, and you can configure them.

Patching the X Server

The following has been done with XFree86 4.0.1 under RedHat 6.2. Older versions of X will require some changes.

Install XFree 4.0.1 from source. Make sure it's running OK. Then go to (xf86 src root)/xc/programs/Xserver/hw/xfree86/common/ and patch xf86Events.c using this xf86Events.diff. I haven't yet tried XFree86 4.0.3, but Edward O'Connor has put up a page where he presents an updated patch for 4.0.3's xf86Events.c. With his permission, I'll repeat the xf86Events.diff for XFree 4.0.3.

This diff is specific to the Sun Type6 keyboard; it does not affect the standard MF2 keys, but for other keyboards with special keys you'll have to change it. Go to (xf86 src root)/xc and do another make; make install.

Note: this X server is restricted to "normal" and Type 6 keyboards. With the current mechanism, it is impossible to have an X server supporting all modern "internet keyboards" at the same time.

Configuring XKB

Now that the X Server sends out unique keycodes for each key, we have to map the new ones onto keysyms ( think of them as "characters" or "actions").

You'll need the new keycodes and other configs for the Type6 keyboard. The following diff is mostly the work of Andy Isaacson, with only few changes for my setup. Apply it in (xf86 root)/lib/X11/xkb: xkb.diff. I was told that the patch doesn't apply out of the box on XFree86 4.0.2 and 4.0.3 because the files have changed slightly, but it should be quite simple to apply the patches by hand. If I have time I'll put up an updated diff for 4.0.3 (don't hold your breath).

All that's left now is to change /etc/X11/XF86Config:

Section "Keyboard"
    Protocol    "Standard"

    XkbModel   "sun_type6_usb"
    XkbLayout  "us(sun_type6_usb)"
    XkbSymbols "us(sun_type6_usb)"
EndSection
If you have a non-US Type 6 keyboard, you'll most likely only have to edit the XKB patch (-> no modification of the server patch) to reflect your different layout and keysyms. A collegue of mine uses a German layout and only had to edit the XKB defs. (it's not perfect - that's why it's not included here ;-)

... and now?

If you've come this far, the rest is simple. Configure your window manager to map desired functions on the new keys. I use sawfish which has all the functions I need (including raise-or-lower for the front key and execute commands for the audio volume keys).

Links

How to get older Type4/Type5 Sun keyboards connected to a PC: EZ-HID Project.

Nils Ellmenreich, Aug 2000, last update: 2004