Here are some notes on assigning functions to those special keys that come on so many keyboards. My Gateway SK-9920 has 12 of these hotkeys: volume up, down, and mute; play, stop, next, and last track; internet, help, mail, shopping cart (?), and back (presumably). I don't even know what the creators of this keyboard envisioned for the "shopping cart" key. Often these keys aren't recognized out-of-the-box in Windows, much less in Linux.

Like usual, there are almost certainly specific GNOME or KDE tools to accomplish this goal. Since I'm not running those, however, I'll stick to tools available in almost any X.Org environment (I happen to be using Ratpoison).

First, some terminology. A scancode is the lowest level of identification for a key. If your key doesn't have a scancode, you're out of luck - the kernel doesn't recognize the key at all. A keycode is the next level of identification. If your key's scancode is identified with a keycode, then there's just one more step to make it do what you want. The last level of identification is a symbol. A scancode is mapped to a keycode, which is mapped to a symbol (for example, the letter "e" or "Caps Lock").

Keycodes

Starting out, none of my hotkeys were mapped to symbols, some were mapped to keycodes, and some only had scancodes (thankfully there were no completely "dead" keys). You can check if a key has a keycode by using xbindkeys. In a terminal (in X - not a console) type

xbindkeys -k

followed by the key you want to check. Here's an example of the output from my "Back" hotkey (before I bound it using xbindkeys, but after I assigned a keycode to the scancode, as described at the end of this post):

james@tv:~$ xbindkeys -k
Press combination of keys or/and click under the window.
You can use one of the two lines after "NoCommand"
in $HOME/.xbindkeysrc to bind a key.
"(Scheme function)"
m:0x10 + c:211
Mod2 + NoSymbol

Binding keycodes to actions

Using the output from xbindkeys -k, it's easy to bind a key to an action. This will be configured in the ~/.xbindkeysrc file (you may need to create it). It will take effect when you run xbindkeys. You'll probably want to call it in your ~/.xinitrc file. Here's an example of the format from my .xbindkeysrc:

It's a pretty simple format. Obviously the "#" precedes a comment (and is optional, but recommended). The next line is the command you want the hotkey to run (surrounded by quotes). You'll recognize the final line from the output of xbindkeys -k. I'm not sure if you can use either output line (or both) but mine works fine with just the first line following the "(Scheme function)" line.

That's all there is to it... unless your key does not have a keycode.

Mapping scancodes to keycodes

If xbindkeys -k does not recognize your key, it's probably not associated with a keycode. You can check if the key has a scancode (in other words, if the kernel recognizes the key) by pressing the key and then checking dmesg to see if the key was mentioned. Here's an example of what it will look like (from pushing my "Back" hotkey, before I assigned it to a keycode):

If you get similar output, you're key has a scancode (and is not mapped to a keycode). You can use setkeycodes to assign a keycode to the key. Before doing this, however, you're going to want to make sure that you don't assign it to a keycode that's already in use. You can find this out by looking at your keymap.

You can see that some keycodes are not being used (89-95, for example), so those are safe to use. (By the way, I've heard that you're supposed to pick a keycode between 1-127, but I don't know why, or what happens if you don't - I've never used one outside of that range).

You can then assign a scancode to one of these unused keycodes using setkeycodes (as root).

setkeycodes 0x83 89

The above code assigns the scancode from my "Back" hotkey to the unused keycode "89". Once that's been done, you can use xbindkeys -k (as described above) to get the correct identifier to bind the key using xbindkeys.

Assuming you want to use this binding after you reboot, you'll want to add the setkeycodes command to /etc/rc.local. Here's an example of mine:

james@tv:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
## James added to map the "back", "shopping cart", and "?" keys on Gateway keyboard
setkeycodes 0x83 89 &
setkeycodes 0x81 90 &
setkeycodes 0x82 91 &
exit 0

Followed your guide to config my laptop’s multimedia keys (vol+,vol- and mute) in my #! (debian crunchbang distro). But something really odd happened. First None of them worked at all, then following your guide managed to map Mute button (those are touch buttons by the way), yet Vol+ and Vol- were’nt working.

In fact “xbindkeys” won’t even recognize them, suddenlly after trying to find out why they were not working (couple of hours) they suddenlly start working … I didn’t do anything.