Map scancodes to keycodes
該頁面假定您已閱讀 Extra keyboard keys ,它提供了更多的內容。
將「掃描碼」映射為「鍵位碼」的動作,要比 Xorg 和 Linux 控制台更接近底層,所以對這個映射的更改在兩者中均有效。
將「掃描碼」映射到「鍵位碼」方式有兩種:
- 使用 udev
- Using setkeycodes(8)
首選方法是使用 「udev」,因為它使用硬件信息(這是一個非常可靠的來源)來選擇數據庫中的鍵盤型號。如果能在數據庫中找到鍵盤型號,則可以「開箱即用」地識別您的按鍵。
確定掃描碼[編輯 | 編輯原始碼]
您需要知道要重新映射的鍵的「掃描代碼」。詳情請見Keyboard input#Identifying scancodes。
使用 udev[編輯 | 編輯原始碼]
udev提供了一個稱為"hwdb"的內置函數,用於維護 /etc/udev/hwdb.bin
中的硬件數據庫索引。 數據庫是從位於/usr/lib/udev/hwdb.d/
、 /run/udev/hwdb.d/
和 /etc/udev/hwdb.d/
目錄中的擴展名為.hwdb的文件編譯而成的。 默認的 "掃描碼到鍵碼" 映射文件是 /usr/lib/udev/hwdb.d/60-keyboard.hwdb
。 有關詳細信息,請參見udev(7) 。
.hwdb 文件可以包含不同鍵盤的多個映射塊,也可以將一個塊應用於多個鍵盤。 evdev:
前綴用於將塊與硬件進行匹配,支持以下硬件匹配:
- USB內核模式標識的通用輸入設備(也包括USB鍵盤):
evdev:input:b<bus_id>v<vendor_id>p<product_id>e<version_id>-<modalias>
其中 <vendor_id>
, <product_id>
和 <version_id>
是 4位十六進制大寫(不夠4位在前面補0)的供應商,產品和版本ID ( 你可以通過運行lsusb
命令來得到它們), <modalias>
是描述設備功能的任意長度的輸入模態 (input-modalias). <bus_id>
是4位數的十六進制總線ID,對於USB設備,應為0003。<bus_id>
可能的值在 /usr/include/linux/input.h
中定義 (你可以運行 awk '/BUS_/ {print $2, $3}' /usr/include/linux/input.h
得到一個列表).
evtest
或者 cat /proc/bus/input/devices
可以一次性得到<bus_id>、<vendor_id>、 <product_id> 和 <version_id>
很多時候可以不用那麼精確,就可以用 *
來作為通配符。
- AT鍵盤DMI數據匹配:
evdev:atkbd:dmi:bvn*:bvr*:bd*:svn<vendor>:pn<product>:pvr*
其中 <vendor>
和 <product>
是由內核 DMI Modalias 導出的固件提供的字符串。
- 輸入驅動程序設備名稱和DMI數據匹配:
evdev:name:<input device name>:dmi:bvn*:bvr*:bd*:svn<vendor>:pn*
其中 <input_device_name>
是驅動程序指定的名稱設備 ,<vendor>
是由內核DMI modalias導出的固件提供的字符串。
塊主體中每一行的格式為 KEYBOARD_KEY_<scancode>=<keycode>
. <scancode>
的值是十六進制的,但是沒有前導0x
(即,是a0
而不是0xa0
), 而 <keycode>
的值是小寫的鍵名名稱字符串,就像在/usr/include/linux/input-event-codes.h
中列的一樣(請參閱KEY_<KEYCODE>
變量),[4] 處有一個排序列表。注意不能在<keycode>中指定十進制值。
evemu-describe
來獲取 這個設備(要自定義hwdb 規則的設備)的標識符, 該實用程序由 evemu包 軟件包提供。
通過以root用户身份運行 evtest
這個設備(要自定義hwdb 規則的設備)的標識符以及要使用的按鍵的掃描碼。 該實用程序由evtest包軟件包提供。自定義hwdb的示例[編輯 | 編輯原始碼]
示例hwdb文件將匹配所有AT鍵盤:
/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
這是在筆記本電腦和USB鍵盤上重新綁定修飾符(modifiers)的示例:
/etc/udev/hwdb.d/10-my-modifiers.hwdb
evdev:input:b0003v05AFp8277* # 在Kensington Slim Type USB(使用旧的ABI)上进行了测试 KEYBOARD_KEY_70039=leftalt # 将capslock绑定到leftalt KEYBOARD_KEY_700e2=leftctrl # 将leftalt绑定到leftctrl evdev:atkbd:dmi:* # 内置键盘:匹配所有AT键盘 KEYBOARD_KEY_3a=leftalt # 将capslock绑定到leftalt KEYBOARD_KEY_38=leftctrl # 将leftalt绑定到leftctrl
要阻止 Sleep
鍵,請將其綁定到 "reserved" 關鍵字。 或者,您可以使用 "unknown" 將其映射到 NoSymbol
鍵。 例如:
/etc/udev/hwdb.d/90-block-sleep.hwdb
evdev:input:b0003v03F0p020C* # hp 5308 keyboard controller KEYBOARD_KEY_10082=reserved
更新硬件數據庫索引[編輯 | 編輯原始碼]
更改配置文件後,需要重建硬件數據庫索引 hwdb.bin
。
- 通過運行一下命令手動更新
hwdb.bin
# systemd-hwdb update
- 通過註釋掉
systemd-hwdb-update.service
中的ConditionNeedsUpdate
,在每次重新啟動時自動更新。
/usr/lib/systemd/system/systemd-hwdb-update.service
# 该文件是systemd的一部分。 . . #ConditionNeedsUpdate=/etc . .
在systemd-hwdb-update.service
完成加載後,systemd-trigger.service
將從hwdb.bin
重新加載更改。
- Systemd(簡體中文)升級後自動。
在Systemd的每次升級中,安裝腳本都通過以root用户身份運行udevadm hwdb --update
來重建hwdb.bin
,因此我們不需要關心它 。
重新加載硬件數據庫索引[編輯 | 編輯原始碼]
內核在啟動過程中加載hwdb.bin
,重新啟動系統將保證加載更新後的hwdb.bin
。
使用 udevadm
,可以通過運行下面命令來從更新後的hwdb.bin
加載新的鍵映射。
# 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
as the root user, then the deleted mapping still kept by the kernel, at least until a reboot.
請注意,使用 udevadm
僅加載已添加或更改的鍵映射,因此,如果我們從配置文件中刪除映射,重建 hwdb.bin
並以root用户身份運行 udevadm trigger
,那麼刪除的映射仍將保留在內核中,直到重新啟動為止。
查詢數據庫[編輯 | 編輯原始碼]
您可以通過按鍵或運行 udevadm info
來檢查配置是否已加載。 對於上面示例中的USB鍵盤,這將輸出我們配置的映射,如下所示:
# udevadm info /dev/input/by-path/*-usb-*-kbd | grep KEYBOARD_KEY E: KEYBOARD_KEY_70039=leftalt E: KEYBOARD_KEY_700e2=leftctrl
使用setkeycodes[編輯 | 編輯原始碼]
setkeycodes 是一個將 scancodes-to-keycodes 映射表加載到Linux內核中的工具。 它的用法是:
# setkeycodes scancode keycode ...
可以一次指定多個對。 掃描碼(Scancodes) 以十六進制給出, 鍵位碼 以十進制給出。
# setkeycodes 45 30 # 将NumLock(0x45)绑定到AT键盘上的KEY_A(30) (successful) # setkeycodes 70053 30 # 将NumLock(0x70053)绑定到USB键盘上的KEY_A(30) KDSETKEYCODE: Invalid argument failed to set scancode 620d3 to keycode 31