First things first: the keycodes
The first problem of this keyboard is that it is not supported fully by the kernel. When in console, most keys are fine, but some of the special keys are unknown at the kernel level and are not translated in anything. This needs fixing before going further. Even though most people are fine using only X, X relies on the kernel translation of keycodes in key codes (note the space).
I did this by the trial-and-error method (once, twice), pressing the keys of my keyboard and waiting for the dreaded message to appear:
atkbd.c: Use 'setkeycodes e016' to make it known.
atkbd.c: Unknown key released (translated set 2, code 0x96 on isa0060/serio0).
When the kernel is taught (during boot time) about this translation, then X may use the keys (else nothing is passed at all to X). I did put in yellow the keys that were not recognised correctly and are after this script (put it in /etc/init.d, make a link in /etc/rcS.d/S47keymap-logitech (see the whole file as an attachment below):
setkeycodes e011 216;setkeycodes e012 212;setkeycodes e013 218
setkeycodes e014 221;setkeycodes e016 135;setkeycodes e03b 181
setkeycodes e03c 232;setkeycodes e03d 233;setkeycodes e03e 231
setkeycodes e03f 131;setkeycodes e040 182;setkeycodes e041 210
setkeycodes e042 234;setkeycodes e043 157;setkeycodes e044 235
setkeycodes e057 148;setkeycodes e058 149
There are other things I do in the attached script that simply echo <KeyName> when some media key is used in the console. Gadget, but I could do it. Please note that the function keys work correctly out of the box, as well as the Up and Down translations for the left side wheel; what was not working were the function keys when the "Lock Function" (topleft corner) was off, or the click of the left-side wheel (which I did bind to Paste).
How did I find the codes to put in there? The first time, I tested with random values. Then I found some interesting info in /usr/share/X11/xkb/keycodes/evdev that gave me codes predefined for evdev, which was a good thing. However:
<I222> = 222; // #define KEY_QUESTION 214
<I223> = 223; // #define KEY_EMAIL 215
<I224> = 224; // #define KEY_CHAT 216
<I225> = 225; // #define KEY_SEARCH 217
<I226> = 226; // #define KEY_CONNECT 218
<I227> = 227; // #define KEY_FINANCE 219
You see that for each line, there are two numbers; the second one is the good one, and is 8 less than the first one. However, on some lines, there is only one number, some substract 8 from it to get the correct keycode. If you choose these codes, the second step will be easier (mostly everything should work as is).
Let's teach something to XKB
XKB is the layer in X that cares about keyboards, modifiers, layouts. One of the problems you will meet is if you modify your files, the changes will not be kept between upgrades of xkb-data. For some reason, one of these files was marked as a conffile, the others are in /usr/share/X11/xkb. With the advent of evdev, the one marked as a conffile is not the right one to be modified any more anyway.
So the second thing was to make a script that patches these files, puts diversions into place, and allows to revert the changes. I give you the result as an attachment, the main concern being keeping a safe keyboard database (all modifications should be reversible with a simple command). So this is my file /etc/init.d/fixkeyboard (linked as /etc/rcS.d/S47fixkeyboard and /etc/rc{0,1,6}.d/K47fixkeyboard).
Warning: the attached script (below) is not LSB compliant (does not use the LSB functions to display its messages) and uses bash. I did not have time to do better; if someone cares enough about that, please send me a working copy!
How to include custom modifications to a keyboard
Now that we can patch our XKB system, let's go to work. Because I had done it earlier, I also have the patch for the base system (which means: no evdev used). I do not plan on using it, but hey, I have it. However, for the sake of simplicity, I will ignore those modifications.
The first thing is test what already works. Out of the box, most media keys were recognised (I chose a Logitech keyboard quite similar to this one), but some keys were still not working. Using xev to check the keycodes, I saw that keycodes were translated in symbols if they were defined in /usr/share/X11/xkb/symbols/inet, in the evdev section.
// Evdev Standardized Keycodes
partial alphanumeric_keys
xkb_symbols "evdev" {
key <MUTE> { [ XF86AudioMute ] };
key <VOL-> { [ XF86AudioLowerVolume ] };
key <VOL+> { [ XF86AudioRaiseVolume ] };
key <POWR> { [ XF86PowerOff ] };
key <STOP> { [ Cancel ] };
key <AGAI> { [ Redo ] };
key <PROP> { [ SunProps ] };
...
So almost nothing to change... except that some of these lines are commented out, and some of the keys matched the commented out lines.
key <I223> { [ XF86Mail ] };
// key <I224> { [ XF86Messenger ] }; // KEY_CHAT
key <I225> { [ XF86Search ] };
// key <I226> { [ XF86Go ] }; // KEY_CONNECT
key <I227> { [ XF86Finance ] };
That's a pity, because except for these two keys, everything would be fine. Somehow, one day, I will have to find out why these lines are commented out.
Anyway, I also have my personal french keyboard (special layout), so I had to patch. Since this fix for multimedia is less obtrusive, I will show how I did, it might help someone some day.
Now, I know what I have to do: add these two lines to the definitions of my keyboard.
I prefer not to change the usual models (if they were commented out, there might be a reason), so I created a special option that would enable these two keys.
I first copy /usr/share/X11/xkb to /usr/share/X11/xkb.orig and /usr/share/X11/xkb.mod. All my edits go in the mod directory, then I do a diff -d -x 'rules/x{free86,org}*' -x 'rules/base.xml' -ur ../xkb.orig/ . > /etc/X11/xkb/keyboard.patch and a cd /etc/X11/xkb; diff -u base.xml.orig base.xml > /etc/X11/xkb/xml.patch.
Remark that the complex diff is needed only if you are patching the base set of rules, which I will not do here anyway.
To add an option, the first thing is to edit the base and evdev rules sets.
I first added a logielite model to the list of models. Further down, I added support for my new symbols in the option sets:
...
! option = symbols
fixinet:logielite = +inet(logielite)
grp:shift_toggle = +group(shifts_toggle)
...
Now, this work has to be done in two other formats, and this for the two sets of rules (base and evdev). The second format is the index (for the applications that do not use libxklavier). For this tutorial, I will drop the base set of rules and do only the rules/evdev.lst file:
...
logicink Logitech Internet Navigator Keyboard
logielite Logitech Elite Keyboard
logiex110 Logitech Cordless Desktop EX110
...
esperanto:dvorak To the corresponding key in a Dvorak keyboard.
fixinet Adding fixes to the multimedia keyboards
fixinet:logielite To the Logitech Elite Keyboard
The third one is the XML file (the one that for the base set of rules is in /etc), evdev.xml:
--- ../xkb.orig/rules/evdev.xml 2009-04-14 11:00:25.000000000 +0200
+++ ./rules/evdev.xml 2009-04-20 12:51:46.000000000 +0200
@@ -715,6 +715,13 @@
</model>
<model>
<configItem>
+ <name>logielite</name>
+ <description>Logitech Elite Keyboard</description>
+ <vendor>Logitech</vendor>
+ </configItem>
+ </model>
+ <model>
+ <configItem>
<name>logiex110</name>
<description>Logitech Cordless Desktop EX110</description>
<vendor>Logitech</vendor>
@@ -4898,5 +4905,17 @@
</configItem>
</option>
</group>
+ <group allowMultipleSelection="true">
+ <configItem>
+ <name>fixinet</name>
+ <description>Adding fixes to the multimedia keyboards</description>
+ </configItem>
+ <option>
+ <configItem>
+ <name>fixinet:logielite</name>
+ <description>To the Logitech Elite Keyboard.</description>
+ </configItem>
+ </option>
+ </group>
</optionList>
</xkbConfigRegistry>
Most everything is ready. Now, we just have to edit the symbols files (I added a small snippet to the symbols/inet):
// Logitech Elite Keyboard
partial alphanumeric_keys
xkb_symbols "logielite" {
key <I224> { [ XF86Messenger ] };
key <I226> { [ XF86iTouch ] };
};
Of course, one should also modify the symbols.dir listing (in the main directory):
--- ../xkb.orig/symbols.dir 2009-04-14 11:00:25.000000000 +0200
+++ symbols.dir 2009-04-20 12:58:20.000000000 +0200
@@ -684,6 +684,7 @@
--p----- a------- inet(logiaccess)
--p----- a------- inet(logicda)
--p----- a------- inet(logicink)
+--p----- a------- inet(logielite)
--p----- a------- inet(logiex110)
--p----- a------- inet(logiinkse)
--p----- a------- inet(logiinkseusb)
This done, I generate the patch (diff -ur ../xkb.orig ./ > /etc/X11/xkb/keyboard.patch), launches /etc/init.d/fixkeyboard start, and I give you the patched files. Be aware that they include my personal French Keyboard (see attached file keyboard.patch).
How to set this up?
Now that the modifications are made, how to apply them? The simplest way is to enter your configuration is /etc/default/console-setup:
# The following variables describe your keyboard and can have the same
# values as the XkbModel, XkbLayout, XkbVariant and XkbOptions options
# in /etc/X11/xorg.conf.
XKBMODEL="logielite"
XKBLAYOUT="fr"
XKBVARIANT="complete" # or "latin9"
XKBOPTIONS="compose:menu,fixinet:logielite"
Relaunch console-setup, restart X, everything should work fine.
The other way is to use your desktop environment settings: for Gnome, System->Preferences->Keyboard->Layout->Options->Adding fixes to the multimedia keyboards->To the Logitech Elite Keyboard.
There are also some ways to not use console-setup and juste use hal.
The only thing left is to bind these keys (the extra ones, at least) to something useful. This can be done with compiz or Metacity.