USB HID 1.11 を読む

USB HID 1.11[1] 規格の概要。

[1] http://www.usb.org/developers/docs/docs/hidpage/

1 序文

2 導入

3 概要

USB デバイスの情報は ROM のセグメントに保存されています。このセグメントはディスクリプタと呼ばれます。インターフェースディスクリプタは有限のクラスのうちの一つに所属するデバイスを特定するために使用されます。そのうちの HID クラスがこの文章で取り上げるものです。

USB/HID クラスデバイスはデータのルート決定とデータを取得するために対応する HID クラスドライバを使用します。

データのルート決定とデータの取得はデバイスディスクリプタとデータを調べることで行います。

...図

HID クラスデバイスディスクリプタの存在とそのサイズでディスクリプタの種類を特定できます。

...図

4 機能特性

このセクションでは HID の以下の機能特性について説明します。

  • クラス
  • サブクラス
  • インターフェース
4.1 HID クラス

インターフェースディスクリプタのクラスで HID クラスを指定する。

4.2 サブクラス

ブートインターフェースの場合、インターフェースディスクリプタのサブクラスを正しく指定する。

サブクラスコード 説明
0 サブクラスなし
1 ブートインターフェースサブクラス
2-255 予約
4.3 プロトコル

ブートデバイスの場合、インターフェースディスクリプタのインターフェースプロトコルで機能用のプロトコルを指定する。

プロトコルコード 説明
0 なし
1 キーボード
2 マウス
3-255 予約
4.4 インターフェース

HID クラスデバイスはコントロールパイプとインタラプトパイプでコミュニケーションする。

コントロールパイプは次のために使用されます。

  • USB 制御とクラスデータの要求の送受信。
  • HID クラスドライバによるデータ送信 (Get_Report リクエスト)。
  • ホストからデータを受信。

インタラプトパイプは次のために使用されます。

  • 非同期 (リクエストされていない) のデータをデバイスから受信。
  • 低レイテンシデータをデバイスから送信。

インタラプトアウトプットパイプはオプション (デバイスからみて受信側)。インタラプトアウトプットパイプがない場合、アウトプットレポートはコントロールエンドポイントを介して Set_Report(Output) リクエストで送信される。

パイプ 説明 必須
コントロール (エンドポイント 0) USB 制御、クラスリクエストコード、ポーリングデータ(メッセージデータ) Y
インタラプトイン データイン、デバイスから(ストリームデータ) Y
インタラプトアウト データアウト、デバイスへ(ストリームデータ) N

4.5 デバイスの制限

USB 仕様書 5 章参照。

5 オプションモデル

このセクションでは HID クラスデバイスのオプションモデルの基本について大まかに説明します。

5.1 デバイスディスクリプタの構造

最上位レベルでは、ディスクリプタはデバイスディスクリプタと文字列ディスクリプタとして情報を参照できる 2 つのテーブルを含みます。標準的な USB デバイスディスクリプタはプロダクト IDとその他のデバイスについての情報を指定します。

...図

5.2 レポートディスクリプタ

レポートディスクリプタは情報テーブルで、項目と呼ばれるデータブロックの集合です。

...図

5.3 一般的な項目の書式

項目はデバイスについての情報の欠片です。すべての項目は 1 バイトのプレフィックスを持ち、そこにはサイズ、種類、タグが含まれています。

...図

項目はオプションとしてデータを含むことができます。短い項目と長い項目があり、プレフィックスを確認することで判別できます。詳細はセクション 6 参照。

...図

5.4 項目のパーサ

HID クラスデバイスドライバは Report ディスクリプタの項目のパーサを持っています。パーサがディスクリプタから連続的に並んだデータから情報を抽出します。

...図

Main, Push, Pop 項目によってステートテーブルの項目の内容が移動します。

  • Main 項目が見つかると、新しいレポート構造が作成、初期化されます。すべての Local 項目はステートテーブルから削除されますが、Global 項目は残ります。そのため、Global 項目は新しい Main 項目のデフォルト値を設定します。複数の同じようなコントロールは最初の Main 項目の Global 項目により一度だけ設定すれば十分です。
  • Push 項目に遭遇すると、ステートテーブルはコピーされてスタックに配置されます。
  • Pop 項目があると、ステートテーブルはスタックからテーブルの一番上に置換されます。

