USB HUB の制御方法


 資料をあさっても USB HUB の制御方法がイマイチ分からなかったので、USB アナライザでログを採り、通信内容を調べてみることにした。

2004-02-16

機材

 調査に仕様した機材は以下の通り。


USB Streamscope を使う上での注意

 USB Streamscope は、古いバージョンでは WindowsXP で正常に動作しないのでアップデートする必要がある。

 詳しくは調べていないが、製品に付属していた Ver.1.00A では動作せず、現在有限会社オービットのサイトからダウンロード出来る Ver.1.0.5.2 では動作した。ただし面倒なことに、ユーザ登録をして ID とパスワードを発行してもらわないとダウンロード出来ない。人から借りる場合は最新版をダウンロードしてもらうように所有者にお願いするとよいだろう。

 US-F100A で採取したログは、通常プリンタ接続用として使われるパラレルポートで PC に送信され、USB Streamscope で解析される。PC の BIOS 設定でパラレルポートを ECP モードにしておく必要がある。

 アイソクロナス転送のログを採取する場合は、USB のホストとなる PC と、パラレルで繋げる PC は別々の PC にする必要がある。今回は HUB とマウスなのでアイソクロナス転送は無いので、一台の PC ですませた。

 他にもいろいろあると思うが、主な注意点は以上の通り。


採取手順

 ログの採取は、以下の手順で行った。

  1. US-F100A と PC をパラレルケーブルで接続する。
  2. US-F100A の USB アップストリームポートと PC を USB ケーブルで接続する。
  3. US-F100A の電源を入れ、USB Streamscope を起動する。
  4. ログ開始ボタンをクリックする。
  5. US-F100A の USB ダウンストリームポートに USB HUB を取り付ける。
  6. Windows による HUB の初期化が終わるまで待機。
  7. USB HUB に USB マウスを取り付ける。
  8. Windows によるマウスの初期化が終わるまで待機。
  9. マウスをしばらくグリグリと動かす。
  10. ログ停止ボタンをクリックする(開始ボタンとトグル動作)。
  11. 「名前をつけて保存」でログをファイルに保存。
  12. USB Streamscope を終了し、US-F100A の電源を切る。

注釈付きログ

 以下に USB Streamscope で採取したログを記載する。そのままペーストしても見れたものではないので、HTML のテーブルにして、注釈を入れてみた。ただし、USB HUB が分からないのでログを見て勉強するということで、 解釈に間違いがあるかも知れない。

USB HUB と USB MOUSE のログ
PRE1PID1ADRENPPID2DATAPRE3PID3
SETUPADR=0ENP=0DATA080 06 00 01 00 00 40 00ACK
INADR=0ENP=0DATA112 01 10 01 09 00 00 08ACK
OUTADR=0ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 HUB のデバイスデスクリプタの先頭8バイトだけを読み込んで、エンドポイント0のパケットサイズを取得。要求サイズは64バイトだが、8バイト受信した時点で強制的にステータスフェーズに移行して転送を打ち切っている。

SETUPADR=0ENP=0DATA000 05 01 00 00 00 00 00ACK
INADR=0ENP=0DATA1ACK

SET_ADDRESS addr = 1

 HUB のデバイスアドレスを1に設定。

SETUPADR=1ENP=0DATA080 06 00 01 00 00 12 00ACK
INADR=1ENP=0DATA112 01 10 01 09 00 00 08ACK
INADR=1ENP=0DATA016 04 18 55 07 00 00 01ACK
INADR=1ENP=0DATA100 01ACK
OUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 HUB のデバイスデスクリプタを取得。

SETUPADR=1ENP=0DATA080 06 00 02 00 00 09 00ACK
INADR=1ENP=0DATA109 02 19 00 01 01 00 E0ACK
INADR=1ENP=0DATA032ACK
OUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 HUB のコンフィギュレーションデスクリプタを取得。

