- Stream N : Nには1~65533(FFFDh)の範囲の値が入る。これはその特定のStream IDを意味する。
- Stream 0 : これはシステム予約の番号なので、Stream Pipeでは利用されない。これはBulk Pipeのデフォルトの番号に割り当てられている。
- Cstream : Current Streamの意味である。要するに現在処理が行われているStream IDを常に示す。当たり前であるが、Streamは見かけ上複数同時に保持して転送が行えるが、これはあくまで見かけ上の話であって、実際には複数のStreamを切り替えながら転送を行うことになる。したがって、USBの上では「現在転送しているStream」を把握しておく必要があり、これは当然HostとDeviceの両方でこの値を管理している。Cstreamはまさしくこの「現在のStream ID」を示すわけで、Stream NとNoStreamのどれかの値が入る。
- LCstream : Last Cstream、つまり直前まで転送を行っていたStreamのStream IDを示す。この値はHostでのみ管理される。
これらの値はいずれもHost側で管理され、Deviceにそれが通知される形になる。そもそもStream IDというものが言ってみれば論理管理番号の様なもので、その値そのものは(0とかNoStreamといった特殊なものを除くと)Deviceには意味が無い値なので、Deviceはこの値を変更したり、その値から何かを推察したり(例えばStream IDが一桁だったら、比較的通信のプライオリティが高いだろうと見做して、転送を一杯掛けようとするとか)してはいけないと定められている。
ところで前回はBulk Stream全体についてSPSMの簡単な模式図を示したが、これをもう少しBreakdownしてみたい。Photo01はBulk IN Streamの場合の模式図(ISPSM:In Stream Protocol State Machine)である。Endpointが構成されたら、まずPipeはDisabled Stateに入る。この状態がPrime Pipe Stateに遷移するのは、Stream IDにPrimeが指定されてACKを受け取った場合である。ここから更にIdle Stateに遷移するのは、やはりStream IDにPrimeが指定されてNRDYを受け取った場合である。
ここで注意すべきは、HostとDeviceの間にHubが入っており、かつこのHubがACK TPをDefered bitを立てて送るケースが考えられることだ(連載の第311回、"USB 3.0の研究(38)"で触れた(2)のケース)。要するにHubが待機状態で処理が間に合ってないケースだが、この結果としてHostとDeviceは共にNRDY TPを送りあうことになる。するとどうなるかというと、Stream IDはPrimeのままだから、HostはPrime Pipe StateからIdle Stateに遷移するし、Deviceは一旦(Defered bitの立った)ACK TPを受け取る事でPrime Pipe Stateに遷移し、続いてNRDY TPを受け取る事でやはりIdle Stateに遷移する。こうしたHubの影響によるState遷移も、ISPSMでは考慮されている。
Idle Stateに遷移すると、ここではStreamの選択(StartStreamないしMoveDataへの遷移)か、Endpoint Bufferの追加/変更通知をHostから受け取る(Prime Pipe Stateへの復帰)のを待つことになる。
ここからMove Dataへの遷移は、Stream IDがStream NかつNumP > 0が指定されたACK TPを受け取る事で行われるし、Start Streamhへの遷移はStream NかつNumP > 0が指定されたERDY TPを受け取る事で行われる。StartStream Stateでは、Deviceが要求したStream IDの転送をHostがAcceptするかRejectするかをまずは待つことになる。HostがこれをRejectする場合、Stream IDにNoStream、NumPに0、そしてPacketPendingにも0をセットしたACK TPを返す。ちなみにこのRejectの理由としては、指定されたStream IDに対するEndpoint Bufferが確保できない場合が挙げられている(逆に言えば、その他のケースでは原則としてAcceptしなければいけない、ということでもある)。これを受けとったら、ISPSMは再びIdle Stateに遷移する。
このISPSMはHostとDeviceの両側で独立に動作するため、例えばDeviceがERDY TPをHostに送って自身はStart Stream Stateに遷移し、その一方HostはStream ID=Prime、Packet Pending=0としたACK TPをDeviceに送って自身はPrime Stateに遷移するといった競合状態が起こりえる。ただこの場合、DeviceがStart Stream StateでHostからのACK TPを受け取ると、DeviceはPrime Pipe ACK Stateに遷移し、ここでHostに対しStream ID=PrimeとしてNRDY TPを送り、自身はIdleに遷移する。一方Hostは送られてきたNRDY TPを受け取ってIdleに戻るという形で競合を解消することになる。
(続く)