パーサーは Report ディスクリプタ全体をパースする必要があります。

5.5 Usage

Usage は Report ディスクリプタの一部でコントロールの役割についての情報を提供します。さらに、Usage タグはベンダーが指定する使用方法を示します。

一つの Report ディスクリプタは複数の Usage タグを含むことができます。コントロールには各々の Usage を割り当てることができます。

Usage は 32 ビット符号なし値で、上位 16 ビットは Usage Page を定義し、下位 16 ビットは Usage ID を定義します。

5.6 レポート

USB では USB フレームごとにデータを送信または受信します。
トランザクションは複数のパケットで構成できますが、Low スピードデバイスでは 8 ビット制限、high スピードデバイスでは 64 ビット制限があります。

...図

多くのデバイスは簡単なデータフィールドのレポートを送信します。しかし、一つのエンドポイントで複数の機能を持つ場合、同じエンドポイントから独立した複数のレポートを送信することもできます。
Report ID 項目タグが各々のレポート転送に 1 バイトの識別用プレフィックスを設定します。Report ID 項目タグが Report ディスクリプタに存在しない場合、ただ一つの Input, Output, Feature 構造が存在するとみなされます。

バイスが複数のレポート構造を持つ場合、すべてのデータ転送は 1 バイトの識別用プレフィックスから始まります。

5.7 文字列

オプション。データーフィールドのラベルを設定します。

補足 E: HID クラスデバイスの USB ディスクリプタを参照。

5.8 マルチバイト数値の書式

レポート中のマルチバイトの数値はリトルエンディアン形式になります。レポート中の Logical Minimum と Logical Maximum の値が上限と下限を決定します。浮動小数点値は不可。

5.9 方位

HID クラスのデバイスは右手系を使用します。

バイナリデータをレポートするコントロールでは 0 = off/False、1 = on/True とします。

5.10 ヌル値

HID クラスでは実行時に特定のフィールドを無視することができます。値の範囲を指定して、レポートの値がその範囲を超えている場合、コントロールは変化していないことになります。

0 をヌル値に含めることをお勧めします。

6 ディスクリプタ

6.1 標準ディスクリプタ

HID クラスデバイスは以下の USB ディスクリプタを使用します。

  • バイス (Device)
  • コンフィグレーション (Configuration)
  • インターフェース (Interface)
  • エンドポイント (Endpoint)
  • 文字列 (String)
6.2 クラス固有のディスクリプタ

HID クラス固有のディスクリプタは以下のものがあります。

  • HID
  • レポート (Report)
  • フィジカル (Physical)
6.2.1 HID ディスクリプタ
パート オフセット
/サイズ(バイト)
説明
bLength 0/1 HID ディスクリプタの合計長さ
bDescriptorType 1/1 HID ディスクリプタを指定する定数
bcdHID 2/2 HID クラス仕様書のリリースバージョン
bCountryCode 4/1 国別コード
bNumDescriptors 5/1 ディスクリプタ
bDescriptorType 6/1 クラスディスクリプタを示す定数 (7.1.2 参照)
wDescriptorLength 7/2 レポートディスクリプタの合計サイズ
[bDescriptorType]... 9/1 オプションのディスクリプタの種類を指定する定数
[wDescriptorLength]... 10/2 オプションのディスクリプタの合計サイズ
コード
00 指定なし
13 ISO
15 Japan(Katakana)
33 US
6.2.2 レポートディスクリプタ

レポートディスクリプタはデバイスのレポートのデータフィールドに依存しています。
最初の部分は項目の種類、項目タグ、項目のサイズから構成されています。

項目の種類には Main, Global, Local があります。Main 項目には以下のものが定義されています。

  • Input: デバイスの同じようなコントロールからのデータ参照。
  • Output: デバイスの同じようなコントロールへのデータ。
  • Feature: エンドユーザーに関係のないデバイスの入出力。
  • Collection: Input, Output, Feature 項目のグループ。
  • End Collection: Collection の終了。

