USBコントロール転送ステータスステージのデバッグ:Zero-Length Packet、エンドポイントゼロ、SETUP/DATA/STATUS、ストール
USBコントロール転送のステータスステージ問題、Zero-Length Packet、エンドポイントゼロのSTALL、SETUP/DATA/STATUSシーケンス、ディスクリプタリクエスト、ベンダーコマンド失敗をデバッグする方法を解説します。
USBコントロール転送は、デバイスがステータスステージで落ち始めた瞬間に「シンプルそうに見えて複雑」な問題に化けます。ディスクリプタは取得できているのに、あるコマンドだけがストールしたりタイムアウトしたりする——そんな場面で USB control transfer status stage、zero length packet USB、endpoint zero stall、SETUP DATA STATUS USB、control transfer timeout、vendor request fails といった検索がされます。
Bus Scopeが効くのは、コントロール転送の失敗には「すべてのステージをまとめて」見る必要があるからです。Setupパケットだけでは不十分。データステージとステータスステージまで含めて、ホストとデバイスがトランザクションを完走したかどうかが証明できます。
コントロール転送のステージ
通常のコントロール転送は次の構成です。
- SETUPステージ
- (任意の)DATAステージ
- STATUSステージ
ステータスステージは、データステージと逆方向にZero-Length Packetを送ることで完了確認とするのが一般的です。
ステータスステージが失敗すると、デバイスがすでにデータを交換済みでも、ホストはタイムアウトとして報告することがあります。
Zero-Length Packetの混乱
Zero-Length Packetは、アプリ層の意味でいう「データなし」とは限りません。コントロール転送では、Zero-Length Packetは「必要なステータスのハンドシェイク」になり得ます。
よくあるミス:
- ファームウェアがステータスステージをACKしない
- ホストがZero-LengthステータスPacketを期待しているのにSTALLを受け取る
- ステータスが空であるべき場面でデバイスがデータを送る
- ベンダーコマンドはデータステージまで完走するが最終ハンドシェイクで失敗する
- ファームウェアのステートマシンがエンドポイントゼロの武装を忘れる
これらはカスタムベンダーコマンドやブートローダで頻出するバグです。
エンドポイントゼロは特別
エンドポイントゼロは列挙とコントロールリクエストを担います。エンドポイントゼロの状態が壊れると、デバイス全体が不安定になり得ます。
症状:
- 列挙は始まるが後のディスクリプタで失敗
- ベンダーリクエストは1回動くがその後ストール
- コントロール転送の後に抜き差しが必要
- SET_ADDRESS/SET_CONFIGURATIONが不安定
- コントロールパス経由のHIDフィーチャーレポートが失敗
- DFUのdetachリクエストは返すがデバイスがモード変更しない
Bus Scopeは、エンドポイントゼロがストール後に復旧したのか壊れたままなのかを示します。
IN方向/OUT方向のコントロール転送
方向によって、ステータスステージの方向も変わります。
INリクエストの場合:
- ホストがSETUPを送る
- デバイスがDATAを送る
- ホストがステータスのOUT Zero-Length Packetを送る
OUTリクエストの場合:
- ホストがSETUPを送る
- 必要ならホストがDATAを送る
- デバイスがステータスのIN Zero-Length Packetを送る
ファームウェアのバグは、一方向ばかりテストして逆方向が疎かになる傾向があります。
ディスクリプタとベンダーコマンドの失敗
標準ディスクリプタリクエストは、よくテストされたファームウェア経路を使うので動くことが多いです。ベンダー固有リクエストは、カスタムハンドラが長さ・方向・ステータスステージを誤って扱い、失敗しがちです。
証拠:
bmRequestTypebRequestwValuewIndexwLength- 実際のデータ長
- ステータスステージの結果
- STALL、NAK、タイムアウト、リセット
Setupパケットのフィールドは、観測されたステージの挙動と組み合わせて解釈する必要があります。
デバッグチェックリスト
次の流れで作業すると、原因に早くたどり着けます。
- コントロール転送全体をキャプチャする
- SETUPフィールドをデコードする
- 転送方向を確認する
- 期待データ長を確認する
- データステージのバイトを検証する
- ステータスステージの方向を検証する
- Zero-Length Packetを探す
- STALL/タイムアウトを確認する
- 標準リクエストとベンダーリクエストを比較する
- エンドポイントゼロの復旧挙動を保全する
最終的な診断
USBコントロール転送の失敗は、Setupパケットの問題だけでなく、ステータスステージの失敗であることが多いです。Zero-Length Packet、エンドポイントゼロの状態、方向、最終ハンドシェイクが鍵になります。
Bus Scopeは、デバイスがSETUP/DATA/STATUS/ZLP処理/エンドポイントゼロ復旧/ベンダーコマンド処理のどこで落ちたかを、ファームウェアエンジニアが証明する手助けをします。