# キーが登録され、コンピュータで解釈される仕組み

<!---
  original document: 0.9.32:docs/how_keyboards_work.md
  git diff 0.9.32 HEAD -- docs/how_keyboards_work.md | cat
-->

このファイルでは、USB を介してキーボードがどのように動作するかの概念を学習できます。ファームウェアを直接変更することで何が期待できるかをより良く理解することができます。

## 概略図

特定のキーを1つ入力するたびに、このような一連のアクションが発生します:

```text
+------+         +-----+       +----------+      +----------+     +----+
| User |-------->| Key |------>| Firmware |----->| USB wire |---->| OS |
+------+         +-----+       +----------+      +----------+     +----+
```

この図は何が起こっているかを非常に単純に示したものです。詳細については次のセクションで説明します。

## 1. キーを押す

キーを押すたびに、キーボードのファームウェアはこのイベントを登録することができます。
キーが押され、保持され、放された時に登録することができます。

これは通常キー押下の定期的な走査で発生します。多くの場合、キーの機械的な応答時間、キー押下情報を転送するプロトコル(ここでは USB HID)、あるいは使用されるソフトウェアによって、この速度は制限されます。

## 2. ファームウェアが送信するもの

[HID 仕様]https://www.usb.org/sites/default/files/documents/hut1_12v2.pdfでは、適切に認識されるためにキーボードが USB 経由で実際に送信できるものを規定しています。これには、`0x00` から `0xE7` までの単純な数字であるスキャンコードの定義済リストが含まれます。ファームウェアはスキャンコードをキーボードのそれぞれのキーに割り当てます。

ファームウェアは実際の文字を送信せず、スキャンコードだけを送信します。
従って、ファームウェアを変更することで、特定のキーにたいして USB を介してどのスキャンコードが送信されるかだけを変更することができます。

## 3. イベント入力やカーネルが行うこと

*スキャンコード*は、[マスターブランチの 60-keyboard.hwdb]https://github.com/systemd/systemd/blob/master/hwdb.d/60-keyboard.hwdb キーボードに依存する*キーコード*にマップされます。このマッピングが無いと、オペレーティングシステムは有効なキーコードを受信せず、キー押下で何も有用なことができません。

## 4. オペレーティングシステムがすること

キーコードがオペレーティングシステムに到達すると、ソフトウェアの一部はキーボードのレイアウトによって、実際の文字と照合しなければなりません。例えば、レイアウトが QWERTY に設定されている場合、照合テーブルの例は以下の通りです:

| キーコード | 文字 |
|---------|-----------|
| 0x04 | a/A |
| 0x05 | b/B |
| 0x06 | c/C |
| ... | ... |
| 0x1C | y/Y |
| 0x1D | z/Z |
| ... | ... |

## 説明をファームウェアに戻して

(独自のものを作成していない限り)レイアウトは一般的に固定されているため、ファームウェアは実際には作業を簡単するためレイアウト名で直接キーコードを記述できます。これが、`KC_A` が実際に QWERTY で `0x04` を表す場合に行われることです。完全なリストは[キーコード]ja/keycodes.mdにあります。

## 送信できる文字のリスト

ショートカットを別として、限られたキーコードのセットが限られたレイアウトにマップされていることは、**指定されたキーに割り当てることができる文字のリストは、レイアウト内に存在するものだけである**ことを意味します。

例えば、QWERTY US レイアウトがあり、1つのキーを `` (ユーロ通貨記号)を生成するように割り当てたい場合、そうすることができないことを意味します。なぜなら、QWERTY US レイアウトはそのようなマッピングを持たないためです。QWERTY UK レイアウト、あるいは QWERTY US International を使うことでそれを修正することができます。

全ての Unicode を含むキーボードレイアウトがなぜ考案されていないのか疑問に思うかもしれません。USB を介して利用可能なキーコードの数の制限により、このようなことは許可されません。

## (おそらく) Unicode 文字を入力する方法

ファームウェアに *一連のキー* を送信させて、目的のオペレーティングシステムの[ソフトウェア Unicode インプットメソッド]https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_inputを使うことができます。このようにして、OS で定義されたレイアウトとは無関係に文字を効率的に入力することができます。

ただし、以下のような複数の欠点があります:

- 一度に、一つの特定の OS に縛られます (OS を変更する時に再コンパイルする必要があります);
- 特定の OS では、全てのソフトウェアが動作するわけではありません;
- 一部のシステムでは Unicode のサブセットに制限されます。