次がInterrupt Transferである。45回目でも触れたとおり、Interrupt Transferは非同期に割り込まれて、かつ伝達保障(正確に言えば、転送に要するLatencyの最大値保障)が行われる通信方式である。

ちなみに見かけ上(つまりApplication Layerや更にその上のユーザーから見た場合)、Interrupt TransferはDevice側がイベントを発生するとそれに合わせて転送が行われる形になるから、あたかもDevice→HostへのInterruptが発生している様に見えるし、Deviceから見ても実はデータをInterrupt PIPEに突っ込んでおけば勝手に転送が行われているわけで、あたかもInterrupt PIPEにデータを入れればInterruptが上がるように扱える。

が、こうしたInterrupt伝達メカニズムはUSB 1.1/2.0にもUSB 3.0にも含まれていない。厳密に言えば、Device NotificationというメカニズムがUSB 3.0で追加され、Device→Hostに任意のタイミングでTPを送ることが出来るようになったが、これはあくまでも電力管理に関するものであるという話は14回目でも説明した通り。35回目で具体的なDevice Notificationの詳細を示しているが、ご覧のとおり電源管理かBus Interval Adjustmentに関係するケースしか想定していない。

勿論インプリメントは、普段は電源をSleep Modeに保っておき、動きがあった場合のみActive、終わったら再びSleepに戻るといったマウスを作れば、事実上Device Notificationを使ってマウスイベントを通知できることになる。ただし、Sleep→Wakeupの時間的なオーバーヘッドが馬鹿にならないことを考えると、インプリメントとしてみた場合にはDevice Notificationを使わない方がオーバーヘッドが少なそうだ。特に最近ゲーム向けとかのハイエンドレーザーマウスだと解像度が5,000dpiを超えており、極限までタイムラグを減らすような工夫が施されている訳で、少なくともこうした用途であればむしろ不利になりそうな気がする(このあたりはきちんと試算したわけではないが、Sleep→Activeの間にLFPSのシーケンスが入ることを考えると、かなり時間的なLatencyは大きいように思われる)。

そんなわけで、USB 1.1/2.0においても、USB 3.0においても、Interrupt TransferそのものはHost側がその必要性を判断して、必要ならば転送をかけるというシーケンスになる。これもあり、ProtocolそのものはBulk Transferと殆ど変わらない(Photo01)。

Photo01: USB 1.1/2.0の場合、例えばInterrupt INでエラーがあった場合、HostはDeviceに何も返さないし、Interrupt OUTでエラーがあった場合はDeviceはHostにエラーを返さない。このあたりのインプリメントはUSB 2.0と異なる部分である。

相違点としては、

  • Bulk Transferは、1回当たり最大3パケットまでに制限される。
  • 頻度が異なる(Interrupt Transferは、そのDeviceへのService Intervalの期間中は何回でも連続して行うことが出来る)。
  • エラー対応(通信エラーがあってもRetryは行わない。ただしERDY TPの場合はそのままTranscationを継続して待機する)。

といったあたりだろうか。DPに合わせて毎回ACKを送ることはBulk Transferと変わらないが、こちらはUSB 2.0との相違という事になる。

ところで伝達保障についてもう少し。Interrupt Transferは、あるService Intervalの期間は常に転送が行える事を保障しているが、逆に何らかの理由でDevice側がInterrupt Transferを行いたくない場合があるとする(Photo02)。その場合、DeviceはHostからのACK TPに対してNRDY TPを返すだけでよい。するとHostは、次にDeviceからERDY TPが来るまでの間は、そのDeviceに対してInterrupt Transferを行わない。

Photo02: 図には2×bIntervalとあるが、これはちょっと省略しすぎ。そもそもInterrupt TransferのService Intervalは125μsを最小単位とし、Interval=125×2^(bInterval-1)μsと規定されている(bInterval:1~16)。このbIntervalはDevice毎に異なっているので、実際には2×125×2^(bInterval-1)=125×2^(bInterval)μs以内に再送を開始する、ということになる。

で、一度DeviceからERDY TPが到着したら再びサービスを開始することになるが、問題はそのERDYが届くタイミングが予想できないことだ。このため、次のService Intervalが来るまでまるまる待たされる場合があることだ。Specificationによれば、各Device毎のService Interval期間の2倍未満の範囲でACK TPを送り出すようにとここでは規定されている。

(続く)