Difference between revisions of "Map scancodes to keycodes"

From ArchWiki
Jump to: navigation, search
({{ic}} templates, docs)
(Updating the Hardware Database Index: add accuracy flag)
 
(35 intermediate revisions by 15 users not shown)
Line 1: Line 1:
 
[[Category:Keyboards]]
 
[[Category:Keyboards]]
{{stub}}
+
[[ja:スキャンコードをキーコードにマップ]]
scancodes are the lowest identification numbers for a key, they are from the kernel and are not used by applications that's why we have to map them to keycodes which correspond to functions.
+
{{Note|This page assumes that you have read [[Extra keyboard keys]], which provides wider context to the problem.}}
  
''See [[Extra Keyboard Keys]] for more information.''
+
Mapping ''scancodes'' to ''keycodes'' is universal and not specific to Linux console or Xorg, which means that changes to this mapping will be effective in both.
  
There are three ways of mapping scancodes to keycodes:
+
There are two ways of mapping ''scancodes'' to ''keycodes'':
*Using [[udev]]
+
* Using [[udev]]
*Using the kernel tool {{ic|setkeycodes}}
+
* Using ''setkeycodes''
  
The preferred one is to use udev because it uses hardware information (which is a quite reliable source) to choose the keyboard model in a database. It means that if your keyboard model as been defined in the database your keys are recognized "out of the box" and can be seen by Xorg. That's why by expanding the database you are helping the linux community and maybe someday we won't have to care about scancodes.
+
The preferred method is to use ''udev'' because it uses hardware information (which is a quite reliable source) to choose the keyboard model in a database. It means that if your keyboard model has been found in the database, your keys are recognized ''out of the box''.
 +
 
 +
== Identifying scancodes ==
 +
 
 +