SETUPADR=1ENP=0DATA080 06 00 02 00 00 FF 00ACK
INADR=1ENP=0DATA109 02 19 00 01 01 00 E0ACK
INADR=1ENP=0DATA032 09 04 00 00 01 09 00ACK
INADR=1ENP=0DATA100 00 07 05 81 03 01 00ACK
INADR=1ENP=0DATA0FFACK
OUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 HUB のコンフィギュレーションデスクリプタと、それに続くインタフェースデスクリプタ、エンドポイントデスクリプタを一括して取得。

SETUPADR=1ENP=0DATA080 06 EE 03 00 00 12 00ACK
INADR=1ENP=0STALL

GET_DESCRIPTOR(string)

 インデックス 0xee のストリングデスクリプタを取得しようとして失敗(デバイス側で用意されていないインデックス番号だった)。

80 80 A5 52 42

??? Unknown data ???

 ここでログに謎のゴミデータが記録された。以後の通信内容から推測すると、Windows により USB バスリセットが掛けられたと思われる。

SETUPADR=0ENP=0DATA080 06 00 01 00 00 40 00ACK
INADR=0ENP=0DATA112 01 10 01 09 00 00 08ACK
OUTADR=0ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 HUB のデバイスデスクリプタの先頭8バイトを取得。

SETUPADR=0ENP=0DATA000 05 02 00 00 00 00 00ACK
INADR=0ENP=0DATA1ACK

SET_ADDRESS addr = 2

 HUB のデバイスアドレスを2に設定。

SETUPADR=2ENP=0DATA080 06 00 01 00 00 12 00ACK
INADR=2ENP=0DATA112 01 10 01 09 00 00 08ACK
INADR=2ENP=0DATA016 04 18 55 07 00 00 01ACK
INADR=2ENP=0DATA100 01ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 HUB のデバイスデスクリプタを取得。

SETUPADR=2ENP=0DATA080 06 00 02 00 00 09 00ACK
INADR=2ENP=0DATA109 02 19 00 01 01 00 E0ACK
INADR=2ENP=0DATA032ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 HUB のコンフィギュレーションデスクリプタを取得。

SETUPADR=2ENP=0DATA080 06 00 03 00 00 FF 00ACK
INADR=2ENP=0DATA104 03 09 04ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 HUB のストリングデスクリプタ、インデックス 0x00(=対応している言語 ID の配列)を取得。0x0409 は English(United States)を表す。

SETUPADR=2ENP=0DATA080 06 01 03 09 04 FF 00ACK
INADR=2ENP=0DATA112 03 55 00 53 00 42 00ACK
INADR=2ENP=0DATA020 00 48 00 55 00 42 00ACK
INADR=2ENP=0DATA120 00ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string) "USB HUB "

 HUB のストリングスデスクリプタ、インデックス 0x01 を取得。

SETUPADR=2ENP=0DATA080 06 00 03 00 00 FF 00ACK
INADR=2ENP=0DATA104 03 09 04ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、HUB のストリングスデスクリプタ、インデックス 0x00 を取得。毎回取得し直している理由は不明。

SETUPADR=2ENP=0DATA080 06 01 03 09 04 FF 00ACK
INADR=2ENP=0DATA112 03 55 00 53 00 42 00ACK
INADR=2ENP=0DATA020 00 48 00 55 00 42 00ACK
INADR=2ENP=0DATA120 00ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string) "USB HUB "

 再度、HUB のストリングスデスクリプタ、インデックス 0x01 を取得。

SETUPADR=2ENP=0DATA080 06 00 03 00 00 FF 00ACK
INADR=2ENP=0DATA104 03 09 04ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、HUB のストリングスデスクリプタ、インデックス 0x00 を取得。

SETUPADR=2ENP=0DATA080 06 01 03 09 04 FF 00ACK
INADR=2ENP=0DATA112 03 55 00 53 00 42 00ACK
INADR=2ENP=0DATA020 00 48 00 55 00 42 00ACK
INADR=2ENP=0DATA120 00ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string) "USB HUB "

 再度、HUB のストリングスデスクリプタ、インデックス 0x01 を取得。

