KolibriOSでのUSBサポート:内部には何がありますか? パート6:ハブドライバー

USBインフラストラクチャの最後の部分はハブです。 ハブは独立したUSBデバイスですが、インフラストラクチャの他の部分と密接に関連しているため、ハブ仕様はメインUSB仕様の一部であり、サポートコードはbus / usb / hub.incファイルにあるカーネルの一部です



ハブのタスクは次のとおりです。

スイッチング速度のないブロードキャストトラフィックは、ホストに対して完全に透過的です。 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つは、取り外し不可能なデバイス(キーボード自体)に接続されています。

ハブ記述子には次のフィールドが含まれます。 ハンドルのサイズは可変です。 最大サイズは255ポートで取得され、40バイトに相当します。 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



コマンドを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:ハブドライバー



All Articles