Architecture
Size: 5878
Comment: edit 'kernel keyboard mapping' to point developers more directly at the process of deploying fixes
|
Size: 7286
Comment: port over pitti's comments from the Troubleshooting page
|
Deletions are marked like this. | Additions are marked like this. |
Line 38: | Line 38: |
==== hal-info key maps ==== If the steps above revealed that the kernel does not know the key symbol for a particular key (or assigns the wrong symbol), the key can be added/changed in hal-info's keymaps (`/usr/share/hal/fdi/information/10freedesktop/30-keymap-*`). These have model-specific (`system.hardware.vendor` and `system.hardware.product`) scan code → key symbol mappings. hal reads those FDI files and pokes them into the kernel with the `EVIOCSKEYCODE` ioctl. ==== Key codes ==== `input-events` outputs a "code/value" pair, which needs to be changed into a hex number which hal/the kernel understand. The meaning of "code" is unknown as of now (it is usually "4"). Values below 128 are put into hal-info as they are (just converted to hex), values above 128 must be converted: hal_value = hex(value - 128 + 0xE0000) Examples: || ''value'' || ''hal-info representation'' || || 1 || 01 || || 16 || 10 || || 127 || 7f || || 128 || e0000 || || 129 || e0001 || ==== Key symbol names ==== The file `/usr/include/linux/input.h` defines available key names. To convert this into a list of symbols which are valid to put into `hal-info`, use: {{{ awk '/^#define.*KEY_/ { if ($2 != "KEY_MAX") { print substr($2, 5) } }' /usr/include/linux/input.h }}} Case is ignored in hal-info's key names, but by convention you should use lower-case names. |
NOTE: This document is a work in progress. ACPI is a complex subsystem and impossible for any one person to fully understand. Please take a few minutes to improve this document with the bits you know!
Current architecture |
Target architecture |
Here is the bird's-eye view of how key mapping works: The kernel recognizes the key and establishes a raw scancode and maps it to an arbitrary kernel keycode (e.g. e06d -> 120). Xorg reads the kernel's keycode table, and generates it's own list of X keycodes (e.g. 120 -> 136). X then maps each X keycode to a keysym (e.g. 136 -> XF86AudioMedia). Finally, the window manager maps the keysym to a desired window manager shortcut action or an application command (e.g. XF86AudioMedia -> rhythmbox).
Part A: Kernel keyboard mapping
All acpi events associated with keys are intended to be translated to keycodes in the kernel. MatthewGarrett is actively pursuing this in kernel upstream:
If a key's scancode is unknown to the kernel's keyboard mapping layer, this will typically result in a kernel log message when pressed. For instance, hitting the 'Media' key on a Dell Inspiron, we might see in dmesg output:
atkbd.c: Unknown key pressed (translated set 2, code ... on isa0060/serio0). atkbd.c: Use 'setkeycodes e06d <keycode>' to make it known.
In the above, e06d is what we're looking for.
Generally, the keys will already be mapped but may be mapped to an incorrect keycode. In this case, use showkey -s from the console to see the raw scancodes, or showkey -k to see the keycodes. This will give output for Media on a Dell Inspiron 1505N like:
0x9c 0x00 0x80 0xe2 0x80 0x81 0xe2
Once the correct keymapping has been determined, this is configured either by setting a default in the per-platform hotkey kernel driver, or by overriding the kernel keymap using an fdi file in the hal-info package. You shuold not add any keymappings to the obsolete hotkey-setup package.
hal-info key maps
If the steps above revealed that the kernel does not know the key symbol for a particular key (or assigns the wrong symbol), the key can be added/changed in hal-info's keymaps (/usr/share/hal/fdi/information/10freedesktop/30-keymap-*). These have model-specific (system.hardware.vendor and system.hardware.product) scan code → key symbol mappings.
hal reads those FDI files and pokes them into the kernel with the EVIOCSKEYCODE ioctl.
Key codes
input-events outputs a "code/value" pair, which needs to be changed into a hex number which hal/the kernel understand. The meaning of "code" is unknown as of now (it is usually "4"). Values below 128 are put into hal-info as they are (just converted to hex), values above 128 must be converted:
- hal_value = hex(value - 128 + 0xE0000)
Examples:
value
hal-info representation
1
01
16
10
127
7f
128
e0000
129
e0001
Key symbol names
The file /usr/include/linux/input.h defines available key names. To convert this into a list of symbols which are valid to put into hal-info, use:
awk '/^#define.*KEY_/ { if ($2 != "KEY_MAX") { print substr($2, 5) } }' /usr/include/linux/input.h
Case is ignored in hal-info's key names, but by convention you should use lower-case names.
In some cases, your keys may be generating ACPI events instead of standard keycodes. To check this, run sudo tail -f /var/log/acpid and then hit the key. You should see something like:
received event "ibm/hotkey HKEY 00000080 00001010"
The interesting bits here is the part between the quotes. [What do we do with this info?]
On IBM/Lenovo laptops, some keys are only accessible via /dev/nvram.
Identify the kernel keycode to use by referring to /usr/share/hotkey-setup/key-constants. For example, browsing through the file we find KEY_MEDIA:
... KEY_BRIGHTNESSDOWN=224 KEY_BRIGHTNESSUP=225 KEY_MEDIA=226 KEY_SWITCHVIDEOMODE=227 KEY_KBDILLUMTOGGLE=228 ...
These codes are defined in /usr/include/linux/input.h.
Part B: Hal
Set up the kernel keycode mapping for the keyboard layout. These can be set up via HAL quirks. See Keymap Quirk Debugger for details. Essentially, you need to add or update a section in the appropriate FDI file in /usr/share/hal/fdi/information/10freedesktop/, such as 30-keymap-dell.fdi for a Dell Inspiron 1505N:
... <!-- Dell Inspiron 9400, 640m, E1505/6400 --> <match key="/org/freedesktop/Hal/devices/computer:system.hardware.product" prefix_outof="MP061;MXC061;MM061"> <append key="input.keymap.data" type="strlist">e005:brightnessdown</append> <!-- Fn+Down arrow Brightness Down --> <append key="input.keymap.data" type="strlist">e006:brightnessup</append> <!-- Fn+Up arrow Brightness Up --> <append key="input.keymap.data" type="strlist">e007:battery</append> <!-- Fn+F3 battery icon --> <append key="input.keymap.data" type="strlist">e008:wlan</append> <!-- Fn+F2 Toggle WiFi --> <append key="input.keymap.data" type="strlist">e008:bluetooth</append> <!-- FIXME Bluetooth switch (same as wireless) --> <append key="input.keymap.data" type="strlist">e009:ejectclosecd</append> <!-- Fn+F10 Eject CD --> <append key="input.keymap.data" type="strlist">e00a:suspend</append> <!-- Fn+F1 hibernate --> <append key="input.keymap.data" type="strlist">e00b:switchvideomode</append> <!-- Fn+F8 CRT/LCD --> <append key="input.keymap.data" type="strlist">e012:media</append> <!-- MediaDirect button (house icon) --> <append key="info.capabilities" type="strlist">input.keymap</append> </match> ...
So for instance, to support the e06d code we found before, we'd create a new section like the above, substituting in e06d for e012 (and any other codes that need remapping), into a new product section.
Use lshal | grep system.hardware.product and lshal | grep system.hardware.vendor to determine the product name and vendor of your laptop.
To see if hal has picked up your keymaps, restart the hal daemon and use lshal | grep keymap, which gives output like:
info.callouts.add = {'hal-setup-keymap'} (string list) info.capabilities = {'input', 'input.keyboard', 'input.keypad', 'input.keys', 'input.keymap', 'button'} (string list) input.keymap.data = {'e005:brightnessdown', 'e006:brightnessup', 'e007:battery', 'e008:wlan', 'e008:bluetooth', 'e009:ejectclosecd', 'e00a:suspend', 'e00b:switchvideomode', 'e012:media'} (string list)
Part C: Gnome/KDE hotkey mapping
At this point, gnome-keybinding-properties should now be able to detect your key. Check this by setting it for "Launch help browser" for example.
Hotkeys/Architecture (last edited 2009-07-08 14:28:19 by pD9EB7542)