SETUPADR=2ENP=0DATA080 06 00 03 00 00 FF 00ACK
INADR=2ENP=0DATA104 03 09 04ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、HUB のストリングスデスクリプタ、インデックス 0x00 を取得。

SETUPADR=2ENP=0DATA080 06 01 03 09 04 FF 00ACK
INADR=2ENP=0DATA112 03 55 00 53 00 42 00ACK
INADR=2ENP=0DATA020 00 48 00 55 00 42 00ACK
INADR=2ENP=0DATA120 00ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(string) "USB HUB "

 再度、HUB のストリングスデスクリプタ、インデックス 0x01 を取得。

SETUPADR=2ENP=0DATA080 06 00 01 00 00 12 00ACK
INADR=2ENP=0DATA112 01 10 01 09 00 00 08ACK
INADR=2ENP=0DATA016 04 18 55 07 00 00 01ACK
INADR=2ENP=0DATA100 01ACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 再度、HUB のデバイスデスクリプタを取得。

SETUPADR=2ENP=0DATA080 06 00 02 00 00 FF 00ACK
INADR=2ENP=0DATA109 02 19 00 01 01 00 E0ACK
INADR=2ENP=0DATA032 09 04 00 00 01 09 00ACK
INADR=2ENP=0DATA100 00 07 05 81 03 01 00ACK
INADR=2ENP=0DATA0FFACK
OUTADR=2ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 再度、HUB のコンフィギュレーションデスクリプタを取得。

SETUPADR=2ENP=0DATA0A0 06 00 00 00 00 47 00ACK
INADR=2ENP=0DATA109 29 04 09 00 40 64 00ACK
INADR=2ENP=0DATA000ACK
OUTADR=2ENP=0DATA1ACK

[HUB Class] GET_DESCRIPTOR(device) = GetHubDescriptor

 HUB クラスデバイスデスクリプタを取得。GET_DESCRIPTOR(device) を HUB クラスのリクエストとして実行すると、HUB クラスデスクリプタの取得コマンドとなる。

SETUPADR=2ENP=0DATA080 00 00 00 00 00 02 00ACK
INADR=2ENP=0DATA101 00ACK
OUTADR=2ENP=0DATA1ACK

GET_STATUS

 HUB のデバイス状態を取得。0x0001 はセルフパワード、リモートウェイクアップ不可を示すが、実際には HUB に自己電源はなくバスパワードで動作させていたので、正しくない値である。

SETUPADR=2ENP=0DATA000 09 01 00 00 00 00 00ACK
INADR=2ENP=0DATA1ACK

SET_CONFIGURATION Conf.val = 1

 HUB のコンフィギュレーション番号を設定。

SETUPADR=2ENP=0DATA023 03 08 00 01 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] SET_FEATURE(port) = SetPortFeature

 ポート1への電源供給を開始。

SETUPADR=2ENP=0DATA023 03 08 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] SET_FEATURE(port) = SetPortFeature

 ポート2への電源供給を開始。

SETUPADR=2ENP=0DATA023 03 08 00 03 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] SET_FEATURE(port) = SetPortFeature

 ポート3への電源供給を開始。この HUB は実際には2ポートだが、何故か4ポートだと自己主張しているようだ。

SETUPADR=2ENP=0DATA023 03 08 00 04 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] SET_FEATURE(port) = SetPortFeature

 ポート4への電源供給を開始。

SETUPADR=2ENP=0DATA023 01 10 00 01 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート1の接続ステータス変化フラグ(C_PORT_CONNECTION)を初期化。

SETUPADR=2ENP=0DATA023 01 10 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート2の接続ステータス変化フラグ(C_PORT_CONNECTION)を初期化。

SETUPADR=2ENP=0DATA023 01 10 00 03 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート3の接続ステータス変化フラグ(C_PORT_CONNECTION)を初期化。

