USBエンドポイント最大パケットサイズ不一致:wMaxPacketSize、ショートパケット、バルク転送、ファームウェアバッファバグのデバッグ
USBエンドポイントの最大パケットサイズ不一致、wMaxPacketSizeディスクリプタエラー、ショートパケット、バルク転送ストール、High-Speed vs Full-Speedの差、ファームウェアバッファバグをデバッグする方法を解説します。
USBエンドポイントの wMaxPacketSize は小さなディスクリプタ項目に見えますが、値が間違っているとバルク転送・インタラプトレポート・High-Speed動作・ファームウェアバッファリング・ホストドライバの前提がまとめて崩れます。特定のサイズや速度でだけ転送が失敗するとき、USB wMaxPacketSize mismatch、USB short packet problem、bulk transfer stops at 64 bytes、USB endpoint packet size high speed full speed、USB descriptor max packet size bug で検索されます。
Bus Scopeが効くのは、失敗が「ディスクリプタ」と「実際のパケット」を並べて比較して初めて見えるものだからです。ディスクリプタは特定のパケットサイズを主張しているのに、ファームウェア/ホストコード/エンドポイントハードウェアが別のサイズで振る舞っている、ということが普通に起きます。
wMaxPacketSizeが制御するもの
各エンドポイントディスクリプタには wMaxPacketSize が含まれます。これはホストに対し「そのエンドポイントの最大ペイロード」を伝えます。一般的な値は速度とエンドポイント種別で決まります。
例:
- Full-Speedバルクエンドポイントは多くが64バイト
- High-Speedバルクエンドポイントは多くが512バイト
- インタラプトエンドポイントは速度とintervalで変わる
- アイソクロナスエンドポイントは帯域固有のパケットサイズ
ファームウェアがエンドポイントバッファを64バイトで構成しているのに512バイトを提示すると、ホストはデバイスが正しく扱えない転送を送ってきます。
よくある症状
最大パケットサイズ由来バグの症状:
- バルク転送は小さいメッセージでは成功するが、大きいと失敗
- Full-Speedでは動くがHigh-Speedで失敗
- 64バイトちょうどで転送が止まる
- ホストがショートパケットをいつまでも待つ
- ファームウェアが想定外の分割データを受け取る
- OUT転送をデバイスがストール
- IN転送が短縮データを返す
- トラフィックがあるのにドライバがタイムアウトを報告
- 複合デバイスで1つのインターフェースだけ動かない
バイトカウントがそのままヒントになるケースが多いです。
ショートパケットの挙動
USBバルク転送では、要求長が実データより大きい場合にショートパケットで「転送の終わり」を示すことがあります。デバイスがちょうど最大パケットサイズの倍数を返しただけだと、長さが別途定義されていない限り、またはZero-Length Packetを送らない限り、ホストは追加データを待ち続けます。
例:
max packet size: 64
payload length: 128
packets: 64 + 64
end condition: ambiguous unless length is known or ZLP is sent
だからこそ「USB short packet」「USB zero length packet」が強い検索ワードになります。単純なテストは通っても、ペイロード長がパケット境界に乗った瞬間に固まるデバイスは普通にいます。
High-Speed vs Full-Speedの不一致
Full-Speedでは正しく動くデバイスが、High-Speedで失敗することがあります。原因は:
- High-Speedディスクリプタが512バイトを提示
- ファームウェアのバッファは64バイトのまま
- High-SpeedでDMAアラインメントが変わる
- エンドポイントFIFOが小さすぎる
- ホストドライバがHigh-Speedパケット化を前提にしている
- デバイスディスクリプタが速度モード間で異なる
Bus Scopeは、列挙速度・エンドポイントディスクリプタの値・実際の転送チャンクを比較する手助けをします。
ディスクリプタのコピペエラー
ファームウェアチームは、エンドポイントディスクリプタをインターフェース間やモード間でコピーしがちです。これが地味なバグを生みます。
- インタラプトエンドポイントがバルク的なサイズを提示
- OUTとINでエンドポイントサイズが想定外に違う
- Alternate Settingでサイズが変わるのにファームウェアがエンドポイントを再構成しない
- Full-SpeedとHigh-Speedのディスクリプタツリーが一致しない
- 関連ディスクリプタが期待スループットと噛み合わない
正しい診断ビューは、エンドポイントアドレスとディスクリプタ、そのエンドポイント上の全転送を結びつけます。
ファームウェアのバッファバグ
ディスクリプタが正しくても、ファームウェアのデータ処理が間違っていることがあります。
- 1つのUSBパケットを1つのアプリメッセージと決め打ち
- 分割メッセージを扱えない
- Zero-Length Packetを落とす
- ショートパケットをエラー扱いする
- 最初のパケット受信後に受信バッファを上書きする
- 転送長が最大パケットサイズと一致する場合に失敗する
- 最終ショートパケット後にINエンドポイントをフラッシュしない
ベンダー固有デバイスやブートローダでは定番バグです。プロトコルが独自なので。
ホストドライバの思い込み
ホスト側コードも間違えます。たとえば:
- バッファを小さくとりすぎる
- 1回のreadコール=1デバイスメッセージと決め打ち
- ショートパケット終了を無視
- タイムアウトに頼り、プロトコル長フレーミングを使わない
- ファームウェアバッファより大きいコマンドを送る
- Zero-Length Packetの扱いを忘れる
両側が独自実装のときは、パケットトレースそのものが「契約」になります。
取得すべき証拠
最大パケットサイズの診断では、以下を集めます。
- デバイス速度
- エンドポイントディスクリプタ
- エンドポイントアドレスと方向
wMaxPacketSize- ホストが要求した転送サイズ
- 実際のパケットサイズ
- ショートパケット/Zero-Length Packetの有無
- 転送後のSTALL/NAK/タイムアウト/リセット
- Full-Speed/High-Speed列挙の差
- 可能なかぎりファームウェアログ
最良のレポートはバイト数を正確に残すもの。検索エンジンもこうした実用的な詳細を拾います。
デバッグチェックリスト
次の流れで作業すると、原因に早くたどり着けます。
- 対象エンドポイントのディスクリプタを特定する
wMaxPacketSizeを記録する- 速度モードを比較する
- 最大パケットサイズ未満/等しい/超えるペイロードを送る
- 最大パケットサイズの倍数境界を試す
- ショートパケット/Zero-Length Packetを探す
- 最終パケット後にホストが待っていないか確認する
- IN/OUTエンドポイントの挙動を比較する
- Alternate Setting変更時の挙動を確認する
- 失敗する転送シーケンスを保全する
最終的な診断
USBエンドポイント最大パケットサイズのバグは、ディスクリプタ・転送・ファームウェア契約の問題です。有用な証拠は、提示された wMaxPacketSize、実際のパケット化、ショートパケットの挙動、Zero-Length Packet処理、速度モード、エンドポイント固有の失敗です。
Bus Scopeは、バグが「ディスクリプタ」「ファームウェアバッファ処理」「ホストドライバの思い込み」「転送フレーミング」のどれにあるかを、ファームウェアエンジニアが証明する手助けをします。