USB-MIDI (9)
前回の規格書付録 B のディスクリプタと同等のディスクリプタを。C 言語の初期値付き配列の形で表現したものを下に示します。
LPC11U35 を使った FM 音源プログラムの USB-MIDI 機能部分で、このディスクリプタを使ってコンパイルして MIDI OUT 機能が正常に動作することを確かめてあります。 (MIDI IN 機能は、もともと実装していない)
// // Macro for split WORD (2 byte) value // into little-endian order bytes // #define lew(x) ((uint8_t)(x)), (((uint16_t)(x)) >> 8) const uint8_t ConfigurationDescriptor[] = { // // Configuration descriptor (9 byte) // 0x09, // bLength 0x02, // bDescriptorType lew(0x0065), // wTotalLength 0x02, // bNumInterfaces 0x01, // bConfigurationValue 0x00, // iConfiguration 0x80, // bmAttributes 0x32, // MaxPower // // Standard AudioControl // Interface descriptor (9 byte) // 0x09, // bLength 0x04, // bDescriptorType 0x00, // bInterfaceNumber 0x00, // bAlternateSetting 0x00, // bNumEndpoints 0x01, // bInterfaceClass 0x01, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0x00, // iInferface // // Class-Specific AudioControl // Interface descriptor (9 byte) // 0x09, // bLength 0x24, // bDescriptorType 0x01, // bDescriptorSubType lew(0x0100), // bcdADC lew(0x0009), // wTotalLength 0x01, // bInCollection 0x01, // baInferfaceNr(1) // // Standard MIDIStreaming // Interface descriptor (9 byte) // 0x09, // bLength 0x04, // bDescriptorType 0x01, // bInterfaceNumber 0x00, // bAlternateSetting 0x02, // bNumEndpoints 0x01, // bInterfaceClass 0x03, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0x00, // iInferface // // Class-Specific MIDIStreaming // Interface descriptor (7 byte) // 0x07, // bLength 0x24, // bDescriptorType 0x01, // bDescriptorSubType lew(0x0100), // bcdMSC lew(0x0025), // wTotalLength // // Class-Specific MIDI IN Jack // descriptor (Embedded) (6 byte) // 0x06, // bLength 0x24, // bDescriptorType 0x02, // bDescriptorSubType 0x01, // bJackType 0x01, // bJackID 0x00, // iJack // // Class-Specific MIDI IN Jack // descriptor (External) (6 byte) // 0x06, // bLength 0x24, // bDescriptorType 0x02, // bDescriptorSubType 0x02, // bJackType 0x02, // bJackID 0x00, // iJack // // Class-Specific MIDI OUT Jack // descriptor (Embedded) (9 byte) // 0x09, // bLength 0x24, // bDescriptorType 0x03, // bDescriptorSubType 0x01, // bJackType 0x03, // bJackID 0x01, // bNrInputPins 0x02, // baSourceID(1) 0x01, // baSourcePin(1) 0x00, // iJack // // Class-Specific MIDI OUT Jack // descriptor (External) (9 byte) // 0x09, // bLength 0x24, // bDescriptorType 0x03, // bDescriptorSubType 0x02, // bJackType 0x04, // bJackID 0x01, // bNrInputPins 0x01, // baSourceID(1) 0x01, // baSourcePin(1) 0x00, // iJack // // Standard Bulk OUT // Endpoint descriptor (9 byte) // 0x09, // bLength 0x05, // bDescriptorType 0x01, // bEndpointAddress 0x02, // bmAttributes lew(0x0040), // wMaxPacketSize 0x00, // bInterval 0x00, // bRefresh 0x00, // bSynchAddress // // Class-Specific Bulk OUT // Endpoint descriptor (5 byte) // 0x05, // bLength 0x25, // bDescriptorType 0x01, // bDescriptorSubType 0x01, // bNumEmbMIDIJack 0x01, // baAssocJackID(1) // // Standard Bulk IN // Endpoint descriptor (9 byte) // 0x09, // bLength 0x05, // bDescriptorType 0x81, // bEndpointAddress 0x02, // bmAttributes lew(0x0040), // wMaxPacketSize 0x00, // bInterval 0x00, // bRefresh 0x00, // bSynchAddress // // Class-Specific Bulk IN // Endpoint descriptor (5 byte) // 0x05, // bLength 0x25, // bDescriptorType 0x01, // bDescriptorSubType 0x01, // bNumEmbMIDIJack 0x03 // baAssocJackID(1) }; // uint8_t ConfigurationDescriptor[]
ディスクリプタ内には MINI IN 側の構成も含まれているので、ホスト PC 側は IN エンドポイントからデータを入力しようとします。
USB-MIDI のファームで MIDI 入力がサポートされていない場合でも、多くの場合には問題になりません。
動作可能な IN エンドポイントのバッファにデータが何も書き込まれていない場合には USB モジュールのハードウェアで自動的に「NAK」を返します。
IN エンドポイントが動作不能の状態で、ホストからの IN 要求に対して「無反応」となる場合にはエラーと認識されますが、これは大したことではありません。
決して入力されない IN エンドポイントに対してホストは IN 要求を投げ続けるわけで、効率は悪くなりますが、 OUT 動作の障害にはなりません。
逆に MIDI IN だけサポートして MIDI OUT は放置の場合は、OUT 要求に NAK あるいは無反応を出し続けて、ホスト側は先に進めなくなります。
この場合、OUT エンドポイントに溜まったデータを読み捨てて、ホスト側の MIDI 出力処理が進むようにします。
下にディスクリプタの 16 進ダンプを示します。
0000 09 02 65 00 02 01 00 80 32 09 04 00 00 00 01 01 0010 00 00 09 24 01 00 01 09 00 01 01 09 04 01 00 02 0020 01 03 00 00 07 24 01 00 01 25 00 06 24 02 01 01 0030 00 06 24 02 02 02 00 09 24 03 01 03 01 02 01 00 0040 09 24 03 02 04 01 01 01 00 09 05 01 02 40 00 00 0050 00 00 05 25 01 01 01 09 05 81 02 40 00 00 00 00 0060 05 25 01 01 03
この 16 進ダンプを、1 行に 1 つのディスクリプタが並ぶように区切って表示したものを下に示します。
規格書の記述と突き合わせて見ると理解が進むかと思います。
09 02 65 00 02 01 00 80 32 // Configuration desc. 09 04 00 00 00 01 01 00 00 // Std. AC IF desc. 09 24 01 00 01 09 00 01 01 // CS AC IF desc. 09 04 01 00 02 01 03 00 00 // Std. MS IF desc. 07 24 01 00 01 25 00 // CS MS IF desc. (HEADER) 06 24 02 01 01 00 // |-- Emb. MIDI IN Jack 06 24 02 02 02 00 // |-- Ext. MIDI IN Jack 09 24 03 01 03 01 02 01 00 // |-- Emb. MIDI OUT Jack 09 24 03 02 04 01 01 01 00 // |-- Ext. MIDI OUT Jack 09 05 01 02 40 00 00 00 00 // Std. Bulk OUT EP desc. 05 25 01 01 01 // CS Bulk OUT EP desc. 09 05 81 02 40 00 00 00 00 // Std. Bulk IN EP desc. 05 25 01 01 03 // CS Bulk IN EP desc.