SETUPADR=2ENP=0DATA023 01 10 00 04 00 00 00ACK
INADR=2ENP=0DATA1ACK

[HUB Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート4の接続ステータス変化フラグ(C_PORT_CONNECTION)を初期化。

SETUPADR=2ENP=0DATA0A3 00 00 00 01 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
INADR=2ENP=1NAK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート1のステータスを取得。この時点ではまだ HUB には何も繋いでおらず、その通りの結果が返っている(1ビットだけフラグが立っている所は、ポートが電源供給状態にあることを示す)。

 三行目にあるエンドポイント1に対する IN は、インタラプト転送により定期的に行われる HUB の状態変化フラグの取得であり、SETUP〜IN(二行目)〜OUT からなるセットアップ転送とは別の転送である(ちなみに変化が無かったので NAK が返されている)。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。結果は同じ。

SETUPADR=2ENP=0DATA0A3 00 00 00 03 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート3のステータスを取得。結果は同じ。

SETUPADR=2ENP=0DATA0A3 00 00 00 04 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート4のステータスを取得。結果は同じ。

INADR=2ENP=1NAK

 しばらく IN と NAK が続くので省略。Windows が HUB のドライバをロードしている模様。

SETUPADR=2ENP=0DATA000 03 01 00 00 00 00 00ACK
INADR=2ENP=0DATA1ACK

SET_FEATURE(device)

 HUB に DEVICE_REMOTE_WAKEUP を設定。

SETUPADR=2ENP=0DATA000 01 01 00 00 00 00 00ACK
INADR=2ENP=0DATA1ACK

CLEAR_FEATURE(device)

 HUB の DEVICE_REMOTE_WAKEUP を解除。設定した後に解除する理由は不明。

INADR=2ENP=1DATA004ACK

 ここで HUB のポートにマウスを接続。ポート2の状態が変化したというデータが返ってくる。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA101 03 01 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_CONNECTION(デバイスが存在する)、C_PORT_CONNECTION(接続状態が変化した)という結果が返ってきた。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA101 03 01 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 再度、ポート2のステータスを取得。繰り返す理由は不明。結果は同じ。

SETUPADR=2ENP=0DATA023 01 10 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[Hub Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート2の接続ステータス変化フラグ(C_PORT_CONNECTION)を初期化。

SETUPADR=2ENP=0DATA0A3 00 00 00 01 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート1のステータスを取得。電源供給のみ。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA101 03 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_CONNECTION(デバイスが存在する)。

INADR=2ENP=1NAK

 4回ほど IN と NAK が続くので省略。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA101 03 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_CONNECTION(デバイスが存在する)。

SETUPADR=2ENP=0DATA023 03 04 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[Hub Class] SET_FEATURE(port) = SetPortFeature

 ポート2をリセット。

INADR=2ENP=1DATA104ACK

 HUB のポート2が変化。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA103 03 10 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_ENABLE(ポートが動作可能)、PORT_CONNECTION(デバイスが存在する)、C_PORT_CONNECTION(接続状態が変化)。

SETUPADR=2ENP=0DATA023 01 14 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[Hub Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート2のリセットステータス変化フラグ(C_PORT_RESET)を初期化。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA103 03 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_ENABLE(ポートが動作可能)、PORT_CONNECTION(デバイスが存在する)。

INADR=2ENP=1NAK

 前回から HUB の状態変化なし。

PRESETUPADR=0ENP=0DATA080 06 00 01 00 00 40 00ACK
PREINADR=0ENP=0DATA112 01 00 01 00 00 00 08PREACK
PREINADR=0ENP=0DATA0FE 05 11 00 00 00 01 02PREACK
PREINADR=0ENP=0DATA100 01PREACK
PREOUTADR=0ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 この時点で、HUB のポート2に接続したマウスがアドレス0でアクセス出来るようになっている。マウスのデバイスデスクリプタを取得。

 以後、HUB を経由しての Low Speed 通信が行われるが、ホストから HUB 経由で Low Speed デバイスにパケットを送る場合は直前に PRE パケットを送信する必要がある。ここでは SETUP、DATA1、DATA0、ACK が該当する。Low Speed デバイスから HUB 経由でホストにパケットが送られる場合は PRE パケットは必要ない。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=1NAK
INADR=2ENP=0DATA103 03 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_ENABLE(ポートが動作可能)、PORT_CONNECTION(デバイスが存在する)。

SETUPADR=2ENP=0DATA023 03 04 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[Hub Class] SET_FEATURE(port) = SetPortFeature

 ポート2をリセット。

INADR=2ENP=1DATA004ACK

 HUB のポート2が変化。

SETUPADR=2ENP=0DATA0A3 00 00 00 02 00 04 00ACK
INADR=2ENP=0DATA103 03 10 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート2のステータスを取得。PORT_LOW_SPEED(Low Speed デバイスが接続)、PORT_POWER(ポートが電源供給状態にある)、PORT_ENABLE(ポートが動作可能)、PORT_CONNECTION(デバイスが存在する)、C_PORT_RESET(リセット処理が完了した)。

SETUPADR=2ENP=0DATA023 01 14 00 02 00 00 00ACK
INADR=2ENP=0DATA1ACK

[Hub Class] CLEAR_FEATURE(port) = ClearPortFeature

 ポート2のリセットステータス変化フラグ(C_PORT_RESET)を初期化。

INADR=2ENP=1NAK

 前回から HUB の状態変化なし。以後省略。

PRESETUPADR=0ENP=0DATA000 05 01 00 00 00 00 00ACK
PREINADR=0ENP=0DATA1PREACK

SET_ADDRESS addr = 1

 マウスのデバイスアドレスを1に設定。

INADR=2ENP=1NAK

PRESETUPADR=1ENP=0DATA080 06 00 01 00 00 12 00ACK
PREINADR=1ENP=0DATA112 01 00 01 00 00 00 08PREACK
PREINADR=1ENP=0DATA0FE 05 11 00 00 00 01 02PREACK
PREINADR=1ENP=0DATA100 01PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 マウスのデバイスデスクリプタを取得。

PRESETUPADR=1ENP=0DATA080 06 00 02 00 00 09 00ACK
PREINADR=1ENP=0DATA109 02 22 00 01 01 04 A0PREACK
PREINADR=1ENP=0DATA032PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 マウスのコンフィギュレーションデスクリプタを取得。

PRESETUPADR=1ENP=0DATA080 06 00 02 00 00 FF 00ACK
PREINADR=1ENP=0DATA109 02 22 00 01 01 04 A0PREACK
PREINADR=1ENP=0DATA032 09 04 00 00 01 03 01PREACK
PREINADR=1ENP=0DATA102 05 09 21 00 01 00 01PREACK
PREINADR=1ENP=0DATA022 36 00 07 05 81 03 04PREACK
PREINADR=1ENP=0DATA100 0APREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 マウスのコンフィギュレーションデスクリプタと、それに続くインタフェースデスクリプタ、エンドポイントデスクリプタを一括して取得。

SETUPADR=2ENP=0DATA0A3 00 00 00 03 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート3のステータスを取得。電源供給のみ。

SETUPADR=2ENP=0DATA0A3 00 00 00 04 00 04 00ACK
INADR=2ENP=0DATA100 01 00 00ACK
OUTADR=2ENP=0DATA1ACK

[Hub Class] GET_STATUS(port) = GetPortStatus

 ポート4のステータスを取得。結果は同じ。

INADR=2ENP=1NAK

PRESETUPADR=1ENP=0DATA080 06 00 03 00 00 FF 00ACK
PREINADR=1ENP=0DATA104 03 09 04PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 マウスのストリングデスクリプタ、インデックス 0x00(=対応している言語 ID の配列)を取得。0x0409 は English(United States)を表す。

PRESETUPADR=1ENP=0DATA080 06 02 03 09 04 FF 00ACK
PREINADR=1ENP=0DATA138 03 50 00 53 00 32 00PREACK
PREINADR=1ENP=0DATA02F 00 55 00 53 00 42 00PREACK
PREINADR=1ENP=0DATA120 00 42 00 72 00 6F 00PREACK
PREINADR=1ENP=0DATA077 00 73 00 65 00 72 00PREACK
PREINADR=1ENP=0DATA120 00 43 00 6F 00 6D 00PREACK
PREINADR=1ENP=0DATA062 00 6F 00 20 00 4D 00PREACK
PREINADR=1ENP=0DATA16F 00 75 00 73 00 65 00PREACK
PREINADR=1ENP=0DATA0PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string) "PS2/USB Browser Combo Mouse"

 マウスのストリングスデスクリプタ、インデックス 0x02 を取得。

PRESETUPADR=1ENP=0DATA080 06 00 03 00 00 FF 00ACK
PREINADR=1ENP=0DATA104 03 09 04PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、マウスのストリングスデスクリプタ、インデックス 0x00 を取得。

PRESETUPADR=1ENP=0DATA080 06 02 03 09 04 FF 00ACK
PREINADR=1ENP=0DATA138 03 50 00 53 00 32 00PREACK
PREINADR=1ENP=0DATA02F 00 55 00 53 00 42 00PREACK
PREINADR=1ENP=0DATA120 00 42 00 72 00 6F 00PREACK
PREINADR=1ENP=0DATA077 00 73 00 65 00 72 00PREACK
PREINADR=1ENP=0DATA120 00 43 00 6F 00 6D 00PREACK
PREINADR=1ENP=0DATA062 00 6F 00 20 00 4D 00PREACK
PREINADR=1ENP=0DATA16F 00 75 00 73 00 65 00PREACK
PREINADR=1ENP=0DATA0PREACK
INADR=2ENP=1NAK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string) "PS2/USB Browser Combo Mouse"

 再度、マウスのストリングスデスクリプタ、インデックス 0x02 を取得。

 下から二行目の IN は HUB に対する状態変化フラグの取得。

INADR=2ENP=1NAK

 しばらく続くので省略。

PRESETUPADR=1ENP=0DATA080 06 00 03 00 00 FF 00ACK
PREINADR=1ENP=0DATA104 03 09 04PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、マウスのストリングスデスクリプタ、インデックス 0x00 を取得。

PRESETUPADR=1ENP=0DATA080 06 02 03 09 04 FF 00ACK
PREINADR=1ENP=0DATA138 03 50 00 53 00 32 00PREACK
PREINADR=1ENP=0DATA02F 00 55 00 53 00 42 00PREACK
PREINADR=1ENP=0DATA120 00 42 00 72 00 6F 00PREACK
PREINADR=1ENP=0DATA077 00 73 00 65 00 72 00PREACK
PREINADR=1ENP=0DATA120 00 43 00 6F 00 6D 00PREACK
PREINADR=1ENP=0DATA062 00 6F 00 20 00 4D 00PREACK
PREINADR=1ENP=0DATA16F 00 75 00 73 00 65 00PREACK
PREINADR=1ENP=0DATA0PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string) "PS2/USB Browser Combo Mouse"

 再度、マウスのストリングスデスクリプタ、インデックス 0x02 を取得。

