こうした転送方式の違いは、様々な転送に影響してくる。まずはControl Transfer。Control TransferはApplicationとかDriverなどのSoftwareと、USB Device内のFunction(特定の機能)の間でConfiguration/Command/Statusといったメッセージを取り交わすための転送である。全てのDeviceはこのControl Transferをサポートする事が義務付けられている。

USB 2.0ではHost→DeviceやDevice→HostのControl Transferにおけるデータの転送やその取り扱い方式が事細かに決められているが、これらについてはUSB 3.0でも基本的には変わっていない。ただし幾つかの相違点は当然あり、

  • USB 2.0においては、Control TransferのBandwidthについて、これをDeviceあるいはSoftwareが明示的に指定するといった事は出来なかった。USB 3.0についてもこれは同じだが、Bandwidthに関してはBest effortを提供できるような仕組みが入った。これに伴い、Control TransferのData Payload sizeの最大値は512Byte固定となり、また全てのDeviceはDevice DescriptorのbMaxPacketSizeに09Hを入れる事が必須となった
  • 複数のEndpointで、Control/Bulk Transferが待機状態にある場合、Host ControllerはFair access policyに従ってControl Transferから優先的に処理する(ただしこの際のpolicyの実装はHost Controllerの実装に依存

となっている。

2番目の項目が意味不明かもしれないが、USB 2.0まではそもそもHost ControllerがRound Robin方式に全Endpointを一定のTime Slot間隔でサーチして、そこで順次処理をするという方式だったから、そもそもControl/Bulk TransferのPendingという事態そのものが発生しなかった訳で、非同期にEndpoint→HostにNotificationを送れるUSB 3.0ならではの追加とも言える。

またBulk Transferについても変更がある。Bulk Transferは大量のデータ転送(HDDの接続などその好例だろう)とかStreaming(USB Speakerとか、最近だとUSB TV Tunerなどがこれにあたるだろう)に向いた転送方式で、USB 3.0でもこの方式を当然サポートしている訳だが、基本的な特徴である、

  • Bandwidth-available basis(転送の中で最もPriorityが低いので、帯域が余って居れば高速に転送できるが保障されない)
  • データの転送そのものは保障されるが、BandwidthやLatencyは一切保障なし

はそのまま継承している。

では何が変わったかというと、まずUSB 2.0ではBus Errorなどの場合にProtocol LevelでTransfer Retryがサポートされていたが、USB 3.0ではProtocol LevelではError Freeが保障される形になった。これはLink LayerでError DetectionとかRetryがサポートされるので、Protocolでは考える必要がなくなったということだ。

また大きな追加点として、Protocol LevelでMulti-stream modelをサポートするようになった事が挙げられよう。これまでは、複数のStream Deviceを1つのHost Controllerにぶら下げる場合、素性が悪いデバイスだと2つ目のDeviceを繋いだ瞬間に転送がまともに行われなくなったりするケースがあったが、USB 3.0ではこうした問題への解決に一歩前進した形だ。

Photo01はこのMulti-streamの模式図である。HostとDeviceは、Stream TransferのHandshakeを行うが、この際にStream IDと呼ばれるUnique IDをそのHandshake毎に割り当てる形になる。FunctionあるいはEndpointは、従来と同様にStream PIPEに対してデータを送出あるいはStream PIPEからデータを受け取る形になるが、これまではStream PIPEがController Domain全体で一つだったのが、今度は仮想的に複数持てるようになった、という事だ。

Photo01: Universal Serial Bus Specification 3.0のFigure 4-3より抜粋

実体としては、Stream PIPEの前後にMUX/DEMUXを配して、

MUX : パケットにStreamIDで紐付けする
DEMUX : パケットのStreamIDを元に分配する

という事になる。このMUX/DEMUXは、共通のCStreamID(Current StreamID)を持ち、これで現在どのStreamIDのパケットを処理するか管理する、というわけだ。

(続く)