これが特定Deviceのみの切り替えだとどうなるか? というのが次なる問題で、今度はシステムでまとめて処理という訳にはいかない。前回のパターンだと、USB 3.0→USB 2.0の場合でも、USB 2.0→USB 3.0の場合でもHost Controller(と、その配下に繋がる全Device)のResetが発生していたが、あるDeviceのみ速度を切り替えたい、というときに一々全DeviceのResetが発生するのはあまり好ましくない。

実装そのものは簡単である。USB 3.0→USB 2.0の場合、当該DeviceはSetPortFeatureのPORT_LINK_STATEを使い、USB 3.0のPortをDisableにし、かつTerminationを(電気的に)外せば、そのDeviceはUSB 3.0として切り離されたものとHubやHostは認識する。なので、後はUSB 2.0として繋ぐだけである。逆にUSB 2.0→USB 3.0のケースでは、まずTerminationを(電気的に)取り付け、やはりSetPortFeatureのPORT_LINK_STATEを使ってRx.Detectにある事を上位に通知し、かつUSB 2.0ポートに対しPORT_RESETをSetPort Featureで通知するという形で、USB 2.0のDisconnectとUSB 3.0のConnectを行う事になる(Photo01)。

Photo01: USB 3.0 HubのDownstream Port的には、対応DeviceがUSB 2.0で繋がっている間はDSPORT.DisabledのStateに居る事になる。

この仕組みそのものは問題ないのだが、問題は「だれがこれをやるか」である。Photo01にもある通り、これは"Software issues"である。この動作の主体はあくまでDeviceなりHubなりであって、ところがDeviceやHubは原則としてSlave Deviceだから、(勿論色々仕込むことは不可能ではないだろうが)基本的にはHost側で動くSoftwareがこうした遷移を管理する必要がある。が、幾らなんでもBase DriverやMiniport DriverがこうしたDevice毎の速度管理を細かくやるとは思えないので、あるとすればそのDeviceに対応したClass Driverやこの上に入るFilter Driverなどがこれを管理するのが現実的だろう。

問題は、こうした事に対応するDriverがどこまであるか、である。そもそもUSB 2.0とUSB 3.0に両対応Deviceが、当初はUSB 3.0で接続されており、何かの理由でUSB 2.0で繋ぎなおされ、その後もう一度USB 3.0で繋ぎなおすなんてシナリオそのものが実は考えにくい。勿論間に物理的な着脱が入るのであれば、「最初はUSB 3.0対応Flash Memoryを直接繋いでいたが、ちょっとポート数が足りなくなり、一時的にUSB 2.0 Hub経由で繋いだ。その後用事が済んだので、再び直接つなぎなおした」なんてケースがまさしくこれにあたるわけで、この場合はそもそもBus全体のResetとして取り扱われるから問題ないのだが。

これに関しては、例えばSpecificationのChapter 11(Interoperability and Power Delivery)を見ても、特に明確な記述はなく、したがって大半のDeviceやHubにとっては、一度何かの理由でUSB 3.0→USB 2.0に速度変更した場合、バス全体のリセットか、あるいはケーブルの脱着が発生しない限りUSB 2.0のまま動作を続ける、というインプリメントをするのが一般的ではないかと考えられる。もともと、USB 3.0→USB 2.0にスピードを落とす、という事そのものが理由がないというか、合理的な理由が考えにくい。あるとすれば、DeviceなりHubなりのPortのトラブルとかケーブルの劣化など、そもそも異常事態しかないわけで、こうしたスピード変更をきちんとサポートすべき理由はない(というか、サポートしても構わないだろうが、それによる利便性の向上は殆ど期待できない)からである。

さて、速度変更の話はこのくらいにして、次にRoutingの話。329回で紹介したとおり、Hubは5層のStackingが可能になっており、これに対応するためRouteStringと呼ばれるもの井がアドレス向けに用意されている、という話は303回で触れたとおりだ。RouteStringは、各HubがどうパケットをRountingすべきかが記述されており、Hubはこれを見ながらRoutingを行えるので、動作的にはEthernetのSwitching Hubに近い物ながらARPの様に動的にRouting動作を決めるといった必要はなく、これが最終的には消費電力の低減や実装コストの低下に繋がる、という話は302回に纏めたとおりだ(Photo02)。当たり前だがHubが動作に当たってRouteStringを考慮するのは、Configure Stateに入ってからの話で、それ以前は無視するというか、そもそもConfigure State以前は何の動作もできないから、無視するもへったくりもないのだが。(続く)

Photo02: こちらも概ね同じ事を言っている。RouteStringは20bitsのフィールドで、これを4bitづつ5つのHubに割り当てている計算。