PRESETUPADR=1ENP=0DATA080 06 00 03 00 00 FF 00ACK
PREINADR=1ENP=0DATA104 03 09 04PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string)

 再度、マウスのストリングスデスクリプタ、インデックス 0x00 を取得。

PRESETUPADR=1ENP=0DATA080 06 02 03 09 04 FF 00ACK
PREINADR=1ENP=0DATA138 03 50 00 53 00 32 00PREACK
PREINADR=1ENP=0DATA02F 00 55 00 53 00 42 00PREACK
PREINADR=1ENP=0DATA120 00 42 00 72 00 6F 00PREACK
PREINADR=1ENP=0DATA077 00 73 00 65 00 72 00PREACK
PREINADR=1ENP=0DATA120 00 43 00 6F 00 6D 00PREACK
PREINADR=1ENP=0DATA062 00 6F 00 20 00 4D 00PREACK
PREINADR=1ENP=0DATA16F 00 75 00 73 00 65 00PREACK
PREINADR=1ENP=0DATA0PREACK
INADR=2ENP=1NAK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(string) "PS2/USB Browser Combo Mouse"

 再度、マウスのストリングスデスクリプタ、インデックス 0x02 を取得。

PRESETUPADR=1ENP=0DATA080 06 00 01 00 00 12 00ACK
PREINADR=1ENP=0DATA112 01 00 01 00 00 00 08PREACK
PREINADR=1ENP=0DATA0FE 05 11 00 00 00 01 02PREACK
PREINADR=1ENP=0DATA100 01PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(device)

 マウスのデバイスデスクリプタを取得。

