USB-MIDI (8)
MIDIStreaming サブクラスの規格書[*1]の付録 B に示されているディスクリプタを元に解説を加えます。
規格書は、「usb.org midi」 を検索キーワードとしてググればすぐに見つかります。
ここで示すディスクリプタは、 2 箇所を除いて規格書の付録 B と同じです。
その 1 箇所は、元の文書ではディスクリプタ全体のサイズを示す wTotalLength に値が指定されていなかったのを実際の数値に置き換えました。
もう 1 箇所は、クラス固有 MS インターフェース・ディスクリプタ内の wTotalLength で、規格書本文の説明に沿えば、後続のエンドポイント・ディスクリプタは含まれないはずですが、付録 B の例では、エンドポイント・ディスクリプタを含む値となっています。
具体的には、エンドポイント・ディスクリプタを含まない場合には 0x0025 = 37 バイト、含む場合には 0x0041 = 65 バイトとなります。
ここでの説明では、エンドポイント・ディスクリプタを含まない値としています。
ソースが公開されている USB-MIDI 関連のプログラムを調べると、付録 B の例のエンドポイント・ディスクリプタを含む値 0x0041 を使用しているケースが多いようです。
私の持っている MIDI 機器の中で、標準 USB クラスに準拠しているのは KORG microKEY-37 だけなのですが、そのディスクリプタを調べるとエンドポイント・ディスクリプタを含まない 0x0025 でした。
EZ-USB (AC2131S) で作成した USB-MIDI プログラムで試して見ると、対象 OS が Windows の場合には 0x0025 でも 0x0041 でも変わらず動作しました。
他の OS の場合については調べていません。
以下に、各ディスクリプタごとに説明します。 これらを順につなぎ合わせていけば「動作する」ディスクリプタが得られます。
ディスクリプタは「リトル・エンディアン」で記述するという「お約束」なので、以下の表で 2 バイトの「ワード値」で表現されている部分は下位バイトを先、上位バイトを後に記述する必要があります。
たとえば、ワード値が 0x0065 なら、0x65, 0x00 の順番でバイト値の列に直します。
まず最初は、先頭に位置するコンフィギュレーション・ディスクリプタです。
表 B-2: MIDI アダプタ コンフィギュレーション・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x02 | ディスクリプタ・タイプ (0x02=CONFIGURATION) |
2 | wTotalLength | 2 | 0x0065 | このディスクリプタを含む 全ディスクリプタ・サイズ (0x0065 = 101 バイト = 9 + 9 + 9 + 9 + 7 + 6 + 6 + 9 + 9 + 9 + 5 + 9 + 5) |
4 | bNumInterfaces | 1 | 0x02 | 全インターフェース数 (AC と MS で計 2 個) |
5 | bConfigurationValue | 1 | 0x01 | コンフィギュレーション番号 |
6 | iConfiguration | 1 | 0x00 | コンフィギュレーション名 ストリングのインデクス (0x00 = 不使用) |
7 | bmAttributes | 1 | 0x80 | 属性 (バスパワーのみ、 リモード・ウェイクアップなし) |
8 | MaxPower | 1 | 0x32 | 最大電流 (0x32 = 100 mA) |
これはクラス固有ではない「標準」のものなので、難しい部分はありませんが、オフセット 4 の bNumInterfaces フィールドの値は、AudioControl インターフェースと MIDIStreaming インターフェースの、計 2 個となります。
規格からは外れますが、AC インターフェースを省略して MS インターフェースだけにするなら、当然この値は「1」にする必要があります。
オフセット 2 の wTotalLength には全ディスクリプタのサイズを指定します。
元の文書には数値が入っていませんが、実際の値は 0x0065 = 101 バイトとなります。 上の表には、その内訳も示してあります。
表 B-3: MIDI アダプタ 標準 AC インターフェース・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x04 | ディスクリプタ・タイプ (0x04 = INTERFACE) |
2 | bInterfaceNumber | 1 | 0x00 | このインターフェースの番号 |
3 | bAlternateSetting | 1 | 0x00 | オルタネート設定の番号 |
4 | bNumEndpoints | 1 | 0x00 | エンドポイント数 (デフォルト・パイプ (EP0) 含まず) |
5 | bInterfaceClass | 1 | 0x01 | インターフェース・クラス (0x01 = AUDIO) |
6 | bInterfaceSubClass | 1 | 0x01 | インターフェース・サブクラス (0x01 = AUDIO_CONTROL) |
7 | bInterfaceProtocol | 1 | 0x00 | インターフェース・プロトコル (0x00 = 指定なし) |
8 | iInferface | 1 | 0x00 | インターフェース名 ストリングのインデクス (0x00 = 不使用) |
AudioControl インターフェースでは、コントロール操作はデフォルト・パイプ (エンドポイント 0) のコントロール転送のクラス拡張リクエストを使うので、コントロールだけなら (追加の) エンドポイントを使う必要はありません。
AC インターフェースでは、ステータス報告のためにインタラプト IN エンドポイントを 1 つだけ追加することができます。 これを使わないならば、bNumEndPoints の値は「0」に設定しておきます。
表 B-4: MIDI アダプタ クラス固有 AC インターフェース・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x01 | ディスクリプタ・サブタイプ (0x01 = HEADER) |
3 | bcdADC | 2 | 0x0100 | Audio Device クラス定義の リリース番号 (0x0100 = rel. 1.0) |
5 | wTotalLength | 2 | 0x0009 | このディスクリプタを含む CS ディスクリプタ・サイズ |
7 | bInCollection | 1 | 0x01 | 属するストリーミング・ インターフェースの個数 (MS だけなので 0x01) |
8 | baInferfaceNr(1) | 1 | 0x01 | 属するストリーミング・ インターフェース番号(1 番目) (0x01 = MSインターフェース の番号) |
AC インターフェースからコントロール可能なエレメントがない場合には、クラス固有の AC インターフェース記述は上のヘッダ部分 1 個だけとなり、前の標準 AC インターフェース・ディスクリプタと合わせて。18 バイト分のディスクリプタは常に固定パターンとなります。
表 B-5: MIDI アダプタ 標準 MS インターフェース・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x04 | ディスクリプタ・タイプ (0x04 = INTERFACE) |
2 | bInterfaceNumber | 1 | 0x01 | このインターフェースの番号 |
3 | bAlternateSetting | 1 | 0x00 | オルタネート設定の番号 |
4 | bNumEndpoints | 1 | 0x02 | エンドポイント数 (デフォルト・パイプ (EP0) 含まず) |
5 | bInterfaceClass | 1 | 0x01 | インターフェース・クラス (0x01 = AUDIO) |
6 | bInterfaceSubClass | 1 | 0x03 | インターフェース・サブクラス (0x03 = MIDI_STREAMING) |
7 | bInterfaceProtocol | 1 | 0x00 | インターフェース・プロトコル (0x00 = 指定なし) |
8 | iInferface | 1 | 0x00 | インターフェース名 ストリングのインデクス (0x00 = 不使用) |
この例では、MIDI IN / OUT にそれぞれエンドポイントを 1 つずつ割り当てるので、上記の標準 MS インターフェース・ディスクリプタのオフセット 4 の bNumEndPoints フィールドの値は「2」となります。
表 B-6: MIDI アダプタ クラス固有 MS インターフェース・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x07 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x01 | ディスクリプタ・サブタイプ (0x01 = HEADER) |
3 | bcdMSC | 2 | 0x0100 | MIDIStreaming サブクラス 定義のリリース番号 (0x0100 = rel. 1.0) |
5 | wTotalLength | 2 | 0x0025 | このディスクリプタを含む CS ディスクリプタ・サイズ (0x0025 = 37 バイト = 7 + 9 + 9 + 6 + 6) |
上のクラス固有 MS インターフェース・ディスクリプタのオフセット 5 の wTotalLength フィールドにはクラス固有ディスクリプタ・サイズを設定する必要がありますが、前述のように、ここではエンドポイント・ディスクリプタを含まない値としています。
表 B-7: MIDI アダプタ MIDI IN ジャック・ディスクリプタ (埋め込み)
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x06 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x02 | ディスクリプタ・サブタイプ (0x02 = MIDI_IN_JACK) |
3 | bJackType | 1 | 0x01 | このジャックのタイプ (0x01 = EMBEDDED) |
4 | bJackID | 1 | 0x01 | このジャックの ID 番号 (ID = 1) |
5 | iJack | 1 | 0x00 | このジャック名の ストリング・インデクス (0x00 = 不使用) |
MIDI IN ジャックには入力ピンがなく、また出力ピンは 1 個だけなので特に指定する必要はなく、ディスクリプタには入出力ピンに関するフィールドはありません。
オフセット 4 の bJackID フィールドで ID 番号を割り当てるのが主な機能です。
表 B-8: MIDI アダプタ MIDI IN ジャック・ディスクリプタ (外部)
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x06 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x02 | ディスクリプタ・サブタイプ (0x02 = MIDI_IN_JACK) |
3 | bJackType | 1 | 0x02 | このジャックのタイプ (0x02 = EXTERNAL) |
4 | bJackID | 1 | 0x02 | このジャックの ID 番号 (ID = 2) |
5 | iJack | 1 | 0x00 | このジャック名の ストリング・インデクス (0x00 = 不使用) |
表 B-9: MIDI アダプタ MIDI OUT ジャック・ディスクリプタ (埋め込み)
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x03 | ディスクリプタ・サブタイプ (0x03 = MIDI_OUT_JACK) |
3 | bJackType | 1 | 0x01 | このジャックのタイプ (0x01 = EMBEDDED) |
4 | bJackID | 1 | 0x03 | このジャックの ID 番号 (ID= 3) |
5 | bNrInputPins | 1 | 0x01 | このジャックの入力ピン数 |
6 | baSourceID(1) | 1 | 0x02 | 1 番入力ピンと接続する要素の ID 番号 (0x02 = Ext MIDI IN Jack) |
7 | baSourcePin(1) | 1 | 0x01 | 1 番入力ピンと接続する要素の 出力ピン番号 (0x01 = 1 番ピン) |
8 | iJack | 1 | 0x00 | このジャック名の ストリング・インデクス (0x00 = 不使用) |
MIDI OUT ジャックでは入力ピンを複数持てるので、ディスクリプタでその接続先のエレメントの ID 番号と出力ピン番号を記述します。 ディスクリプタ・サイズは入力ピン数により変化します。
オフセット 5 の bNrInputPins フィールドで入力ピン数を指定します。
この例では MIDI IN ジャックひとつと接続するだけなので、入力ピン数は「1」です。
オフセット 6 の baSourceID(1) フィールドが 1 番入力ピンと接続するエレメントの ID 番号、オフセット 7 の baSourcePin(1) フィールドがピン番号の指定です。
入力ピンが複数ある場合には、
baSourceID(2),baSourcePin(2),baSouceID(3),baSourcePin(3), ...
のように繰り返します。
「エレメント」の場合には出力ピンを複数持てるのでピン番号を区別する必要がありますが、MIDI IN ジャックの場合には出力ピンは 1 番ピンの 1 つだけなので、baSoucePin(1) フィールドに指定する値は常に「1」となります。
表 B-10: MIDI アダプタ MIDI OUT ジャック・ディスクリプタ (外部)
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x24 | ディスクリプタ・タイプ (0x24 = CS_INTERFACE) |
2 | bDescriptorSubType | 1 | 0x03 | ディスクリプタ・サブタイプ (0x03 = MIDI_OUT_JACK) |
3 | bJackType | 1 | 0x02 | このジャックのタイプ (0x02 = EXTERNAL) |
4 | bJackID | 1 | 0x04 | このジャックの ID 番号 (ID= 4) |
5 | bNrInputPins | 1 | 0x01 | このジャックの入力ピン数 |
6 | baSourceID(1) | 1 | 0x01 | 1 番入力ピンと接続する要素の ID 番号 (0x01 = Emb MIDI IN Jack) |
7 | baSourcePin(1) | 1 | 0x01 | 1 番入力ピンと接続する要素の 出力ピン番号 (0x01 = 1 番ピン) |
8 | iJack | 1 | 0x00 | このジャック名の ストリング・インデクス (0x00 = 不使用) |
表 B-11: MIDI アダプタ 標準バルク OUT エンドポイント・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x05 | ディスクリプタ・タイプ (0x05 = ENDPOINT) |
2 | bEndpointAddress | 1 | 0x01 | エンドポイント・アドレス (OUT EP 1) |
3 | bmAttributes | 1 | 0x02 | エンドポイント属性 (0x02 = Bulk, not shared) |
4 | wMaxPacketSize | 2 | 0x0040 | エンドポイント・サイズ (0x40 = 64 バイト) |
6 | bInterval | 1 | 0x00 | バルク・エンドポイント では無視される |
7 | bRefresh | 1 | 0x00 | 未使用 |
8 | bSynchAddress | 1 | 0x00 | 未使用 |
MIDIStreaming ではバルク転送を行うことが規格で決まっているので、バルク・エンドポイントを指定します。
「標準」とは言いながら、AudioStreaming で使うアイソクロナス・エンドポイントに合わせて、バルク転送には不必要なフィールド bRefresh, bSynchAddress が追加されているので、「0」にしておきます。
エンドポイント・アドレスやエンドポイント・サイズが上の表の値で都合が悪ければ都合の良い値に変更します。
表 B-12: MIDI アダプタ クラス固有バルク OUT エンドポイント・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x05 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x25 | ディスクリプタ・タイプ (0x25 = CS_ENDPOINT) |
2 | bDescriptorSubType | 1 | 0x01 | ディスクリプタ・サブタイプ (0x01 = MS_GENERAL) |
3 | bNumEmbMIDIJack | 1 | 0x01 | 関連付ける埋め込みジャック数 |
4 | baAssocJackID(1) | 1 | 0x01 | 1 番出力 (CN = 0) と関連 付けるジャックの ID 番号 (1 = Emb MIDI IN JACK) |
クラス固有エンドポイント・ディスクリプタでエンドポイントと埋め込み MIDI ジャックとの間の「関連付け」(association) を行います。
1 つのエンドポイントに複数の埋め込み MIDI ジャックを関連付けることができます。
1 番目に指定した埋め込み MIDI ジャックにはケーブル・ナンバー 0 の MIDI パケットが割り振られ、2 番目に指定した埋め込み MIDI ジャックには CN = 1 のパケットが割り振られ、以下同様に CN = 15 のパケットまでがサポートされます。
ホスト PC からは CN が付加されて出力エンドポイントに送られてきますが、それを実際に振り分けるのは USB-MIDI のファームウェアの責任です。
同様に、USB-MIDI のファームウェアではケーブル・ナンバーを付加した MIDI パケットを作成して入力エンドポイントに送る必要があります。
この例では、関連付ける埋め込み MIDI ジャックは 1 つだけなので、ホスト PC のソフトウェアからは MIDI IN ポート 1 つ、MIDI OUT ポート 1 つに見えます。
表 B-13: MIDI アダプタ 標準バルク IN エンドポイント・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x05 | ディスクリプタ・タイプ (0x05 = ENDPOINT) |
2 | bEndpointAddress | 1 | 0x81 | エンドポイント・アドレス (IN EP 1) |
3 | bmAttributes | 1 | 0x02 | エンドポイント属性 (0x02 = Bulk, not shared) |
4 | wMaxPacketSize | 2 | 0x0040 | エンドポイント・サイズ (0x40 = 64 バイト) |
6 | bInterval | 1 | 0x00 | バルク・エンドポイント では無視される |
7 | bRefresh | 1 | 0x00 | 未使用 |
8 | bSynchAddress | 1 | 0x00 | 未使用 |
表 B-14: MIDI アダプタ クラス固有バルク IN エンドポイント・ディスクリプタ
Offset | フィールド | Size | 値 | 説明 |
---|---|---|---|---|
0 | bLength | 1 | 0x05 | このディスクリプタのサイズ (バイト単位) |
1 | bDescriptorType | 1 | 0x25 | ディスクリプタ・タイプ (0x25 = CS_ENDPOINT) |
2 | bDescriptorSubType | 1 | 0x01 | ディスクリプタ・サブタイプ (0x01 = MS_GENERAL) |
3 | bNumEmbMIDIJack | 1 | 0x01 | 関連付ける埋め込みジャック数 |
4 | baAssocJackID(1) | 1 | 0x03 | 1 番入力 (CN = 0) と関連 付けるジャックの ID 番号 (3 = Emb MIDI OUT JACK) |
*1:"Universal Serial Bus Device Class Definition for MIDI Devices Release 1.0", Nov 1, 1999, USB Implementers Forum