CDC 系列文章
CDC 两路虚拟串口
前面两篇文章分别介绍了一路串口的两种实现方式
- 不使用 IAD 接口关联描述符实现一路虚拟串口
- 使用 IAD 接口关联描述符实现一路虚拟串口
本篇主要介绍使用 IAD 实现两路串口
如果需要实现更多路的虚拟串口,依次添加 IAD 即可。
描述符结构
设备描述符
配置描述符
接口关联描述符(CDC1)
接口1描述符(CDC ACM)
CDC 控制接口描述符
类特殊描述符(CDC Header, CDC Call, CDC ACM, CDC Union)
输入端点描述符
接口2描述符(CDC DATA)
CDC 数据接口描述符
输出端点描述符
输入端点描述符
接口关联描述符(CDC2)
接口3描述符(CDC ACM)
CDC 控制接口描述符
类特殊描述符(CDC Header, CDC Call, CDC ACM, CDC Union)
输入端点描述符
接口4描述符(CDC DATA)
CDC 数据接口描述符
输出端点描述符
输入端点描述符
设备描述符
12 01 00 02 EF 02 01 40 FE CA 02 40 00 01 01 02 03 01
Device Descriptor
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bLength | 1 | 0x12 | 描述符长度 |
1 | bDescriptorType | 1 | 0x01 | 设备描述符 |
2 | bcdUSB | 2 | 0x0200 | USB 2.0 |
4 | bDeviceClass | 1 | 0xEF | 类 |
5 | bDeviceSubClass | 1 | 0x02 | 子类 |
6 | bDeviceProtocol | 1 | 0x01 | 协议 |
7 | bMaxPacketSize0 | 1 | 0x40 | 端点 0 最大包长度 |
8 | idVendor | 2 | 0xCAFE | 厂商 ID |
10 | idProduct | 2 | 0x4002 | 产品 ID |
12 | bcdDevice | 2 | 0x0100 | 设备的版本号 |
14 | iManufacturer | 1 | 0x01 | 厂商字符串索引 |
15 | iProduct | 1 | 0x02 | 产品字符串索引 |
16 | iSerialNumber | 1 | 0x03 | 设备的序列号字符串索引 |
17 | bNumConfigurations | 1 | 0x01 | 配置数目 |
类,子类和协议参考 USB-IF
需要注意的是,如何使用接口关联描述符,这里的类,子类和协议需要固定为
bDeviceClass = 0xEF (miscellaneous device class)
bDeviceSubClass = 0x02 (common class)
bDeviceProtocol = 0x01 (interface association descriptor)
配置描述符集合
配置描述符
09 02 8D 00 04 01 00 80 32
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bLength | 1 | 0x09 | 描述符长度 |
1 | bDescriptorType | 1 | 0x02 | 配置描述符 |
2 | wTotalLength | 2 | 0x008d | 配置描述符集合总长度 |
4 | bNumInterfaces | 1 | 0x04 | 接口数目 |
5 | bConfigurationValue | 1 | 0x01 | 配置值 |
6 | iConfiguration | 1 | 0x00 | 该配置的字符串的索引值(0 表示没有) |
7 | bmAttributes | 1 | 0x80 | 配置的属性 |
8 | bMaxPower | 1 | 0x32 | 最大电流量,单位为 2 mA |
配置描述符的 bNumInterfaces(第五个数据) 的值为 4
,表明有四个接口
CDC1
接口关联描述符
08 0B 00 02 02 02 00 00
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bLength | 1 | 0x08 | 描述符长度 |
1 | bDescriptorType | 1 | 0x0B | 接口关联描述符 |
2 | bFirstInterface | 1 | 0 | 与该功能相关联的第一个接口的接口号 0 表示第一个接口 |
3 | bInterfaceCount | 1 | 2 | 与该功能相关联的连续接口的接口数量 |
4 | bFunctionClass | 1 | 2 | 类码 CDC |
5 | bFunctionSubClass | 1 | 2 | 子类码 CDC ACM |
6 | bFunctionProtocol | 1 | 0 | 协议码 不指定协议 |
7 | iFunction | 1 | 0 | 字符串描述符索引 |
类,子类和协议参考 USB-IF
- bFirstInterface 为 0 表示从第一个接口开始
- bInterfaceCount 为 2 表示有两个接口
所以接口关联描述符将接口1 和接口 2 关联到一起
后面的接口描述符,类特殊描述符和端点描述符等和 USB虚拟串口——CDC ACM 虚拟串口(不使用 IAD) 一致
CDC2
接口关联描述符
08 0B 02 02 02 02 00 00
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bLength | 1 | 0x08 | 描述符长度 |
1 | bDescriptorType | 1 | 0x0B | 接口关联描述符 |
2 | bFirstInterface | 1 | 2 | 与该功能相关联的第一个接口的接口号 2 表示第三个接口 |
3 | bInterfaceCount | 1 | 2 | 与该功能相关联的连续接口的接口数量 |
4 | bFunctionClass | 1 | 2 | 类码 CDC DATA |
5 | bFunctionSubClass | 1 | 2 | 子类码 CDC ACM |
6 | bFunctionProtocol | 1 | 0 | 协议码 不指定协议 |
7 | iFunction | 1 | 0 | 字符串描述符索引 |
类,子类和协议参考 USB-IF
- bFirstInterface 为 2 表示从第三个接口开始
- bInterfaceCount 为 2 表示有两个接口
所以接口关联描述符将接口3 和接口 4 关联到一起
后面的接口描述符,类特殊描述符和端点描述符等和 USB虚拟串口——CDC ACM 虚拟串口(不使用 IAD) 一致
类特殊命令
get line coding
A1 21 00 00 00 00 07 00
A1 21 00 00 02 00 07 00
- index = 0 发送到接口 1
- index = 2 发送到接口3
其他类特殊命令类似,用 index 区分不同的接口
数据交互
接口是软件的概念,数据交互往对应的端点写数据即可