PRESETUPADR=1ENP=0DATA080 06 00 02 00 00 09 00ACK
PREINADR=1ENP=0DATA109 02 22 00 01 01 04 A0PREACK
PREINADR=1ENP=0DATA032PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 マウスのコンフィギュレーションデスクリプタを取得。

PRESETUPADR=1ENP=0DATA080 06 00 02 00 00 22 00ACK
PREINADR=1ENP=0DATA109 02 22 00 01 01 04 A0PREACK
PREINADR=1ENP=0DATA032 09 04 00 00 01 03 01PREACK
PREINADR=1ENP=0DATA102 05 09 21 00 01 00 01PREACK
PREINADR=1ENP=0DATA022 36 00 07 05 81 03 04PREACK
PREINADR=1ENP=0DATA100 0APREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(configuration)

 マウスのコンフィギュレーションデスクリプタと、それに続くインタフェースデスクリプタ、エンドポイントデスクリプタを一括して取得。

PRESETUPADR=1ENP=0DATA000 09 01 00 00 00 00 00ACK
PREINADR=1ENP=0DATA1PREACK

SET_CONFIGURATION Conf.val = 1

 マウスのコンフィギュレーション番号を設定。

INADR=2ENP=1NAK

PRESETUPADR=1ENP=0DATA021 0A 00 00 00 00 00 00ACK
PREINADR=1ENP=0DATA1PREACK

