第8讲:复合设备——一个设备身兼数职
本讲目标
理解一个 USB 设备如何通过多个接口提供不同功能,并认识复合设备的描述符组织方式。
一、一个 USB 插头可以承载多个功能吗?
当然可以。
例如,一个单片机设备可以同时提供:
- HID 键盘功能。
- HID 鼠标功能。
- CDC 虚拟串口功能。
电脑只需要通过一个 USB 连接,就可以识别这些功能。
其关键不在于把多个 USB 设备电气上简单并联,而在于通过描述符定义多个接口,并让 Host 分别识别这些接口。
二、复合设备的描述符结构
可以用下面的结构理解:
USB Device
|
└── Configuration
|
├── Interface 0:HID Keyboard
| └── Interrupt IN
|
├── Interface 1:HID Mouse
| └── Interrupt IN
|
└── CDC
├── Communication Interface
└── Data Interface
├── Bulk IN
└── Bulk OUT
这是一种概念示意。实际 CDC 描述符还会涉及类专用描述符和接口关联关系;端点配置也应遵循对应 USB 类规范。
三、操作系统如何区分这些功能?
Host 读取设备的配置描述符集合后,可以看到多个接口。
每个接口拥有自己的接口编号、类信息以及相应的端点配置。
操作系统据此识别各个接口,并根据自身驱动模型进行匹配。
例如:
- HID 接口由 HID 驱动处理。
- CDC 接口由相应的 CDC 驱动处理。
不同操作系统的具体驱动绑定和设备呈现方式可能不同,但基本思想都是通过接口和相应的类规范识别功能。
四、复合设备与多个独立 USB 设备有什么区别?
多个独立 USB 设备通常各自拥有独立的设备描述符和设备地址。
复合设备则通过同一个 USB 设备的配置描述符集合暴露多个接口功能。
因此,在抓包和设备管理器中判断设备结构时,不能只看功能数量,还需要查看设备描述符、配置描述符和接口描述符之间的关系。
五、开发复合设备时需要注意什么?
首先,确保 bNumInterfaces 与配置中实际声明的接口数量一致。
其次,检查接口编号、备用设置、端点地址、端点数量和描述符总长度是否正确。
此外,还要确保 HID 报告描述符长度与实际内容一致,CDC 通信接口与数据接口的关联信息正确。
如果某个接口没有被系统识别,建议先检查描述符是否自洽,再查看系统驱动绑定结果。
六、为什么建议逐步增加功能?
如果一开始就同时实现 HID 键盘、HID 鼠标和 CDC,出现问题时就很难快速判断是哪个接口导致的。
更稳妥的方式是:
- 先让单一 HID 接口正常工作。
- 增加第二个 HID 接口。
- 确认两个接口都能独立工作。
- 再加入 CDC。
- 最后进行多接口并发测试。
这种方式可以把问题逐步缩小,避免一次性引入太多变量。
七、本讲小结
复合设备的关键是通过一个 USB 设备的描述符体系暴露多个接口功能,再由 Host 分别识别和处理。
对于单片机开发者来说,理解接口、端点和驱动绑定之间的关系,比单纯记住某个 SDK 的配置选项更重要。
留给下一讲的问题
如果设备枚举失败、某个端点没有数据,或者系统只识别了部分接口,我们应该怎样定位问题?
下一讲,我们使用 USB 抓包工具 观察 Host 和 Device 之间的实际通信过程。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)