Linux キーボード入力

最終更新: 2022-11-20 20:04:02 +0800 +0800
tags: Input | Keyboard | Linux
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

Linux は、キーボードの転送レベルのレポートを、安定した入力キーコード、および キーボードレイアウトが生成するテキストやアクションから分離します。これらの層を 分けることで、PS/2 と USB キーボードが異なるハードウェアデータを生成しながら、 どちらも KEY_F を報告できる理由を説明できます。

概要 #

入力は概念的に 4 段階をたどります。

  1. 転送ドライバーがバイトまたはレポートを受け取ります。atkbd ドライバーは AT と PS/2 のスキャンコードセットを処理し、usbhid は USB HID usage を解析します。
  2. ドライバーは make、break、プレフィックス、repeat の状態を解析し、押下、解放、 repeat の値とともに KEY_F (33) などの Linux 入力キーコードを報告します。
  3. 入力コアは evdev を通じてイベントを公開します。グラフィカルコンポジターまたは 入力ライブラリは通常、これらのイベントに独自のレイアウトを適用します。
  4. Linux 仮想コンソールでは、カーネルキーボード層がアクティブなコンソールキーマップ を適用し、バイト、Unicode 文字、文字列、コンソールアクションを端末層へ出力します。

したがってスキャンコードは文字ではなく、Linux キーコードは X11、Wayland、Unicode のコードポイントではありません。

IBM PC、XT、AT プロトコル #

初期の 83 キー IBM PC および PC/XT キーボードは、現在スキャンコードセット 1 と 呼ばれるバイト割り当てを確立しました。インターフェイスは実質的にキーボードから ホストへの一方向で、キーボードはクロック付きシリアルデータを供給しましたが、 ホストには LED、repeat、スキャンセット選択を制御する AT コマンドプロトコルが ありませんでした。通常のセット 1 の押下は 0x01 から 0x7f の make バイトを使い、 そのキーを解放するとビット 7 が設定されます。たとえば Escape は押下時に 0x01、 解放時に 0x81 を生成します。

84 キー IBM PC/AT キーボードは双方向インターフェイスとスキャンコードセット 2 を 導入しました。セット 2 はセット 1 を数値的に拡張するのではなく位置を変更しました。 左 Control はセット 2 では 0x14、セット 1 では 0x1d です。break シーケンスは 0xf0 プレフィックスを使うため、左 Control は押下時に 14、解放時に f0 14 を 生成します。ホストは LED、typematic 動作、アクティブセットを設定するコマンドを 送信できます。

PC 互換 AT コントローラーは、ソフトウェア互換性のためにキーボードのセット 2 の バイトをセット 1 形式へ変換することがよくあります。そのため Linux は多くの内蔵 キーボードを AT Translated Set 2 keyboard と識別します。物理キーボードはセット 2 を話し、コントローラーは変換済みバイトを公開します。IBM 端末と後期 PS/2 設計に 関連するスキャンコードセット 3 は、追加キーを独立して割り当て、キーごとの make、 break、typematic 設定をサポートします。現在の Linux atkbd ソースは変換済み セット 2、raw セット 2、セット 3 をサポートし、セット 2 がデフォルトです。

USB キーボードはこれらの AT バイトストリームを送信しません。usage 識別子を含む HID レポートを送信し、HID 入力ドライバーがその usage を同じ Linux KEY_* 名前空間 へマッピングします。

スキャンコードシーケンス #

押下は make、解放は break とも呼ばれます。押し続けた typematic キーは設定 された遅延後に make レポートを繰り返し生成し、make と break を交互に生成するわけ ではありません。Linux 入力インターフェイスはハードウェアまたはソフトウェアの 自動リピートを EV_KEY 値 2 で表します。

0xe0 プレフィックスはセット 1 とセット 2 の両方を拡張します。たとえばセット 1 の左 Control は 1d/9d、右 Control は e0 1d/e0 9d です。セット 2 は代わりに 14/f0 14 と e0 14/e0 f0 14 を使います。0xe1 プレフィックスは Pause など の例外的シーケンスを導入します。Print Screen と Pause は、単一バイトの通常キー ではなく複数バイトの互換シーケンスです。各バイトを個別に扱うと偽の Shift や Control イベントが生じるため、ドライバーはストリームをステートマシンとして解析します。