[HID Class] GET_INTERFACE(interface) = SetIdle

 マウスのインターフェース0のアイドルモードを設定。全ての Input リポートを、状態変化時のみデータを返すように設定している(データが無ければ NAK を返す)。

PRESETUPADR=1ENP=0DATA081 06 00 22 00 00 76 00ACK
PREINADR=1ENP=0DATA105 01 09 02 A1 01 09 01PREACK
INADR=2ENP=1NAK
PREINADR=1ENP=0DATA0A1 00 05 09 19 01 29 05PREACK
PREINADR=1ENP=0DATA115 00 25 01 95 05 75 01PREACK
PREINADR=1ENP=0DATA081 02 95 01 75 03 81 01PREACK
PREINADR=1ENP=0DATA105 01 09 30 09 31 09 38PREACK
PREINADR=1ENP=0DATA015 81 25 7F 75 08 95 03PREACK
PREINADR=1ENP=0DATA181 06 C0 09 3C C0PREACK
PREOUTADR=1ENP=0DATA1ACK

GET_DESCRIPTOR(interface) = GetHidReportDescriptor

 マウスのインターフェース0の HID リポートデスクリプタを取得。

 なお、USB Streamscope Ver.1.0.5.2 では「GET_DESCRIPTOR(CS_CONFIGURATION)」と表示され、 デスクリプタの内容も間違った解釈を行って表示するので注意すること。

INADR=2ENP=1NAK

