scancodes & keycodes
In general when someone says this they mean that the function labeled on a key does not match what "code" that key is sending to the Linux kernel when it's pressed. You can think of it as the key is labeled Home but the kernel is being sent the "code" for the Ctrl key.
At a much lower level part of what's really going on is that each key is assigned a scancode.
excerpt from scancode wikipedia page
A scancode (or scan code) is the data that most computer keyboards
send to a computer to report which keys have been pressed. A number,
or sequence of numbers, is assigned to each key on the keyboard.
These scancodes get mapped into keycodes by the Linux kernel. It's these keycodes which are usually communicated to the applications. Here's another scancode resource if you'd like further details.
NOTE: this is an over simplification but I'm trying to just give you a general understanding of this layer. The key takeaway is that keys get pressed, scancodes are generated, Linux kernel sees these scancodes and emits keycodes.
setkeycodes
You can change the scancode keycode mapping using a tool setkeycodes
:
setkeycodes scancode keycode ...
The setkeycodes command reads its arguments two at a time, each
pair of arguments consisting of a scancode (given in hexadecimal) and a
keycode (given in decimal). For each such pair, it tells the kernel
keyboard driver to map the specified scancode to the specified keycode.
The keycode mapping is kept in keymap files. On my Fedora system my U.S. keymap file was located here, /lib/kbd/keymaps/i386/qwerty/us.map.gz
. I found it by sleuthing a bit with this command:
$ locate map.gz|grep us
/lib/kbd/keymaps/amiga/amiga-us.map.gz
/lib/kbd/keymaps/atari/atari-us.map.gz
/lib/kbd/keymaps/i386/qwerty/br-latin1-us.map.gz
/lib/kbd/keymaps/i386/qwerty/is-latin1-us.map.gz
/lib/kbd/keymaps/i386/qwerty/us-acentos.map.gz
/lib/kbd/keymaps/i386/qwerty/us.map.gz
/lib/kbd/keymaps/i386/qwertz/cz-us-qwertz.map.gz
/lib/kbd/keymaps/mac/all/mac-us.map.gz
/lib/kbd/keymaps/sun/sunt5-cz-us.map.gz
/lib/kbd/keymaps/sun/sunt5-us-cz.map.gz
Notice these files are compressed (.gz) so you have to either unzip them (don't bother) or use zcat
or zless
to look through them:
$ zless /lib/kbd/keymaps/i386/qwerty/us.map.gz
# us.map
keymaps 0-2,4-6,8-9,12
alt_is_meta
include "qwerty-layout"
include "linux-with-alt-and-altgr"
include "compose.latin1"
include "euro1.map"
strings as usual
keycode 1 = Escape
keycode 2 = one exclam
keycode 3 = two at at nul nul
keycode 4 = three numbersign
control keycode 4 = Escape
keycode 5 = four dollar dollar Control_backslash
keycode 6 = five percent
...
...
keycode 97 = Control
So if you wanted to change the "Control" key (keycode 97) and set it to the scancode for the "Left Control" key, (scancode 0x1d 0x9d), you'd use the following:
$ setkeycodes 1d9d 97 &
showkey
You can also see what keycode a key is mapped to using the command showkey
:
$ sudo showkey -a
Press any keys - Ctrl-D will terminate this program
1 49 0061 0x31
2 50 0062 0x32
3 51 0063 0x33
a 97 0141 0x61
b 98 0142 0x62
c 99 0143 0x63
^[OH 27 0033 0x1b
79 0117 0x4f
72 0110 0x48
^D 4 0004 0x04
The "^[OH" is me pressing my HOME key.
NOTE1: When in ascii' dump mode (
showkey -a`), showkey prints to the standard output the decimal, octal, and hexadecimal value(s) of the key pressed, according to the present keymap.