Closed8

HIDについて調べものメモ

nozonozo

Human Interface Device(HID)がPCとどんなやりとりをしているのか気になったので調べる。

HIDのドキュメントや仕様書は以下のものがあったけど全体像が見えていないのであまりピンとこない。

とっかかりとして以下の技術解説記事がわかりやすい。(ほかのUSBの解説記事も参考になる)

HID (Human Interface Device) クラスでは、レポートと呼ばれる単位でデータを転送します。例えばマウスの場合、各ボタンが押されているかどうか、水平方向の移動量、垂直方向の移動量、ホイールの移動量といった情報をまとめたレポートを定期的に転送します。

nozonozo

wio-terminalのサンプルにHIDマウスの実装例があった。これはArduinoのライブラリを使っているので、ライブラリの実装を追っていく。

https://wiki.seeedstudio.com/Wio-Terminal-USBH-Mouse/

まずサンプルをコンパイルすると以下のログが出るので使っているライブラリがMouse.cppとHID.cppであることがわかる。HID.cppはパスにsamdが入っているのでマイコンごとの実装っぽい。

Using cached library dependencies for file: C:\Program Files (x86)\Arduino\libraries\Mouse\src\Mouse.cpp
Using cached library dependencies for file: C:\Users\user\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.8.3\libraries\HID\HID.cpp

ライブラリの呼び出しをさかのぼっていくと、だいたい以下のソースが見つかった。

nozonozo

まずはレポートディスクリプタのバイト列の構造についてみていく。仕様書の"6.2.2 Report Descriptor"あたりから説明されている。

レポートディスクリプタはItemというデータが並んでいるもので、Itemのフォーマットは下のようになっていうる。(ItemにはShort ItemとLong Itemがあって、下のはShort Item)

Mouse.cppで定義されているレポートディスクリプタの一部をフォーマットに当てはめると次のようになる。

    Tag  Type Size         Data
    0000|  01|  01 (0x05), 0x01,                    // USAGE_PAGE (Generic Desktop)  // 54
    0000|  10|  01 (0x09), 0x02,                    // USAGE (Mouse)
    1010|  00|  01 (0xa1), 0x01,                    // COLLECTION (Application)
    0000|  10|  01 (0x09), 0x01,                    //   USAGE (Pointer)
    1010|  00|  01 (0xa1), 0x00,                    //   COLLECTION (Physical)
    1000|  01|  01 (0x85), 0x01,                    //     REPORT_ID (1)
...
    1000|  00|  01 (0x81), 0x06,                    //     INPUT (Data,Var,Rel)
    1100|  00|  00 (0xc0),                          //   END_COLLECTION
    1100|  00|  00 (0xc0),                          // END_COLLECTION
  • Sizeが後ろに続くDataの数を表している。この例だとEND_COLLECTIONというItem以外はすべてSizeが1なのでデータは1byteのみである。
  • TypeとTagでItemの種別を表し、Dataが種別ごとのItemで使われる値を表している。これから各Type/Tag/Dataの定義を見ていく。
nozonozo

ちょっと気になっていたのだけど、M5Stamp C3U(esp32-c3)はHIDデバイスとして扱えないのかな?ボードにUSBポートがついていて、マイコンからアクセスできるならホストと接続したときに自分はHID Classのデバイスだと返せばいける?

esp32-c3のドキュメントを見るとどうもハード的にUSB Serial/JTAG Controller(というClassがある?)に固定されているっぽいので、HIDとして扱うことはできなさそう。

Note that, in contrast with the USB OTG peripheral in some Espressif chips, the USB Serial/JTAG Controller is a fixed function device, implemented entirely in hardware. This means it cannot be reconfigured to perform any function other than to provide a serial channel and JTAG debugging functionality.
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/usb-serial-jtag-console.html

じゃあwio-terminal(ATSAMD51N19A)はどうやってHIDデバイスとして見せているのか気になるところ。

nozonozo

Itemごとの意味を見てみる。まずUSAGE_PAGEとUSAGEについて。

tag名 Tag Type Size
USAGE_PAGE 0000 01(Global) nn
USAGE 0000 10(Local) nn

Usageはデータがどう使われるかを決めている。例えば、レポートが3つの8bitフィールドで構成されていたとすると、Usageはそれらがx, y, zの入力であることを定義したりする。

HIDデバイスの用途?ごとにUsage Pageが割り振られていて、その中でさらにUsage IDが割り振られているイメージ。

HID Usage Tables, https://usb.org/document-library/hid-usage-tables-13

Usage Pageの例:

  • Generic Desktop Page (0x01)
    • 01 Pointer
    • 02 Mouse
    • 03 Reserved
    • 04 Joystick
    • 05 Gamepad
  • Simulation Controls Page (0x02)
  • VR Controls Page (0x03)
  • ...
このスクラップは2022/07/19にクローズされました