ハブのタスクは次のとおりです。
- ハブは、接続されているすべてのデバイスに電力を供給します。
- ハブは、デバイスの接続と切断についてホストに通知します。
- ハブは、ホストからのコマンドで接続されたデバイスをリセットし、同時にその速度を判断します。
- ハブは、リセット後から切断するまでの間にホストから接続されたデバイスに送信されるすべてのトラフィック、および反対方向のデバイスからのトラフィックをブロードキャストします。
- HighSpeedハブには、HighSpeedバスを低速USB1バスにリンクするTransaction Translatorが含まれています。
スイッチング速度のないブロードキャストトラフィックは、ホストに対して完全に透過的です。 EHCIホストコントローラーは分割トランザクションに関与します。ここでは、ソフトウェアから、TTハブのアドレスとTTハブのポートを含むチャネル構造のハードウェアのフィールドに入力することだけが重要です-そして、もちろん、 計画時にトランザクション時間を考慮に入れます 。 ハブドライバーは、タスクリストの残りの項目を管理します。
ハブには、デバイスクラスコード9、デバイスサブクラスコード0、およびプロトコルコードの3つのオプション0、1、2があります。 USB仕様によると、HighSpeedハブはすべてのポートで単一のTTモードを維持する必要があり、さらに、ポートごとに個別のTTモードを維持することができますが、必須ではありません。 典型的なケースは、異なるTTのモードがない場合、プロトコルコードは0です。このモードがサポートされている場合、構成データに同じインターフェイス番号を持つインターフェイス記述子の2つのオプションがあります。 次に、プロトコルコード1は、デフォルトで採用される単一のTTモードを識別し、プロトコル2コードは、
SET_INTERFACE
コマンドで
SET_INTERFACE
された異なるTTモードを識別します。 異なるTTのモードをサポートする野生動物のハブの存在は、このモードの利点と同様に確認されていないため、ハブドライバーはそれを検出して有効にしようとせず、デフォルトでオンになっている単一のTTモードを使用します。
クラス9インターフェイスを発見すると、論理デバイス層は
usb_hub_init
および
usb_hub_disconnect
ドライバー関数へのポインターを含む
usb_hub_callbacks
構造を読み取ります。 ドライバーは、論理デバイスレベルが
usb_hub_init
呼び出すと開始し、 チャネルサポートレベルがデバイスの切断に応じて
usb_hub_disconnect
を呼び出すと終了します。
初期化
ハブの初期化は
usb_hub_init
で開始され、デバイスから応答を受信すると他の機能で続行されます。
usb_hub_init
は、ハブが接続デバイスのステータスの変更をドライバーに通知する割り込みなどのエンドポイントへのチャネルを開きます。 次に、
usb_hub_init
は、ハブ記述子に対する
GET_DESCRIPTOR
要求を送信します。
この図は、3つの異なるハブの16進ダンプ記述子を示しています。2つのポート用のハブが統合されたキーボード、6ポートと8ポート用の2つのRMH。 ハブが組み込まれたキーボードは、システムからはハブとして認識されます。ハブのポートの1つは、取り外し不可能なデバイス(キーボード自体)に接続されています。
ハブ記述子には次のフィールドが含まれます。
- すべての記述子と同様に、サイズとタイプ。 ハブ記述子のタイプは
29h
です。 - ポート数
- 属性ビット。 インフラストラクチャにとって重要な唯一の属性は、速度切り替えでパケットをブロードキャストするときにTTによって導入される一時停止です。これは、FullSpeed速度で8 *(1 +ビット6の値:5)ビットとして計算されます。 図のすべての記述子では、8 FSビットに相当します。
- enableコマンドの後、ポートの電源を安定させるのに必要な時間は、2ミリ秒間隔で測定され、
32h=50
は100ミリ秒に相当します。 - ハブエレクトロニクスに必要な電力(mA)。
- 固定デバイスのビットマスク。 サイズ-ポートごとに1ビット、および予約済みの最下位ビットをバイト境界まで整列。 図のハブキーボードでは、ビット3(ゼロからカウント)が設定されます。これは、ポート3の取り外し不可能なデバイス(1からカウント)に対応し、キーボード自体に対応しています。 ポート3と6には、それぞれ4ビットと7ビットが必要です。これはバイトに丸められます。 8ポートには9ビットが必要であり、2バイトに丸められます。
- 古いソフトウェアとの互換性のために、以前のものと同じ可変サイズのフィールドがもう1つあり、FFで満たされています。
usb_hub_init
は、エンドポイントパケットのサイズを保存します(さらに必要になります)。40バイトのハブ記述子を要求し、短い応答を許可します。 ハブ記述子を受信すると、
usb_hub_got_config
は、興味深いデータを保存するのに十分なメモリに加えて、ポートごとに2つの変数(接続されたデバイスへのポインターとデバイスの接続時間)を割り当てて満たします。
ハブポートを使用する前に、
SET_FEATURE(PORT_POWER)
電源をオンにする必要があります。 このコマンドは、入力で1から始まるポート番号を受け入れます。物理的に、ハブは各ポートの電源オン/オフをサポートするか、2つの状態に制限できます。「すべてのポートに電源がない」と「すべてのポートに電源があります」-下位2ビットから組織を認識できますハブ、00は一般的な電源に対応し、01は別の電源に対応し、10と11は予約されています。 ただし、どちらの場合も、ハブは各ポートの個別の論理状態を維持し、論理的に電源がオフのポートでイベントを報告しないため、物理的な組織に関係なく、各ポートの電源をオンにする必要があります。
usb_hub_got_config
および
usb_hub_port_powered
、すべてのポートに対してパワーオンコマンドを順番に
usb_hub_port_powered
します。
すべてのポートの電源を正常にオンにした後、電源が安定するまで待機する必要があります。待機時間はハブ記述子に示されます。 遅延反応を必要とする他のアクションと同様に、
usb_hub_process_deferred
関数は食物の待機を制御する役割を
usb_hub_process_deferred
ます。 割り当てられた間隔が
usb_hub_process_deferred
、
usb_hub_process_deferred
はハブとの連携を開始します。
仕事
簡単に説明すると、ハブのポーリングスキームは、USB仕様から取った次の図で説明されています。
ハブでの作業は、割り込みなどのエンドポイントからのデータを要求する
usb_hub_wait_change
呼び出しから始まります。 注意が必要なイベントはハブでは発生しませんが、要求はCPUリソースを消費せずに待機します。ホストコントローラーは、ホストからのデータ干渉なしに定期的にエンドポイントをポーリングします。 ポーリング間隔はエンドポイント記述子の最後のバイトでエンコードされ、チャネルが開かれたときに設定されます。 ハブのステータスが変更されると、ハブは、ステータスが変更されたポートを示すビットマスクと、ハブ自体のステータスが変更されたかどうかを示す最下位ビットを返します。 ハブの初期化中にいくつかのデバイスが既にそれに接続されていた場合、最初の要求で、ハブはすぐに「ゼロ」状態に関する変更を返します。
応答の重要な部分のビット単位のサイズは、ポートの数に1を加えたものに等しくなります。 ほとんどの場合、応答の完全なサイズは、整数のバイト数にパディングすることによって取得されます。 しかし、 テストではハブがさらに重要でないバイトを追加できることがあることが示されているため、応答の実際のサイズはエンドポイント記述子から最大パケットサイズとして取得する必要があります。これが、チャネルオープニング関数に渡すことに限定されず、
usb_hub_init
保存した理由
usb_hub_init
。
ハブはポート状態の変化を監視します。 これらの変更をホストに通知する方法はやや混乱します。 ポートのステータスにはいくつかの異なるビットが含まれます:デバイスは接続/切断され、デバイスへのトラフィックはブロードキャスト/非ブロードキャスト、デバイスは一時停止/動作、現在の過負荷は登録済み/いいえ、リセットプロセスは進行中/ポート上ではありません リストされている各ビットについて、ハブは状態変更ビットのペアをサポートしています。 ハブは状態が変化すると自動的にビットを設定し、その後の変更ではビットは設定されたままになります。 ハブは、現在の状態と変更ビットの両方のビットを返す2つの
GET_STATUS
、および指定された変更ビットをリセットする使用方法の1つである
GET_STATUS
もサポートします。 これらは2つの異なるチームであるという事実により、以下の状況が考えられます。
- デバイスがポートに接続されている、
- ハブは、接続されたデバイスのビットと状態変化のビットを設定します。
- ハブは、特定のポートの変更についてホストに通知します。
- ホストは
GET_STATUS
コマンドを提供し、現在の状態および状態変化におけるデバイスの接続を確認します。 - デバイスの電源が切れます
- ハブは接続されたデバイスのビットをリセットし、ステータス変更ビットは設定されたままです。
- ホストは
CLEAR_FEATURE
コマンドを送信し、ハブは変更ビットをリセットし、 - ハブは、ホストがすべての変更について認識していると考えていますが、ホストは現在の状態について誤った考えを持っています。
GET_STATUS
後に状態の変化を処理して、何が起こったかを調べ、
CLEAR_FEATURE
変化をクリアする場合、
GET_STATUS
コマンドを
GET_STATUS
送信して現在のステータスを取得する必要があります。 2番目の
GET_STATUS
コマンド
GET_STATUS
CLEAR_FEATURE
後の状態の変化
GET_STATUS
再び報告する可能性があります。 この時点で処理を停止するのは正しいことですが、次に割り込みなどのエンドポイントからデータが読み取られると、ハブはすぐに新しい変更を報告します-ホストが変更を認識し、ハブの背後のホストの
CLEAR_FEATURE
を更新してループを作成する場合:2番目のコマンド
CLEAR_FEATURE
を送信し、
GET_STATUS
が新しい変更を報告しなくなるまで、3番目の
GET_STATUS
。
割り込みタイプのエンドポイントからのデータは、ハブまたはそのポートのいずれかの状態が変化したときに到着し、
usb_hub_changed
関数によって処理されます。 彼女はどのポートが変更されたかのステータスを見て、各ポートが上記のリクエストステータスと変更確認サイクルを開始し、入ってくる変更を蓄積します。 ほとんどの変更に対する応答は、適切なデバッグ印刷です。 デバイス接続/切断通知の処理のみが必要です。
デバイスが接続されると、
usb_hub_changed
は接続時間を記憶します。その後、
usb_hub_process_deferred
は100ミリ秒後に
usb_hub_process_deferred
することを計画します。 同じポートのデバイスを切断する信号が100ミリ秒以内に到着すると、それ以降のアクションはキャンセルされます。 残念ながら、このような信号がないからといって、デバイスがこれらの100ミリ秒すべて接続されているわけではありません-ポーリング間隔が非常に長く、信号がまだ到達していない可能性があります。 信頼性のために、100ミリ秒間隔の後、
usb_hub_process_deferred
は明示的な
GET_STATUS
要求を送信します。 接続ステータスに変更がなかったことを示している場合、さらに初期化が有効になっています。 同じバス上の2つのデバイスを同時にリセットすることはできません。 同じコントローラー(必ずしも同じハブに接続されている必要はありません)に接続されている他のデバイスのリセットがある場合、最初にデバイスはリセットの順番を待ちます。 リセットは、
SET_FEATURE(PORT_RESET)
によってアクティブ化され、指定された10ミリ秒が経過するとハブによって自動的に無効化されます。これにより、ポーリングインターバルに応じて、エンドポイントの読み取り時に
SET_FEATURE(PORT_RESET)
される場合とされない場合があります。 このような不確実性のため、
usb_hub_process_deferred
は、設定時間と
CLEAR_FEATURE
後に独立して
usb_hub_process_deferred
送信し、変更処理コードは、リセット状態に変更があった場合、それを無視します。 ハブのリセットの終了には、デバイスへのトラフィックの送信が同時に含まれます。 リセット後、
usb_hub_process_deferred
仕様に従って、デバイスはさらに10ミリ秒待機し、その間にデバイスは適応できます。その後、
usb_hardware_func.NewDevice
を呼び出してホストコントローラーサポートコードに制御を
usb_hardware_func.NewDevice
ます。 ハブは、リセットプロセス中に
usb_hardware_func.NewDevice
のデバイスの速度を決定し、
usb_hardware_func.NewDevice
に応答して、他のデバイスステータスとともに返され
GET_STATUS
。
usb_hardware_func.NewDevice
から返された接続デバイスへのポインターは、ハブ構造に格納されます。
デバイスが切断されると、
usb_hub_changed
は
usb_device_disconnected
サポートレベルの
usb_device_disconnected
関数を呼び出し、以前に保存されたポインターを
NewDevice
から
NewDevice
ます。 デバイスが初期化プロセスにあった場合、プロセスは終了します。
断線
usb_hub_disconnected
ハンドラーは、ハブが切断されたときに
usb_device_disconnected
れ、接続されているすべてのデバイスに対して
usb_device_disconnected
を呼び出し、リセットを待機しているデバイスのキューを進めます-接続されたデバイスの1つがリセットされた場合、ハブ構造に割り当てられたメモリを解放します。
次は?
ハブドライバーは、USBインフラストラクチャの最後の部分です。 シリーズの最初の6部で書いたすべて(この記事で終わる)を実装した後、USBで動作するシステムのサポートについて話すことができます。 残念ながら、これはドライバープログラマーにとってのみ重要であり、これまでのところユーザーにはほとんど目立ちません。
次に、無限に多様なドライバーの世界が始まります。 幸いなことに、すべてのさまざまなデバイスでは、多くがクラスに分類され、同じドライバーが同じクラス内のすべてのデバイスに適している場合があります。 ハブが最初のクラスの例です。 KolibriOSがクラスドライバーを提供する他の2つの一般的なクラスは、マウスとキーボードが代表的なHIDデバイスと、フラッシュドライブと絶滅USB外部フロッピードライブが代表的なマスストレージデバイスです。 次回は、HIDデバイスについて説明します。
シリーズのすべての記事
パート1:概要
パート2:ホストコントローラーの操作の基本
パート3:ホストコントローラーサポートコード
パート4:チャネルサポートレベル
パート5:論理デバイスレベル
パート6:ハブドライバー