usb midi class的拓扑逻辑
这部分内容在《USB声卡驱动(二)USB音频设备描述符》中有过详细介绍,此处在简单介绍一下:一个usb 音频设备,含有多个功能(audio function)。其中之一就是,midi 功能。
在midi 功能中,包含有一个或多个的jack口。这个jack口是一个抽象概念。usb midi 设备的功能之一,就是将usb的端点和这些jack口连接在一起。
举个例子,你往usb的某个端点发送数据,就相当于往某个jack口发送数据。至于这个jack口里面的数据,会流向usb设备内部的哪一个模块,或者外部的哪一个模块,我们可以不用关心。
除此之外,一个usb midi设备的jack口,可能不只一个,而一个usb端点可以代表多个jack口。举个例子,如果一个usb设备有3个jack口。某个usb端点想要向其中的第一个jack口发送数据。格式如下:
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 |
---|---|---|---|
jack号+消息索引号 | midi_0 | midi_1 | midi_2 |
消息索引号,如下表格
消息索引号 | 消息字节数 | 描述 |
---|---|---|
0x0 | 1,2或者3 | 保留 |
0x1 | 1,2或者3 | 保留 |
0x2 | 2 | 两字节系统通用消息,如MTC,SongSelect |
0x3 | 3 | 三字节系统通用消息,如SPP |
0x4 | 3 | SysEx消息的开始,或者延续 |
0x5 | 1 | 单字节系统通用消息,或者SysEx消息的带有一个字节的结束标志 |
0x6 | 2 | 带有两个字节的SysEx消息 |
0x7 | 3 | 带有三个字节的SysEx消息 |
0x8 | 3 | note off |
0x9 | 3 | note on |
0xa | 3 | Poley-key press |
0xb | 3 | Control change |
0xc | 2 | Programe change |
0xd | 2 | Channel pressure |
0xe | 3 | PitchBend change |
0xf | 1 | 单字节 |
jack的数据来源或者数据目的地
在usb midi中,jack口只是一种抽象的数据流通通道。那么数据的来源或者数据的处理,该怎么表示呢?
在usb midi 设备的内部,用Elements来表示一个处理单元。这个单元既可以是jack口的输入,也可以是jack口的输出。
usb midi usb的描述符
显然跟其它USB设备一样,它具有如下的描述符:
-
USB 设备描述符,详细的参数说明,已经在《USB声卡驱动(二):USB音频设备描述符》中详细给出,usb midi 设备完全一模一样
-
USB 配置描述符,跟《USB声卡驱动(二):USB音频设备描述符》一模一样,没有特殊之处
-
USB 接口描述符,USB接口描述符分成两部分,前一部分跟《USB声卡驱动(二):USB音频设备描述符》的一模一样,剩下一部分,为USB midi特有。剩下一部分用来描述整个USB midi设备中用的所有东西。
正如上面介绍的一样,肯定需要描述符来描述上面的,jack口,和elemnt单元。同时在这些描述符前面还加上了一个header 描述符。
详细如下:
offset | Field | size | value | Description |
---|---|---|---|---|
0 | bLength | 1 | 整数 | 这个描述符的长度 |
1 | bDescriptorType | 1 | 常量 | 只能为CS_INTERFACE这个值 |
2 | bDescriptorSubtype | 1 | 常量 | 只能为MS_HEADER |
3 | bcdMSC | 2 | BCD值 | 表示该midi设备使用的是那个版本的USB midi规范 |
5 | wTotalLength | 2 | 整数 | 总体长度,包括接下来的jack口的描述符和Element的描述符 |
- 接下来就是jack的描述符,和element的描述符。先来看看输入jack的描述符,如下
offset | Field | size | value | Description |
---|---|---|---|---|
0 | bLength | 1 | 整数 | 本描述符的大小 |
1 | bDescriptorType | 常量 | 只能为CS_INTERFACE | |
2 | bDescriptorSubtype | 常量 | 只能为MIDI_IN_JACK | |
3 | bJackType | 1 | 常量 | EMBEDDED or EXTERNAL前者表示内置,后者表示外接 |
4 | bJackID | 1 | 常量 | 该jack口的ID |
5 | iJack | 1 | 索引值 | 字符串描述符的索引值,用来描述该jack口 |
再来看看,输出jack口的描述符,如下:
offset | Field | size | value | Description |
---|---|---|---|---|
0 | bLength | 1 | 整数 | 本描述符的大小 |
1 | bDescriptorType | 常量 | 只能为CS_INTERFACE | |
2 | bDescriptorSubtype | 常量 | 只能为MIDI_OUT_JACK | |
3 | bJackType | 1 | 常量 | EMBEDDED or EXTERNAL前者表示内置,后者表示外接 |
4 | bJackID | 1 | 常量 | 该jack口的ID |
5 | bNrInputPins | 1 | 整数 | inputpin表示的是Element的引脚,每一个引脚就代表了一个midi数据流。bNrInputPins该字段就表示总共有多少个midi数据流,流进这个jack口 |
6 | baSourceID(1) | 1 | 整数 | 这个jack口链接的第一个输入引脚,对应的单元id(可能是一个Element单元,也可以是另外一个jack口) |
7 | BaSourcePin(1) | 1 | 整数 | 这个jack口链接的第一个输入引脚对应的单元,所对应的输出引脚号 |
… | … | … | … | … |
6+2*(p-1) | baSourceID § | 1 | 整数 | 这个jack口链接的第p个输入引脚,对应的单元的id |
6+2*(p-1)+1 | BaSourcePin§ | 1 | 整数 | 这个jack口链接的第p个输入引脚对应的单元,所对应的输出引脚号 |
5+2*p | iJack | 1 | 索引值 | 字符描述符的索引值,用来描述该jack |
接下来看看Elements的描述符:
offset | Field | size | value | Description |
---|---|---|---|---|
0 | bLength | 1 | 整数 | 本描述符的大小 |
1 | bDescriptorType | 常量 | 只能为CS_INTERFACE | |
2 | bDescriptorSubtype | 常量 | 只能为ELEMENT | |
3 | bElementID | 1 | 常量 | Element的ID |
4 | bNrInputPins | 1 | 整数 | 该Element对应的输入引脚数 |
5 | baSourceID(1) | 1 | 整数 | 该Element链接的第一个输入引脚所对应的单元的id |
6 | BaSourcePin(1) | 1 | 整数 | 该Element链接的第一个输入引脚所对应的单元的输出引脚号 |
… | … | … | … | … |
5+2*(p-1) | baSourceID § | 1 | 整数 | 该Element链接的第p个输入引脚所对应的单元的id |
5+2*(p-1)+1 | BaSourcePin§ | 1 | 整数 | 该Element链接的第p个输入引脚所对应的单元的输出引脚号 |
5+2*p | bNrOutputPins | 1 | 整数 | 该Element输出引脚个数 |
6+2*p | bInTerminalLink | 1 | 常量 | 该Element链接的输入终端的id(终端的含义在《USB声卡驱动(二):USB音频设备描述符》中有介绍) |
7+2*p | bOutTerminalLink | 1 | 常量 | 该Element链接的输出终端的id |
8+2*p | bElCapsSize | 1 | 整数 | bmElementCaps字段的字节大小 |
9+2*p | bmElementCaps | n | 位映射关系 | 表格未能完全展示,见后文 |
9+2*p+n | iElement | 1 | 索引值 | 字符描述符的索引,用来描述该Element |
接下来说明bmElementCaps字段的含义
- D0: CUSTOM UNDEFINED 。设备生厂商自己定义,比如可以用来标记该Element是一个唯一的,独有的处理单元,比如一个恐怖音效处理器
- D1: MIDI CLOCK。 支持MIDI CLOCK
- D2: MIDI TIME CODE (MTC)。 支持同步功能
- D3: MIDI MACHINE CONTROL (MMC)。支持MMC消息
- D4: GM1。支持GM1
- D5: GM2。 支持GM2
- D6: GS。支持GS格式
- D7: XG。支持XG
- D8: EFX。支持USB控制音效处理器
- D9: MIDI Patch Bay。 支持内部的MIDI patcher和路由
- D10: DLS1。支持DLS1
- D11: DLS2.支持DLS2
- D12 and higher。 表示未来可能用到的一些功能和类型
- USB端点描述符。USB端点描述符也分成两部分。第一部分跟《USB声卡驱动(二):USB音频设备描述符》一样。剩下的部分,就是跟MIDI相关的。如下:
|offset|Field|size|value|Description|
|—|—|—|—|—|
|0|bLength|1|整数|本描述符的大小|
|1|bDescriptorType|常量|只能为CS_ENDPOINT|
|2|bDescriptorSubtype|常量|只能为MS_GENERAL|
|3|bNumEmbMIDIJack|1|整数|该端点链接到的内置jack的数量|
|4|baAssocJackID(1)|1|常量|第一个jack的id|
|…|…|…|…|…|
|4+(n-1)|baAssocJackID(n)|1|常量|第n个jack的id|
本文章只能提供一些基本的理论支持,虽然很想把代码上传上去,但是由于保密原因,只能留下我所知道的基本理论知识,如果有错误请指正