You need to know the ''scancodes'' of keys you wish to remap. See [[Extra keyboard keys#Scancodes]] for details.
  
 
== Using udev ==
 
== Using udev ==
First, you need to create a keymap file that udev will recognise. Some examples can be found in {{ic|/lib/udev/keymaps/}}, and you should use one of these if it works for your keyboard model. Otherwise, you need to create one yourself. The format of each line in a keymap is '<scancode> <keycode>'. You can work out <scancode> (looks like 0xXX) using
 
# /lib/udev/keymap -i input/eventX
 
and pressing the relevant keys. Replace input/eventX with your keyboard device, which can be found by running
 
$ /lib/udev/findkeyboards
 
The choices for <keycode> are listed as KEY_<KEYCODE> in {{ic|/usr/include/linux/input.h}}, but you need to change these to lower case and remove the KEY_ prefix (for example, KEY_PROG3 corresponds to prog3). A sorted list is available [http://hal.freedesktop.org/quirk/quirk-keymap-list.txt here].
 
  
Once you have a keymap, you need to tell udev to use it. This can be done with a [[Udev#About udev rules|udev rule]]. Here is a simple example:
+
[[udev]] provides a builtin function called ''hwdb'' to maintain the hardware database index in {{ic|/etc/udev/hwdb.bin}}. The database is compiled from files with ''.hwdb'' extension located in directories {{ic|/usr/lib/udev/hwdb.d/}}, {{ic|/run/udev/hwdb.d/}} and {{ic|/etc/udev/hwdb.d/}}. The default ''scancodes-to-keycodes'' mapping file is {{ic|/usr/lib/udev/hwdb.d/60-keyboard.hwdb}}. See {{ic|man udev}} for details.
SUBSYSTEM=="input", ATTRS{name}=="AT Translated Set 2 keyboard", RUN+="/lib/udev/keymap input/$name /path/to/keymap"
+
 
If you place the keymap file in {{ic|/lib/udev/keymaps/}}, you can omit the full path. Now the keymap will be active the next time you restart. You can run the following command to activate it immediately:
+
{{Note|From systemd 220 the udev ABI changed. Users using custom udev hwdb rules should update them according to the new ABI}}
  # /lib/udev/keymap input/eventX /path/to/keymap
+
 
 +
The ''.hwdb'' file can contain multiple blocks of mappings for different keyboards, or one block can be applied to multiple keyboards. The {{ic|evdev:}} prefix is used to match a block against a hardware, the following hardware matches are supported:
 +
 
 +
* Generic input devices (also USB keyboards) identified by the usb kernel modalias: {{bc|evdev:input:b''<bus_id>''v''<vendor_id>''p''<product_id>''e''<version_id>''-''<modalias>''}} where {{ic|''<vendor_id>''}}, {{ic|''<product_id>''}} and {{ic|''<version_id>''}} are the 4-digit hex uppercase vendor, product and version IDs (you can find those by running the {{ic|lsusb}} command) and {{ic|''<modalias>''}}  is an arbitrary length input-modalias describing the device capabilities. {{ic|''<bus_id>''}} is the 4-digit hex bus id and should be 0003 for usb devices. The possible {{ic|''<bus_id>''}} values are defined in {{ic| /usr/include/linux/input.h}} (you can use the following command to get a list {{ic| awk '/BUS_/ {print $2, $3}' /usr/include/linux/input.h}}).
 +
* AT keyboard DMI data matches: {{bc|evdev:atkbd:dmi:bvn*:bvr*:bd*:svn''<vendor>'':pn''<product>'':pvr*}} where {{ic|''<vendor>''}} and {{ic|''<product>''}} are the firmware-provided strings exported by the kernel DMI modalias.
 +
* Input driver device name and DMI data match: {{bc|evdev:name:''<input device name>'':dmi:bvn*:bvr*:bd*:svn''<vendor>'':pn*}} where {{ic|''<input_device_name>''}} is the name device specified by the driver and {{ic|''<vendor>''}} is the firmware-provided string exported by the kernel DMI modalias.
 +
 
 +
The format of each line in the block body is {{ic|1=KEYBOARD_KEY_''<scancode>''=''<keycode>''}}. The value of {{ic|''<scancode>''}} is hexadecimal, but without the leading {{ic|0x}} (i.e. specify {{ic|a0}} instead of {{ic|0xa0}}), whereas the value of {{ic|''<keycode>''}} is the lower-case keycode name string as listed in {{ic|/usr/include/linux/input-event-codes.h}} (see the {{ic|KEY_''<KEYCODE>''}} variables), a sorted list is available at [http://hal.freedesktop.org/quirk/quirk-keymap-list.txt]. It is not possible to specify decimal value in {{ic|''<keycode>''}}.
 +
 
 +
=== Example for custom hwdb ===
 +
 
 +
The example hwdb file will match all AT keyboards:
 +
 
 +
{{hc|/etc/udev/hwdb.d/90-custom-keyboard.hwdb|<nowiki>
 +
evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*
 +
KEYBOARD_KEY_10=suspend
 +
KEYBOARD_KEY_a0=search
 +
</nowiki>}}
 +
 
 +
Here is an example of rebinding modifiers on a laptop and USB keyboard:
 +
 
 +
{{hc|/etc/udev/hwdb.d/10-my-modifiers.hwdb|<nowiki>
 +
evdev:input:b0003v05AFp8277* # was tested on Kensington Slim Type USB (with old ABI)
 +
KEYBOARD_KEY_70039=leftalt  # bind capslock to leftalt
 +
KEYBOARD_KEY_700e2=leftctrl # bind leftalt to leftctrl
 +
 
 +
evdev:atkbd:dmi:*            # built-in keyboard: match all AT keyboards for now
 +
KEYBOARD_KEY_3a=leftalt    # bind capslock to leftalt
 +
KEYBOARD_KEY_38=leftctrl    # bind leftalt to leftctrl
 +
</nowiki>}}
 +
 
 +
=== Updating the Hardware Database Index ===
 +
 
 +
After changing the configuration files, the hardware database index, {{ic|hwdb.bin}}, needs to be rebuilt.
 +
 
 +
* Update {{ic|hwdb.bin}} manually by running
 +
# udevadm hwdb --update
 +
 
 +
{{Accuracy|Don't edit in {{ic|/usr/lib/}}, use [[Systemd#Editing_provided_units|systemctl edit]].}}
 +
 
 +
* Update automatically on each reboot by commenting out {{ic|ConditionNeedsUpdate}} in {{ic|systemd-udev-hwdb-update.service}}.
 +
 
 +
{{hc|/usr/lib/systemd/system/systemd-udev-hwdb-update.service|<nowiki>
 +
#  This file is part of systemd.
 +
.
 +
.
 +
#ConditionNeedsUpdate=/etc
 +
.
 +
.
 +
</nowiki>}}
 +
 
 +
After {{ic|systemd-udev-hwdb-update.service}} finished loading {{ic|systemd-udev-trigger.service}} will reload the changes from
 +
{{ic|hwdb.bin}}.
 +
 
 +
* Automatically after [[Systemd]] upgrade.
 +
 
 +
On each upgrade of [[Systemd]], the installation script rebuilds {{ic|hwdb.bin}} by running {{ic|# udevadm hwdb --update}} so we do not need to care about it.
 +
 
 +
=== Reloading the Hardware Database Index ===
 +
 
 +
The kernel loads {{ic|hwdb.bin}} as part of the boot process, rebooting the system will promise the loading of the updated {{ic|hwdb.bin}}.
 +
 
 +
With {{ic|udevadm}} it is possible to load new key mapping from the updated {{ic|hwdb.bin}} by running
 +
# udevadm trigger
 +
Be aware that with {{ic|udevadm}} only added or changed key mapping are loaded so if we delete a mapping from the config file, rebuild {{ic|hwdb.bin}} and run {{ic|# udevadm trigger}} then the deleted mapping still kept by the kernel, at least until a reboot.
 +
 
 +
=== Querying the database ===
 +
 
 +
You can check that your configuration was loaded either by pressing keys, or by running {{ic|udevadm info}}. For the USB keyboard in the above example, this outputs the mapping we configured as follows:
 +
 
 +
  # udevadm info /dev/input/by-path/*-usb-*-kbd | grep KEYBOARD_KEY
 +
E: KEYBOARD_KEY_70039=leftalt
 +
E: KEYBOARD_KEY_700e2=leftctrl
 +
 
 +
== Using setkeycodes ==
 +
 
 +
''setkeycodes'' is a tool to load ''scancodes''-to-''keycodes'' mapping table into Linux kernel. Its usage is:
 +
 
 +
# setkeycodes ''scancode'' ''keycode'' ...
 +
 
 +
It is possible to specify multiple pairs at once. ''Scancodes'' are given in hexadecimal, ''keycodes'' in decimal.
  
For more information about keymaps, see {{ic|/usr/share/doc/udev/README.keymap.txt}}.
+
{{Note|Apparently ''setkeycodes'' does not work with USB keyboards (Linux 3.14.44-1-lts):
  
== Using the kernel tool <code>setkeycodes</code> ==
+
# setkeycodes 45 30    # bind NumLock (0x45) to KEY_A (30) on AT keyboard
''See the detailed article: [[setkeycodes]].''
+
(successful)
 +
# setkeycodes 70053 30  # bind NumLock (0x70053) to KEY_A (30) on USB keyboard
 +
KDSETKEYCODE: Invalid argument
 +
failed to set scancode 620d3 to keycode 31
 +
}}

Latest revision as of 16:13, 1 April 2016

Note: This page assumes that you have read Extra keyboard keys, which provides wider context to the problem.

Mapping scancodes to keycodes is universal and not specific to Linux console or Xorg, which means that changes to this mapping will be effective in both.

There are two ways of mapping scancodes to keycodes:

  • Using udev
  • Using setkeycodes

The preferred method is to use udev because it uses hardware information (which is a quite reliable source) to choose the keyboard model in a database. It means that if your keyboard model has been found in the database, your keys are recognized out of the box.

Identifying scancodes

You need to know the scancodes of keys you wish to remap. See Extra keyboard keys#Scancodes for details.

Using udev

udev provides a builtin function called hwdb to maintain the hardware database index in /etc/udev/hwdb.bin. The database is compiled from files with .hwdb extension located in directories /usr/lib/udev/hwdb.d/, /run/udev/hwdb.d/ and /etc/udev/hwdb.d/. The default scancodes-to-keycodes mapping file is /usr/lib/udev/hwdb.d/60-keyboard.hwdb. See man udev for details.

Note: From systemd 220 the udev ABI changed. Users using custom udev hwdb rules should update them according to the new ABI

The .hwdb file can contain multiple blocks of mappings for different keyboards, or one block can be applied to multiple keyboards. The evdev: prefix is used to match a block against a hardware, the following hardware matches are supported:

  • Generic input devices (also USB keyboards) identified by the usb kernel modalias:
    evdev:input:b<bus_id>v<vendor_id>p<product_id>e<version_id>-<modalias>
    where <vendor_id>, <product_id> and <version_id> are the 4-digit hex uppercase vendor, product and version IDs (you can find those by running the lsusb command) and <modalias> is an arbitrary length input-modalias describing the device capabilities. <bus_id> is the 4-digit hex bus id and should be 0003 for usb devices. The possible <bus_id> values are defined in /usr/include/linux/input.h (you can use the following command to get a list awk '/BUS_/ {print $2, $3}' /usr/include/linux/input.h).
  • AT keyboard DMI data matches:
    evdev:atkbd:dmi:bvn*:bvr*:bd*:svn<vendor>:pn<product>:pvr*
    where <vendor> and <product> are the firmware-provided strings exported by the kernel DMI modalias.
  • Input driver device name and DMI data match:
    evdev:name:<input device name>:dmi:bvn*:bvr*:bd*:svn<vendor>:pn*
    where <input_device_name> is the name device specified by the driver and <vendor> is the firmware-provided string exported by the kernel DMI modalias.

The format of each line in the block body is KEYBOARD_KEY_<scancode>=<keycode>. The value of <scancode> is hexadecimal, but without the leading 0x (i.e. specify a0 instead of 0xa0), whereas the value of <keycode> is the lower-case keycode name string as listed in /usr/include/linux/input-event-codes.h (see the KEY_<KEYCODE> variables), a sorted list is available at [1]. It is not possible to specify decimal value in <keycode>.

Example for custom hwdb

The example hwdb file will match all AT keyboards:

/etc/udev/hwdb.d/90-custom-keyboard.hwdb
evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*
 KEYBOARD_KEY_10=suspend
 KEYBOARD_KEY_a0=search

Here is an example of rebinding modifiers on a laptop and USB keyboard:

/etc/udev/hwdb.d/10-my-modifiers.hwdb
evdev:input:b0003v05AFp8277* # was tested on Kensington Slim Type USB (with old ABI)
 KEYBOARD_KEY_70039=leftalt  # bind capslock to leftalt
 KEYBOARD_KEY_700e2=leftctrl # bind leftalt to leftctrl

evdev:atkbd:dmi:*            # built-in keyboard: match all AT keyboards for now
 KEYBOARD_KEY_3a=leftalt     # bind capslock to leftalt
 KEYBOARD_KEY_38=leftctrl    # bind leftalt to leftctrl

Updating the Hardware Database Index

After changing the configuration files, the hardware database index, hwdb.bin, needs to be rebuilt.

  • Update hwdb.bin manually by running
# udevadm hwdb --update

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Don't edit in /usr/lib/, use systemctl edit. (Discuss in Talk:Map scancodes to keycodes#)
  • Update automatically on each reboot by commenting out ConditionNeedsUpdate in systemd-udev-hwdb-update.service.
/usr/lib/systemd/system/systemd-udev-hwdb-update.service
#  This file is part of systemd.
.
.
#ConditionNeedsUpdate=/etc
.
.

After systemd-udev-hwdb-update.service finished loading systemd-udev-trigger.service will reload the changes from hwdb.bin.

  • Automatically after Systemd upgrade.

On each upgrade of Systemd, the installation script rebuilds hwdb.bin by running # udevadm hwdb --update so we do not need to care about it.

Reloading the Hardware Database Index

The kernel loads hwdb.bin as part of the boot process, rebooting the system will promise the loading of the updated hwdb.bin.

With udevadm it is possible to load new key mapping from the updated hwdb.bin by running

# udevadm trigger

Be aware that with udevadm only added or changed key mapping are loaded so if we delete a mapping from the config file, rebuild hwdb.bin and run # udevadm trigger then the deleted mapping still kept by the kernel, at least until a reboot.

Querying the database

You can check that your configuration was loaded either by pressing keys, or by running udevadm info. For the USB keyboard in the above example, this outputs the mapping we configured as follows:

# udevadm info /dev/input/by-path/*-usb-*-kbd | grep KEYBOARD_KEY
E: KEYBOARD_KEY_70039=leftalt
E: KEYBOARD_KEY_700e2=leftctrl

Using setkeycodes

setkeycodes is a tool to load scancodes-to-keycodes mapping table into Linux kernel. Its usage is:

# setkeycodes scancode keycode ...

It is possible to specify multiple pairs at once. Scancodes are given in hexadecimal, keycodes in decimal.

Note: Apparently setkeycodes does not work with USB keyboards (Linux 3.14.44-1-lts):
# setkeycodes 45 30     # bind NumLock (0x45) to KEY_A (30) on AT keyboard
(successful)
# setkeycodes 70053 30  # bind NumLock (0x70053) to KEY_A (30) on USB keyboard
KDSETKEYCODE: Invalid argument
failed to set scancode 620d3 to keycode 31