「スキャンコード」という用語は、より高レベルの転送識別子にも使われます。たとえば evdev の EV_MSC/MSC_SCAN 値は 0x70009 のような USB HID usage をエンコード できますが、対応する EV_KEY イベントは依然として KEY_F (33) です。古いセット 1 値と初期 Linux キーコードの数値的一致は歴史的なもので、インターフェイス不変条件 ではありません。

カーネルのスキャンコードからキーコードへのマッピング #

各低レベルドライバーがプロトコルのマッピングを所有します。AT ドライバーはデフォルト で置換可能なスキャンコードからキーコードへのテーブルを索引付けし、HID ドライバー は HID usage からキーコードを導出します。Linux キーコードは UAPI の input-event-codes.h and extend beyond the original 1–255 console range.

setkeycodes はコンソール AT キーボード経路の選択したマッピングを変更します。 エスケープされたセット 1 スキャンコードと 10 進キーコードなどのペアを受け取ります。

sh
sudo setkeycodes e06f 112

このコマンドは任意の USB HID デバイスをリマップせず、キーコード 112 が生成する文字 も定義しません。loadkeys でロードしたコンソールキーマップが後者の操作を行います。 現代のデスクトップ入力スタックは代わりにユーザー空間のレイアウトを適用します。

Console Keymaps, Modifiers, and Character Sets #

A keymaps(5) file describes the Linux virtual-console translation table. keycode N = ... selects an action according to the active modifier mask. The kernel keyboard layer defines weights for Shift (1), AltGr (2), Control (4), Alt (8), ShiftL (16), ShiftR (32), CtrlL (64), CtrlR (128), and CapsShift (256). Map files list only the combinations they need:

text
keymaps 0-2,4-5,8,12
keycode 30 = +a A
control alt keycode 111 = Boot

Keysyms can emit characters, strings, change a modifier or lock, switch virtual consoles, or request another console action. A leading + marks a letter as Caps-Lock-sensitive. string F100 = "text" binds a function-string action, while a compose definition combines two input characters after a Compose or dead-key action:

text
compose '`' 'a' to 'à'

A charset "iso-8859-1" declaration controls how subsequent symbolic keysyms are interpreted. Numeric keysyms are not portable between kernel versions; symbolic names or U+hhhh Unicode notation are preferable. The virtual console’s K_UNICODE mode emits UTF-8 for Unicode keysyms, whereas K_XLATE applies the legacy byte-oriented translation. K_MEDIUMRAW exposes keycode-oriented data and K_RAW exposes an approximation of raw scan bytes. Those console modes do not change the evdev ABI.

Input and Console Device Nodes #

/proc/bus/input/devices and /sys/class/input enumerate input devices and their handlers. /dev/input/eventN is a binary evdev stream of native struct input_event records. Keyboard records commonly include:

  • EV_MSC/MSC_SCAN for a transport identifier when the driver supplies one;
  • EV_KEY with a KEY_* code and value 0 (release), 1 (press), or 2 (repeat); and
  • EV_SYN/SYN_REPORT to terminate one event frame.

Use evtest or libevdev rather than decoding a hexdump, because record size and time fields follow the userspace ABI of the reading process:

sh
grep -A5 -B1 -i keyboard /proc/bus/input/devices
sudo evtest /dev/input/event4

Reading an event node requires the permissions assigned by the system’s input-device policy and can expose passwords typed anywhere on that device.

/dev/tty1, /dev/tty2, and the other virtual-terminal nodes expose terminal input after console keymap translation and line-discipline processing. /dev/tty0 refers to the active virtual terminal; /dev/console refers to the configured system console and is not a raw keyboard device.

Console Utilities #

Run console-mode tools from a real virtual terminal rather than a terminal emulator:

  • showkey -s, showkey -k, and showkey -a display scan-code, keycode, and character-oriented views. Raw mode can make the console temporarily unusable if the program is interrupted.
  • getkeycodes displays the AT driver’s current scan-code mappings.
  • setkeycodes SCANCODE KEYCODE ... changes selected AT mappings.
  • dumpkeys writes the current console layout in keymaps(5) syntax; dumpkeys --long-info also lists known keysyms.
  • loadkeys FILE compiles and installs a keymap into the kernel console tables.

The upstream Linux input documentation, event-code specification, current atkbd source, and upstream keymaps(5) define the interfaces described here.

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)