掃描碼映射至鍵位碼 - Arch Linux 中文维基

跳至內容

# 掃描碼映射至鍵位碼

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 Map scancodes to keycodes，最近一次同步於 2021-02-01，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

該頁面假定您已閱讀 Extra keyboard keys ，它提供了更多的內容。

將「掃描碼」映射為「鍵位碼」的動作，要比 Xorg 和 Linux 控制台更接近底層，所以對這個映射的更改在兩者中均有效。

[1][2][3]

將「掃描碼」映射到「鍵位碼」方式有兩種：

- 使用 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) 。

注意：從systemd 220開始，udev ABI進行了更改。 使用自定義udev hwdb規則的用戶應根據新的ABI更新它們

.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>中指定十進制值。

注意：用root身份運行`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

提示：上面的綁定的含義 A綁定到B，是指：在物理上按下A按鍵，計算機輸入B按鍵

要阻止`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

本文或本節內容已經過時。

原因： `ConditionNeedsUpdate=/etc` seems to be commented out by default in `systemd-hwdb-update.service` (checked in systemd包 232). (在Talk:掃描碼映射至鍵位碼討論)

本文或本章節的事實準確性存在爭議。

原因： Do not edit in `/usr/lib/`, use systemctl edit.（在 Talk:掃描碼映射至鍵位碼 中討論）

- 通過注釋掉`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 不適用於USB鍵盤（Linux 3.14.44-1-lts）：

    # 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

## 參閱

- B站 JimMoen：Linux通用鍵位修改（中）-實際操作
- 依雲's Blog：Poker II 鍵盤調教記

分類：​

- 鍵盤配置
- 使用「模板:過時」標記的頁面或章節

隱藏分類：​

- 使用「模板:準確性」標記的頁面或章節

掃描碼映射至鍵位碼
新增話題