レポートディスクリプタはデバイスの各々のコントロールで提供されているデータについての情報を提供します。

Main 項目 (Input, Output, Feature) はデータのサイズ、データが絶対座標または相対座標かどうか、またその他の情報を提供します。
Local および Global 項目はデータの最小/最大値などの情報を提供します。

Local 項目は次の Main 項目で定義されるデータフィールドについて指定します。
Global 項目はデフォルトの属性を指定し、そのディスクリプタでの他のデータフィールドに影響します。

Report Size (3)
Report Count (2)
Input
Report Size (8)
Input
Output

3 ビットの入力レポートフィールドが 2 つ、8 ビットの入力レポートフィールドが 2 つ、8 ビットの出力フィールドが 2 つ。
途中で Report Size のみ 3 ビットから 8 ビットに変更されている。

レポートディスクリプタは複数の Main 項目を定義できます。レポートディスクリプタは以下の項目を定義していなければいけません。

  • Input (Output または Feature)
  • Usage
  • Usage Page
  • Logical Minimum
  • Logical Maximum
  • Report Size
  • Report Count
Usage Page (Generic Desktop), 
Usage (Mouse), 
Collection (Application), 
  Usage (Pointer), 
  Collection (Physical), 
    Usage Page (Buttons), 
    Usage Minimum (1), 
    Usage Maximum (3), 
    Logical Minimum (0), 
    Logical Maximum (1), 
    Report Count (3), 
    Report Size (1), 
    Input (Data, Variable, Absolute), 
    Report Count (1), 
    Report Size (5), 
    Input (Constant), 
    Usage Page (Generic Desktop), 
    Usage (X), 
    Usage (Y), 
    Logical Minimum (-127), 
    Logical Maximum (127), 
    Report Size (8), 
    Report Count (2), 
    Input (Data, Variable, Relative), 
  End Collection, 
End Collection
6.2.2.1 項目の種類とタグ

すべての項目は 1 バイトの種類を表すプレフィックスを持っています。項目の種類には以下のものがあります。

  • 短い項目: 1-5 バイト。一般的な項目で、典型的な場合にはオプションのデータで 1 または 0 のデータを含みます。
  • 長い項目: 3-258 バイト。より多くのデータを必要とする部分。
6.2.2.2 短い項目

最初のバイトにサイズ、種類、タグを指定します。

...図

部分 説明
bSize データのサイズを指定
0: 0 バイト、1: 1 バイト、2: 2 バイト、3: 4 バイト
bType 項目の種類を指定
0: Main、1: Global、2: Local、3: 予約
bTag 項目の機能を指定
[data] データ(オプション)
  • 短い項目のタグと bSize に関連性はありません。
  • 大きな数値を指定したい場合、一部のデータビットを省略することも手です。
  • 短い項目のタグには Main, Global, Local があります。項目の種類 (bType) がタグのカテゴリを指定して項目の振る舞いも決定します。
6.2.2.3 長い項目

短い項目と同様に最初のバイトに項目のサイズ、種類、タグを指定します。長い項目のタグには、長い項目であることを示す特別な値を指定します。サイズとタグはどちらも 8 ビットになります。データは 255 バイトまでとなります。

...図

部分 説明
bSize 項目の合計サイズ。10 (2 バイト) で長い項目を指定
bType 予約済みの種類 11 (3) で長い項目を指定
bTag 項目の機能を指定、いつも 1111
[bDataSize] 長い項目のデータサイズ
[bLongItemTag] 長い項目のタグ
[data] データ(オプション)

このドキュメントでは長い項目用のタグは定義されていません。xF0-xFF はベンダー定義用です。

6.2.2.4 Main 項目

Main 項目は Report ディスクリプタのデータフィールドを特定の型で指定するために使用します。データと非データの二種類の項目があります。Input, Output, Feature はフィールドを作成しますが、他のものは非データ型です。