PREINADR=1ENP=1DATA000 FF FF 00PREACK

 マウスから移動量・ボタンのデータを読み込み。この時マウスをぐりぐり動かしていたため、それらしき値が返ってきた。

 以下、マウスのデータの読み込みと、HUB のステータス読み込み(全部 NAK)が続く。

PREINADR=1ENP=1DATA100 FD F9 00PREACK
PREINADR=1ENP=1DATA000 FF 00 00PREACK

INADR=2ENP=1NAK

PREINADR=1ENP=1DATA100 00 FF 00PREACK

 しばらく同様なので省略。

PREINADR=1ENP=1NAK

 ここでマウスを放したため、マウスの移動量0、ボタンの状態変化なしとなり、 マウスからのデータ送信がキャンセルされて NAK が返っている。


Windows による HUB の制御手順

 ログを参考に、Windows による HUB の制御手順をおおまかにリストアップしてみる。 はじめて繋げたデバイスなので、通常より処理が多いかもしれない。

  1. HUB の認識を行う。
  2. HUB クラスデスクリプタを取得し、ポート数を調べる。… GetHubDescriptor
  3. HUB のステータスを調べる。… GetStatus
  4. HUB のコンフィギュレーション番号を設定する。… SetConfiguration
  5. 各ポートの電源供給を開始する。… SetPortFeature(PORT_POWER)
  6. 各ポートの接続ステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_CONNECTION)
  7. 各ポートのステータスを調べる(恐らく、デバイスが接続されていたら認識を行うものと思われる)。… GetPortStatus
  8. HUB に DEVICE_REMOTE_WAKEUP を設定し、すぐに解除する。… SetFeature/ClearFeature(DEVICE_REMOTE_WAKEUP)
  9. インタラプト転送にて、HUB のステータス変化フラグを定期的に読み込む。
  10. ステータス変化が発生していれば、変化したポートのステータスを調べる。… GetPortStatus
  11. デバイスが接続されていたら、以下のようにデバイスの認識を行う。
  12. ポートの接続ステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_CONNECTION)
  13. ポートのステータスを調べる。ここでデバイスの速度(Low/Full)が判明。… GetPortStatus
  14. ポートをリセットする。… SetPortFeature(PORT_RESET)
  15. ポートのステータスを調べる。… GetPortStatus
  16. ポートのリセットステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_RESET)
  17. ポートのステータスを調べる。… GetPortStatus
  18. マウスのデバイスデスクリプタを取得する。
  19. ポートのステータスを調べる。… GetPortStatus
  20. ポートをリセットする。… SetPortFeature(PORT_RESET)
  21. ポートのステータスを調べる。… GetPortStatus
  22. ポートのリセットステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_RESET)
  23. マウスの認識を行う。

最小制御手順

 ログや資料から、最低限必要と思われる制御手順を考えてみる。 X680x0、Nereid、USB1.1 という環境で使用するドライバを作成するのがそもそもの目的なので、 とりあえず必要なさそうな部分は無視する。

  1. HUB の認識を行う。
  2. 各ポートの電源供給を開始する(リセット直前でもいい?)。… SetPortFeature(PORT_POWER)
  3. 各ポートの接続ステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_CONNECTION)
  4. 各ポートのステータスを調べる(デバイスが接続されていたら認識を行う)。… GetPortStatus
  5. インタラプト転送にて、HUB のステータス変化フラグを定期的に読み込む。
  6. ステータス変化が発生していれば、変化したポートのステータスを調べる。… GetPortStatus
  7. デバイスが接続されていたら、以下のようにデバイスの認識を行う。
  8. ポートの接続ステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_CONNECTION)
  9. ポートのステータスを調べる。ここでデバイスの速度(Low/Full)を判別。… GetPortStatus
  10. ポートをリセットする。… SetPortFeature(PORT_RESET)
  11. ポートのリセットステータス変化フラグをクリアする。… ClearPortFeature(C_PORT_RESET)
  12. マウスの認識を行う。

goto サイトトップ