具体的なInterrupt Transferの手順だが、まずInterrupt IN(Device→HostのInterrupt)の場合である。HostはInterrupt INの転送を始めたいと思ったときに、Endpointに対しACK TPを送る。面白いのはここで、Sequence NumberとNumber of Packetsに「予想される数」をあらかじめ入れておくことだ。ここでDeviceが本当にInterrupt INを行える状態にある場合、HostからのACK TPと同じService Interval内に、Number of Packetsで指定されただけのDPをHostに送り返すことになる(Photo01)。

Interrupt INの場合、Deviceの側で後からPacket数を変えるということは出来ない。例えばマウスの場合、そのマウスが移動していなければ0になるが、大きく移動しているときに「前回Interrupt INでデータを送って以来の変化量」だけを送ると、必ずしも動作が忠実になっていない事がありえる。

例えば図1の様に、画面の左上から右端までマウスポインタを動かすときに、一直線ではなく左右に振りながら変化させることを考える。ここでものすごく高速に移動させたため、この一連の動きが1回のService Interval内で収まってしまった、と仮定しよう(いや実際にこんなことをやったら腕が千切れそうな気もするが、単にマウスのみならずボタンクリックまで含めると、まるで無いとは言い切れない。良く訓練されたゲーマーが、先押しすれば不可能では無い様に思う)。ここで単に途中の変量を一切無視すると、実際のマウスの軌跡は図2の様になってしまう。これは操作性に若干問題がありと判断されるだろう。

そんなわけで実際は、Service Intervalを出来るだけ短くするか、もう一つの解は図3の様にマウスが定期的に別の中間点を(例えば一定時間毎に)取得するとか、一定の距離を移動すると取得するなどして内部のメモリに蓄えておき、次のInterrupt INの際にまとめて送り出す形になる。前者の場合、最小単位が125μsになるからこれ以下の頻度では転送できないし、この頻度で転送を常に行っているとUSB全体の負荷が馬鹿にならない。後者の場合(今の話題に関係する話だが)、1回のInterrupt INの際にどれだけのデータ量になるかが今度はわからないということになる。勿論例えば「中間点の座標は最新の10個まで」とか決めて、ここから溢れたものは捨てて行くといったアプローチを取ればいいわけだが、数が少ないと折角中間点を保存した意味が薄れるし、だからといって巨大なバッファを取って「毎回DPを3つフルに送る」なんて仕様にしてしまうと今度はシステム全体のパフォーマンスに影響する事になる。今はマウスを例に取ったが、ゲームコントローラの類でもこうした話は当然出てくるわけで、このあたりをどの程度のバランスとするかはデバイス設計者に任されている形だ。

話を戻すと、そんなわけでデータがあれば(無いから送らない、という選択肢は無いので、無い場合は「データが無い」というデータを送る形で対処するのが一般的だ)DPをDevice→Hostに転送。Hostはこれを受信したらACK TPを送り返してトランザクション終了である。Photo01にもある様に、1つのService Interval内で2つ目のトランザクションを開始する事はできないので、次回のService IntervalまではもうInterrupt INは発生しない。ちょっと面白いのはSequence Numberで、これはそのDeviceに対するInterrupt IN Transferが最初に行われた時に0が当てられ、以後これをインクリメントする形になり、明示的にクリアされるのは(桁あふれで0に戻るときか)STALLコマンドが発行される時である。

Photo01: Universal Serial Bus 3.0 SpecificationのFigure 8-35から抜粋

さて、転送が素直に済めばいいが、Device側がBusy状態にある場合はどうするか? というと、Photo02の様にDeviceからNRDY TPを送ることになる。これを受けたHost側は、以後そのDeviceに対するInterrupt INのサービスを停止する。いつまで停止するか? というと、Deviceが自身のBusy状態を解消してERDYをHostに送るまでである。HostはこのERDYを受けたら、一定期間後以内にInterrupt INを再開する(Photo03)。この辺の仕組みは前回紹介した通りだが、再開の際のACK TPのSequence Numberは、先に送ったACK TPと同じものになる、というのがちょっと面白い点である。

Photo02: Universal Serial Bus 3.0 SpecificationのFigure 8-36から抜粋

Photo03: Universal Serial Bus 3.0 SpecificationのFigure 8-37から抜粋

(続く)