タグ
Input 1000 00nn Bit 0 {Data (0) Constant (1)}
Bit 1 {Array (0) Variable (1)}
Bit 2 {Absolute (0 Relative (1)}
Bit 3 {No Wrap (0) Wrap (1)}
Bit 4 {Linear (0) Non Linear (1)}
Bit 5 {Preferred State (0) No Preferred (1)}
Bit 6 {No Null position (0) Null state (1)}
Bit 7 Reserved (0)
Bit 8 {Bit Field (0) Buffered Bytes (1)}
Bit 31-9 Reserved (0)
Output 1001 00nn Bit 0 {Data (0) Constant (1)}
Bit 1 {Array (0) Variable (1)}
Bit 2 {Absolute (0) Relative (1)}
Bit 3 {No Wrap (0) Wrap (1)}
Bit 4 {Linear (0) Non Linear (1)}
Bit 5 {Preferred State (0) No Preferred (1)}
Bit 6 {No Null position (0) Null state (1)}
Bit 7 {Non Volatile (0) Volatile (1)}
Bit 8 {Bit Field (0) Buffered Bytes (1)}
Bit 31-9 Reserved (0)
Feature 1011 00nn Bit 0 {Data (0) Constant (1)}
Bit 1 {Array (0) Variable (1)}
Bit 2 {Absolute (0) Relative (1)}
Bit 3 {No Wrap (0) Wrap (1)}
Bit 4 {Linear (0) Non Linear (1) }
Bit 5 {Preferred State (0) No Preferred (1)}
Bit 6 {No Null position (0) Null state (1)}
Bit 7 {Non Volatile (0) Volatile (1)}
Bit 8 {Bit Field (0) Buffered Bytes (1)}
Bit 31-9 Reserved (0)
Collection 1010 00nn 0x00 Physical (軸グループ)
0x01 Application (マウス、キーボード)
0x02 Logical (相関データ)
0x03 Report
0x04 Named Array
0x05 Usage Switch
0x06 Usage Modifier
0x07-0x7F 予約
0x80-0xFF ベンダー定義
End Collection 1100 00nn なし コレクションを閉じる
Reserved 1101 00nn -
1111 00nn
なし 予約
  • Main 項目のデフォルト値は 0。
  • Input 項目は 0 バイトサイズのデータが可能で、その場合すべてのデータビットはゼロとみなせます。4 バイトデータタグを指定して 4 つのゼロバイト送ることと同じです。
6.2.2.5 Input, Output, Feature 項目
6.2.2.6 Collection, End Collection 項目
6.2.2.7 Global 項目

Global 項目はコントロールからのデータを定義します。新しい Main 項目のステートテーブルの値を設定します。そのため、Global 項目タグによる指定は他の項目にも影響を与えます。他の Global 項目によって上書きされます。

タグ 説明
Usage Page 0000 01nn 現在の Usage Page を指定
Logical Minimum 0001 01nn 論理単位での範囲値の最小値
Logical Maximum 0010 01nn 論理単位での範囲値の最大値
Physical Minimum 0011 01nn 物理的な範囲値の最小値。Logical Minimum に単位をつけたもの
Physical Maximum 0100 01nn 物理的な範囲値の最大値。Logical Maximum に単位をつけたもの
Unit Exponent 0101 01nn 指数
Unit 0110 01nn 単位
Report Size 0111 01nn レポートフィールドのビット数
Report ID 1000 01nn レポート ID
Report Count 1001 01nn 項目のデータフィールド数
Push 1010 01nn Global 項目をステートテーブルのスタックにコピー
Pop 1011 01nn ステートテーブルのスタックの最上位の構造を置き換え
Reserved 1100 01nn -
1111 01nn
予約

...

6.2.2.8 Local 項目
6.2.2.9 パッディング

バイトに揃えるためにパッディングすることができます。

6.2.3 Physical ディスクリプタ

Physical ディスクリプタはコントロールを使用する人間の体の一部を指定する情報を提供します。

...

補足 A: Usage タグ

USB HID Usage Table ドキュメント参照。

補足 B: ブートインターフェースディスクリプタ

補足 C: キーボードの実装

USB キーボードの設計必要条件を挙げます。

  • 非修飾キーは Input(Array, Absolute) 項目でレポートしなければいけません。レポートは現在押し下げられているキーのリストを含み、押し下げと開放のコード (相対データ) ではありません。
  • キーボードは Idle リクエストをサポートしなければいけません。
  • キーボードは Idle レートでデータレポートを送信しなければいけません。また、Get_Report リクエストを受信した場合、新しいキーイベントがなくても送信しなければいけません。
  • キーボードは Report Count を超えるキーが押し下げられていた場合、ファントム状態をUsage(ErrorRollOver) をすべてのフィールドに指定してレポートしなければいけません。補足 B のキーボードディスクリプタを使用した時の制限は非修飾キー 6 つです。さらに、キーボードは無効または人s気不可能な組み合わせのキーが押された時、ファントム状態をレポートします。
  • フィールド中のキーコードの順番は意味を持ちません。順番の判定はホストのソフトウェアが前のレポートと現在のレポートを比較することでおこないます。一つのレポートで 2 つ以上のキーが含まれていた場合、それらの順番は判定不可能です。キーボードは一つのレポートから複数のイベントを発生させるためのイベントをバッファーします。
  • "リピート速度" と "最初のリピートまでのディレイ" はホストが実装するもので、キーボードが行うものではありません。ホストはデバイスのレポートレートとレポート数をキーが押されていた時間の判定に使用します。代わりに、ホストは自身のクロックまたはアイドルリクエストを使用します。
  • LED の状態の同期と CAPS LOCK, NUM LOCK, SCROLL LOCK, COMPOSE, KANA イベントはホストが管理するもので、キーボードが管理するものではありません。補足 B のキーボードディスクリプタを使用する場合、LED の状態は 5 ビットの絶対レポートを Set_Report(Output) を介してキーボードへ送信することで行います。
  • ブートキーボードのため、レポート中のあるキーのインデックスはキーの役割と一致しなければいけません。これは BIOS は Report ディスクリプタを読まないためです。レガシープロトコルでなくとも可能なものは Usage Table と一対一割り当てとすることを推奨します(要求ではありません)。
  • ブートキーボードはブートプロトコルと Set_Protocol リクエストをサポートしていなければいけません。ブートキーボードは USB がフルサポートされている環境のための代替のプロトコル (Report ディスクリプタで指定する) をサポートします。

...例

補足 D: レポートディスクリプタの例

補足 E: HID クラスデバイスのための USB ディスクリプタの例

補足 F: レガシーキーボードの実装

USB を完全にサポートしなくともブートプロトコルとレガシープロトコルをサポートした USB キーボードを使用できます。

F.1 目的

固定の HID レポートを定義して、USB サポートをリッチとしにくい ROM ベースの BIOS などのデバイスで USB ベースのキーボードを利用できるようにします。

F.2 概要

F.3 ブートキーボード必要条件

ブートキーボードは次の項目をサポートすること。

  • 補足 A で記述されている HID クラス規格に従うこと。
  • ブートキーボードは Set_Idle リクエストをサポートすること。
  • ブートキーボードは新しいキーイベントがなくても、パイプがポールされたときにデータレポートを送信すること。Set_Idle リクエストが HID クラス規格に定義されたこの振る舞いをオーバーライドできること。
  • ブートキーボードは修飾キーでないキーが Report Count を超えた場合、すべてのフィールドを "Keyboard ErrorRollOver" としたレポートを送信すること。ブートキーボードの制限は修飾キーを除いて 6 キー。
  • ブートキーボードデバイスがゴーストキーやロールオーバーエラーでキーを正確に決定できない場合、すべてのフィールドを "Keyboard ErrorRollOver" としたレポートを送信すること。
  • ブートキーボードはシステムからの明確な Set_Report(OUtput) リクエストがなければ CAPS LOCK, NUM LOCK, SCROLL LOCK, CMPOSE, KANA LED ステータスを管理しないこと。
  • ブートキーボードは標準 84 キーキーボードのすべてのコードをサポートすること。(補足 A.3 参照)
  • ブートキーボードは Set_Protocol リクエストをサポートすること。
  • ブートキーボードはリセット時にデバイスの Report ディスクリプタに指定されたブートプロトコルでないデバイスに戻ること。この場合、ブートキーボードの Report ディスクリプタはブートプロトコルに合致する必要はありません。ブートキーボードの Report ディスクリプタはブートプロトコルディスクリプタではありません。
  • wValue を指定した Get_Descriptor リクエストを受信すると、コンフィグレーション状態になります。キーボードは Configuration ディスクリプタ、すべての Interface ディスクリプタ、すべての Endpoint ディスクリプタ、HID ディスクリプタを返すこと。この時に HID Report ディスクリプタを返しません。HID ディスクリプタは Interface と Endpoint ディスクリプタに挟んで記述すること。

F.4 キーボード: USB をフルサポートしないシステムの必要条件

USB ブートプロトコルキーボードをサポートするファームウェアなどで必要な条件。

  • 一つのレポート中でキーを押した順番を仮定しないこと。フィールド中のキーコードの順番は意味がありません。キーの順番の判定はホストソフトウェアが前のレポートを現在のレポートを比較することで行います。あるレポート中で 2 つ以上のキーがレポートされている場合、それらの順番は決定できません。キーボードは一つのレポートから複数のイベントを発生するイベントをバッファーできます。
  • システムはリピート速度と間隔を実装すること。ブートキーボードはリピート速度と間隔を実装する能力がありません。システムはデバイスポートレートをキーが押し下げられていた時間を判定するために使用できます。または、システムは自身のクロックまたは Set_Idle レポートのタイミングを使用できます。
  • システムは Caps Lock, Num Lock, Scroll Lock イベントの LED ステータスの同期を管理すること。システムは Set_Report(Output) リクエストを介して 5 ビットの絶対値レポートで LED の状態を設定します。
  • システムはキーボードデバイスがコンフィグレーションされた後で Set_Protocol リクエストをキーボードに発行すること。
  • システムは 8 バイトのキーボードデータパケットの二番目のバイトを無視すること。このバイトはシステム独自の拡張のために提供されています。このバイトは可搬性がありません。システムに固有のノートパソコンのキーボードの拡張などでの利用に制限されます。

F.5 キーボード: キーボードブートプロトコルの使用

補足 G.4 に挙げられている必要条件について説明しています。

ブートプロトコルを使用するには、システムは次の要件をサポートしていなければいけません。

  • bInterfaceSubClass が 1 のブートインターフェースサブクラスと bInterfaceProtocol が 1 のキーボードを含むコンフィグレーションを選択する。
  • バイスがブートモードになるように Set_Protocol を使用する。デフォルトでは、デバイスは非ブートモードで起動します (プロトコルを知るために Report ディスクリプタを読み込まなければいけません)。そのため、この段階でシステムがデバイスを定義済みのブートプロトコルモードに変更させることになります。
  • インタラプトインエンドポイントで 8 バイトレポートを受信すると、システムは SHIFT, CTRL, ALT, GUI キーが前のレポートから変化しているかどうか判断するため、修飾キー (バイト 0 の 7-0 ビット) を確認しなければいけません。システムは非修飾キーの状態が前のレポートから変更されているか判断するために 6 つのキーコードバイトを確認しなければいけません。
  • 非修飾キーの状態が変更されておれば、システムはレポートから送信されたキーコードをシステムが認識できるキーイベントに翻案しなければいけません。
  • このリマッピングはルックアップテーブルで行えます。キーコードは実態はインデックスですが、システムの開発者には区別されません。ブートキーレポートで送信された値は Usage Index で定義されたものと同じ値です。例えば、レポートが次の値を含んでいた場合、Key Usage Table から Usage Index を検索します。04h: A, 3Ah: F1, 5Dh: 5 (キーパッド)。

ブートキーボードの場合、HID レポートの Usage が送信されないため、キーコードは Usage Index と一致しなければいけません。(Logical Minimum ベースで指定できない)

...

補足 G: HID リクエストの必要条件

種類 Get_Report Set_Report Get_Idle Set_Idle Get_Protocol Set_Protocol
ブートマウス 必要 オプション オプション オプション 必要 必要
非ブートマウス 必要 オプション オプション オプション オプション オプション
ブートキーボード 必要 オプション 必要 必要 必要 必要
非ブートキーボード 必要 オプション 必要 必要 オプション オプション
必要 オプション オプション オプション オプション オプション

補足 H: 用語