LoginSignup
0
0

More than 3 years have passed since last update.

USB Hub Class を動かしてみる

Last updated at Posted at 2020-05-14

USB Hub Class の動作をQEMUで確認してみました。

QEMUのRaspberry Pi 3モデルのUSB動作を確認しています。USB Hubの初期化をしないと先に進めないので、ベアメタルのプログラムを作成してUSB Hub classの動作確認を確認してみました。

QEMUのRaspberry Pi 3モデルでUSBホストエミュレーション
ベアメタルでRaspberry Pi 3のUSBコントロール転送
の続きです。

ソースコード

はじめ

まず 今回動作確認した際のUSB のトポロジーは BroadcomのSOCのUSB portにhubが接続されてい、hubのport 1にUSB keyboardが接続されています。

(qemu) info usb
  Device 0.0, Port 1, Speed 12 Mb/s, Product QEMU USB Hub*
  Device 0.0, Port 1.1, Speed 12 Mb/s, Product QEMU USB Keyboard

USB Hubの仕様はUSB仕様書のUSB Hub Classの章で定義されています。

今回の説明では事前にポートにデバイスが接続されていることを知っているものとしていて最低限の初期化処理をしてみました。

今回の説明はUSBのコントロール転送のみです。コントロール転送なのでEP0を使います。
コントロール転送のパラメータはログ中の値をみてください。

USB Hub の初期設定

  • USBのバスリセットをすると、USB Hubがdev 0に現れます。
  • dev 0 の DEVICE Descriptor を取得してClass IDがHub(0x09)であることを確認する。
  • dev 0 のデバイスのアドレスを 2 に設定します。以降はdev 2としてアクセスします。
  • dev 2 のconfig を1に設定する。(Hubはconfig 1しかない)
  • dev 2 の HUB Descriptorを取得する。Hub Descriptoはクラスで定義されているのでreqに0xa006を指定します。応答の3バイト目がUSB Hubのポート数です。この例だと8です。

トレースのログ

GET DEVICE_DESCRIPTOR
  usb_hub_control dev 0, req 0x8006, value 256, index 0, langth 64
  12 01 10 01 09 00 00 08 09 04 AA 55 01 01 01 02 03 01 
SET ADDRESS 2
  usb_hub_control dev 0, req 0x5, value 2, index 0, langth 0
  usb_set_addr dev 2
GET CONFIG_DESCRIPTOR
  usb_hub_control dev 2, req 0x8006, value 512, index 0, langth 64
  09 02 19 00 01 01 00 E0 00 09 04 00 00 01 09
SET CONFIG 1
  usb_hub_control dev 2, req 0x9, value 1, index 0, langth 0
GET HUB_DESCRIPTOR
  usb_hub_control dev 2, req 0xa006, value 10496, index 0, langth 64
 0A 29 08 0A 00 01 00 00 00 FF 00 00 00 00 00 00 00 00

USB Hub port 1の設定

  • portの設定はSetPortFeatureを追加居ます。req が 0x0203 です。
  • port 1 の電源を入れる。 (value 8, index 1)
  • port 1 をリセットする。(value 4, index 1)
  • リセットをするとリセットをしたポートに接続してあるUSBキーボードがdev 0でアクセスできるようになります。port 1 に接続されたUSBキーボードのDevice Descritorを取得する。9バイト目が

トレースのログ

SET PORT 1 POWER ON
  usb_hub_control dev 2, req 0x2303, value 8, index 1, langth 0
  usb_hub_set_port_feature dev 2, port 1, feature power
SET PORT 1 RESET
  usb_hub_control dev 2, req 0x2303, value 4, index 1, langth 0
  usb_hub_set_port_feature dev 2, port 1, feature reset
GET DEVICE_DESCRIPTOR on Port 1.1
  usb_desc_device dev 0 query device, len 64, ret 18
  12 01 00 02 00 00 00 08 27 06 01 00 00 00 01 04 0B 01

メモ

  • 最後にリセットしたデバイスがdev 0に現れるという仕様は面白いです。
  • device addressが7bitなのでUSBの最大接続台数が127台になってる。
  • インタラプト転送を使うとどのポートで変更があったか検知できる。sttatus が0x2だとポート1に何か要因がある。
usb_dwc2_handle_packet ch 3 dev 0x55b99b16fdf0 pkt 0x7f1c7b99c3c8 ep 1 type Intr dir In mps 64 len 64 pcnt 1
  usb_hub_status_report dev 2, status 0x2
  02 00
  • CLEAR_PORT_FEATUREで要因をクリアすることができる。
  • ポートの電源ONとポートのリセット後は要因クリアした方が良い。
  • 電源ONの後は時間待ちが必要。
  • USBのドライバを書くにはUSBのプロトコルを勉強しないとツライ。
  • パケットを投げるにも、パラメータが多くて、応答が無い場合に、どのパラメータが間違っているのか調査するのがシンドイ。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0