PIC32MX220F032B USB MIDI ホスト (10)

今回は Microchip 社の USB ホスト・スタックの概要について説明します。
USB ホスト・スタックを利用したプログラムは、下のような三層のレイヤー構造で構成されます。

  • アプリケーション
  • USB クライアント (クラス)・ドライバ
  • USB ホスト・ドライバ

最下層の「USB ホスト・ドライバ・レイヤー」はハードウェアに最も近い層で、ホスト・モードでの USB モジュールの「デバイス・ドライバ」として機能します。
Microchip Applications Library の「Microchip/USB」フォルダの下の「usb_host.c」がこの機能を担当しています。
ホスト・ドライバ・レイヤーでは、USB モジュール・ハードウェアの管理、USB デバイスのエニュメレーション、後述する TPL (Targeted Peripheral List) を参照して対応するクライアント (クラス)・ドライバの呼び出しなどを行います。
ホスト・ドライバ・レイヤーと、クライアント (クラス)・ドライバ・レイヤーがライブラリとして提供されています。
USB MIDI ホスト機能のクラス・ドライバは「Microchip/USB/MIDI Host Driver」フォルダの下の「usb_host_midi.c」です。
ライブラリに付属する各種のデモ・プログラムは、「アプリケーション・レイヤー」の部分を実現していることになります。
ホスト・ドライバは、割り込みハンドラ部分と、接続した USB デバイスの状態にほぼ対応したステートを持つステート・マシン・プログラムから成り立っています。
ホスト・スタックの実行については、OS / RTOS の使用を前提にしていないので、アプリケーションからは「USBHostInit()」(あるいは USBInitalize()) を呼び出して初期化した後、「USBHostTasks()」(あるいは USBTasks()) を継続的に繰り返し呼び出す必要があります。
イメージとしては、ホスト・スタックが「裏」で「勝手」に接続された USB デバイスのエニュメレーションを進めて行く感じとなります。
特にエニュメレーションの開始を指示する必要もありません。
もちろん、マルチ・タスクでもマルチ・スレッドでもないので、エニュメレーション・プロセスが進行していくのは、USBHostTasks() を繰り返し呼び出しているおかげです。
エニュメレーションの過程で、接続された USB デバイスのベンダ ID (VID) / プロダクト ID (PID) あるいは、クラス/サブクラス/プロトコルが判明するので、TPL (Targeted Peripheral List) を利用して、対応するクライアント (クラス)・ドライバを呼び出します。
一般の PC などのリソースが潤沢なマシンでは、多様なデバイスに対応する多種のドライバをメモリに動的にロードして処理することができますが、リソースが貧弱な組み込みホストでは、ごく限られたデバイスにしか対応できません。
サポート可能な (限定された) デバイスを列挙したリストが TPL (Targeted Peripheral List) です。
Microchip 社の USB ホスト・スタックでは、CDT (Client Driver Table) と組にして使います。
CDT のテーブル・エントリは

  • クライアント・ドライバの初期化関数へのポインタ
  • クライアント・ドライバのイベント・ハンドラ関数へのポインタ
  • クライアント・ドライバのデータ・イベント・ハンドラ関数へのポインタ
  • 初期化フラグ

TPL のテーブル・エントリは

で構成されています。
エニュメレーション途中のデバイスディスクリプタを読み込んだ時点で、TPL をスキャンし、VID/PID の組、あるいはクラスの組が一致するものがあるかどうかを調べます。
コンフィギュレーション番号として、デフォルトの「1」以外の番号を設定できるのは、このデバイス・レベルで TPL エントリと一致した場合のみです。
この時点で一致するものがなかった場合、コンフィギュレーションディスクリプタを読み込んだ時点で、インターフェース・ディスクリプタをスキャンして、TPL に登録されているクラスの組と一致するものがあるかどうかを調べます。
バイスあるいはインターフェースの中で TPL の登録内容と一致するものがあれば、エニュメレーション完了時に CDT のインデクスをもとに、CDT に登録されているクライアント・ドライバの初期化関数を呼び出します。
Microchip のホスト・スタックでは、同時に接続できる USB デバイスの数はひとつに限られていますが、ひとつのデバイス内に複数の「インターフェース」を持つ「複合デバイス」(composite device) には対応しています。
その場合には、複数のインターフェースに対して複数のクラス・ドライバが呼ばれることになります。
デモ・プログラムのなかにも、HID + MSD や、MSD + CDC の組み合わせの複合デバイスに対応するものがあります。
エニュメレーションが完了すると、ホスト・ドライバは「Running」ステートとなり、サスペンド/リジュームの処理をする以外は、ホスト・ドライバのステートマシン自体が主体的に USB デバイスに対して入出力を行うことはなくなります。
「Running」ステートでの入出力はクライアント・ドライバ、あるいはアプリケーションから、ホスト・ドライバ内の入出力関数を利用して実行されます。
転送完了のイベントは、クライアント・ドライバのイベント・ハンドラ、あるいはアプリケーション・イペント・ハンドラに通知されます。
USB デバイスが抜かれるなどして、デタッチ状態になった場合にも、イベント・ハンドラに通知されます。
その後、ホスト・ドライバはデバイスがアタッチ状態になるのを監視していて、デバイスがアタッチされると再びエニュメレーションが開始されます。
最後に Microchip 社の USB ホスト・スタックに関するドキュメント (アプリケーション・ノート) には、以下のようなものがあります。

  AN1140 - USB Embedded Host Stack
  AN1141 - USB Embedded Host Stack Programmer's Guide
  AN1142 - USB Mass Storage Class on an Embedded Host
  AN1143 - Generic Client Driver for a USB Embedded Host
  AN1144 - USB Human Interface Device Class on an Embedded Host
  AN1145 - Using a Flash Drive with an Embedded Host

ホスト・スタック自体について説明しているのは、最初のふたつです。