Logitech 350 Media keys in Linux

In my previous post I talked about my new keyboard and how I hated the software that came with it. I also smugly commented that Linux would let me do whatever I wanted with this keyboard. Well, I was right, and everything worked fairly well except for two minor problems.

First, it turns out that Logitech keyboards don't all assign the same key code to keys with the same icon on the keyboard; that is, a key with a picture of a home (i.e. your browser's home page) might be scancode 178 on one keyboard (this guy's, for example) but is scancode 130 on my keyboard. The only reason I can imagine that Logitech would do this is to drive people crazy and make them reliant on the Logitech software. Luckily the X.org folks have made lists of known keyboard layouts and put them into a configuration program so you can just pick your layout. Unfortunately for me, my layout wasn't listed so I had to pick a few different Logitech keyboard layouts until I found one that matched mine. I chose the layout from KDE's control center, which you can see in the screenshot below.
The second problem was that the closest matching layout had bugs. First, the key with the calculator icon was tagged as "XF86VendorHome", whatever that means. It should have been "XF86Calculator"; however this is more of a cosmetic problem. More vexing is the flaw in the xkeyboard definition file which tags two keycodes with XF86AudioRaiseVolume which effectively stops this key from working. My workaround was to modify an existing layout so that it worked with all my keys and only my keys. Now I can choose this layout in KDE's keyboard config center and then, also using KDE's config center, assign actions to hotkeys.

In order to fix the bug I had to edit the /usr/share/X11/xkb/symbols/inet file. In this file was a layout definition that is used as the base definition for Logitech keyboards. I snipped out the boring parts, here are the three lines that were wrong:
xkb_symbols "logitech_base" {

key <i21> { [ XF86VendorHome ] };
key <i2f> { [ XF86AudioRaiseVolume ] };
key <i30> { [ XF86AudioRaiseVolume ] };

I made a new definition, with a new name, that contains keycodes for the 8 extra keys on this keyboard:
xkb_symbols "logitech_350" {

key <i01> { [ XF86AudioMedia ] };
key <i02> { [ XF86WWW ] };
key <i20> { [ XF86AudioMute ] };
key <i21> { [ XF86Calculator ] };
key <i22> { [ XF86AudioPlay, XF86AudioPause ] };
key <i2e> { [ XF86AudioLowerVolume ] };
key <i30> { [ XF86AudioRaiseVolume ] };
key <i32> { [ XF86HomePage ] };
key <i6c> { [ XF86Mail ] };
key <i6d> { [ XF86AudioMedia ] };

The reason I made a new definition was to make sure I didn't break anything else. Since I'm not 100% sure how to create a whole new definition from scratch, I just modified the Logitech Ultrix definition, which was just an import of the base definition:
partial alphanumeric_keys
xkb_symbols "logiultrax" {
include "inet(logitech_base)"

partial alphanumeric_keys
xkb_symbols "logiultrax" {
include "inet(logitech_350)"

This was quick and easy. Once I made the change to this file I simply logged out, logged back in, and the new keys worked as advertised.

Making something interesting happen when the keys were pressed was trivial once the bindings worked. To control the sound volume I set the key bindings in KMix, KDE's volume applet. To launch programs when I press the application starters I used the KDE control center's keyboard shortcuts page; just pick an action or program and assign any key combination to it. In the screenshot you can see Firefox and KMail have their special keys mapped.
The last detail was making XMMS play and pause when the play/pause key was hit. KDE once again came to the rescue. KDE 3.5 has a complex "Input Actions" framework that lets you assign arbitrary actions to fairly arbitrary input sequences. This can be used to create your own mouse gestures, or assign macros to keys. In my case I opted to assign a command to a key; the command is "xmms -t". This command starts XMMS if it's not running, and toggles the playing of music. If music is playing, it pauses. If music is not playing, it plays. With this final bit in place all 8 keys were working. And in the end I did bind the calculator key to kcalc, but that's only because I hadn't installed any games since upgrading to Fedora 7 yet.

No comments: