usb composite device
USB复合装置(Composite Device)
平台:NuMicro
在USB Specification Revision 2.0定义USB复合装置(Composite Device)为「具有多个独立控制介面(Interface)的装置」
复合装置是一个具有多个功能和配置多个介面的组合设备,但是只有一个唯一的设备(Device)地址,透过相对应的USB设备驱动程式(Device Driver)来与主机通讯。
若是复合装置中有单一功能对应多个介面的类别就必须额外使用介面关联描述元(Interface association Descriptor, IAD),让设备中的不同介面与其相同功能建立关联。
介面(Interface)
复合装置只有一套PID/VID,透过不同的介面定义为不同的类别来实现多个功能。 USB设备必须额外使用介面关联描述元(IAD)来定义多重介面功能的复合装置。复合装置的介面描述元(Interface Descriptor)定义介面的每一个功能,USB主机透过此描述元来得知USB设备可用的功能。
端点(Endpoints)
复合装置的Endpoint分配,除了控制端点用于标准、特定类别和供应商特定的请求,其他Endpoint是给复合装置内的个别功能来使用,使用的传输方式与应用的需求有关。
Descriptor:
装置描述元(device descriptor)、
组态描述元(configuration descriptor)、
介面描述元(interface descriptor)、
特定的类别描述元(class-specific descriptors) 、
端点描述元(endpoint descriptor)、
字串描述元(String descriptor)。
一个USB装置的功能被使用之前,主机会先向USB装置取得组态资料,然后再由USB装置将这些描述元的资料当作组态资料一起传给主机,组态描述元除了本身组态描述元外,另外包含介面描述元、类别描述元、和端点描述元,而HID类别则会有特定的类别描述元,此描述元会交代报告(report)描述元和实体(physical)描述元;
Device descriptor:
一种为非多重介面功能的复合装置( Composite device without multi-interface functions),例如:HID Transfer + MSC、 HID Transfer + HID Keyboard和HID Mouse + HID Keyboard
另一种则是多重介面功能的复合装置(Composite device with multi-interface function),例如: VCOM + HID Transfer、VCOM + MSC、VCOM + HID Keyboard、Dual VCOM和Audio + HID Transfer。
组态描述元(Configuration descriptor)
组态描述元除了本身组态描述元外,另外还包含介面(interface)描述元、类别(class)描述元、和端点(endpoint)描述元。多重介面功能的复合装置介面描述元就必须使用介面关联描述元(IAD),以便将多重介面关联在单一装置功能中,可看作是多个独立的USB设备个别运作。
这里以usbd_vcom_and_hid_keyboard为例:
•功能1:VCOM(CDC Class),透过IAD定义相同功能的两个介面。 (介面0和介面1)
•功能2:Mass Storage(MSC Class),这个功能只有一个介面。 (介面2)
IAD中的第五个栏位bFunctionClass和第六个栏位bFunctionSubclassClass,填写时需要小心这两个值要与接下来要被关联的介面描述元的bInterfaceClass和bInterfaceSubClass相同。
HID类别会有特定的类别描述元,它是由描述HID介面的HID描述元及报告描述元所组成。 HID描述元是放在组态描述元中,在列举时用来辨识HID装置,再经由报告描述元内定义的格式来传送与接收资料。
装置枚举时主机向USB设备发出USB GetDescriptor请求来取得各种描述元,由于HID Mouse加上HID Keyboard的复合装置范例由两个HID功能组成,所以描述元除了有设备描述元、组态描述元及字串描述元,还另外包含HID描述元和报告描述元。
void USBD_GetDescriptor(void)
{
uint32_t u32Len;
u32Len = 0;
u32Len = g_usbd_SetupPacket[7];
u32Len <<= 8;
u32Len += g_usbd_SetupPacket[6];
switch (g_usbd_SetupPacket[3]) {
// Get Device Descriptor
case DESC_DEVICE: {
u32Len = Minimum(u32Len, LEN_DEVICE);
DBG_printF("Get device desc, %d\n", u32Len);
USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
break;
}
自行修改的项目有:Endpoint的配置、定义描述元及回应装置的标准请求和类别的特定请求
Item | 描述 |
---|---|
descriptors.c | 定义此范例所使用到的装置描述元、配置描述元、字串描述元 |
vcom_serial.c | CDC类别请求和每个端点的事件处理 |
vcom_serial.h | 定义CDC class request |
void USBD_IRQhandler(void) {
uint32_t u32IntSts = USBD_GET_INT_FLAG();
uint32_t u32State = USBD_GET_BUS_STATE();
-------------------------/ *热插拔中断*/ -----------------------------
if(u32IntSts & USBD_INTSTS_FLDET) {
/*清除热插拔中断状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_FLDET);
if(USBD_IS_attachED()) {
/* USB插入,开启USB和PHY */ USBD_ENABLE_USB() ; } else {
/* USB拔除,关闭USB功能*/ USBD_disable_USB(); } }
--------------------------/* USB汇流排中断*/ -------------------------
if(u32IntSts & USBD_INTSTS_BUS) {
/*清除USB汇流排状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_BUS);
if(u32State & USBD_STATE_USBRST) {
/* USB汇流排重置*/ USBD_ENABLE_USB(); USBD_SwReset(); } if(u32State & USBD_STATE_S USPEND) {
/*开启USB,关闭PHY */ USBD_DISABLE_PHY(); } if(u32State & USBD_STATE_RESUME) {
/*开启USB和PHY */ USBD_ENABLE_USB(); } }
---------------------------/* USB事件中断*/ --------------------------
if(u32IntSts & USBD_INTSTS_USB ) {
-----------/* SETUP事件*/---------
if(u32IntSts & USBD_INTSTS_SETUP) {
/*清除SETUP事件状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP);
/*清除控制端点的Ready状态*/ USBD_STOP_transaction(EP0); USBD_STOP_TRANSACTION(EP1); / *分析Setup Packet */ USBD_ProcessSetupPacket();
----------/*端点事件*/------------
if(u32IntSts & USBD_INTSTS_EP0) /* EP0被配置为控制端点IN */ {
/ *清除EP0事件状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_EP0); /*处理控制端点发送数据给主机完完成中断*/ USBD_CtrlIn(); }
if(u32IntSts & USBD_INTSTS_EP1) /* EP1被配置为控制端点OUT */ {
/*清除EP1事件状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);
/*处理主机通过控制端点发送数据给Device */ USBD_CtrlOut(); }
if(u32IntSts & USBD_INTSTS_EP3) {
/*清除EP3事件状态*/ USBD_CLR_INT_FLAG(USBD_INTSTS_EP3); /* EP3中断处理函数*/ EP3_Handler (); }
提供8个Endpoint可以配置成Control/Bulk /Interrupt/Isochronous传输类型。
一个USB设备中,可以有多个端点,每个端点的作用不同,所以需要端点地址来辨识端点。端点地址定义在USB_CFGx暂存器中的EP_NUM,它用来记录端点的地址,此地址需要跟端点描述元中的地址相对应,这样硬体才知道要跟哪个端点通讯,而每个端点发送/接收到的最大封包长度定义在USBD_MXPLD暂存器。
一个USB设备中,可以有多个端点,每个端点的作用不同,所以需要端点地址来辨识端点。端点地址定义在USB_CFGx暂存器中的EP_NUM,它用来记录端点的地址,此地址需要跟端点描述元中的地址相对应,这样硬体才知道要跟哪个端点通讯,而每个端点发送/接收到的最大封包长度定义在USBD_MXPLD暂存器。
描述符:
字符串描述符:
报告描述符:
报告描述符长度:
HID描述符在组态描述符内的位置:
非多重界面功能的复合装置:HID Transfer + MSC
在MSC程序上合并HID Transfer:
步骤1:端点配置及端点初始化
多重界面功能的复合装置:VCOM + HID Transfer
相关阅读
u盘插入电脑不显示(usb mass storage device----usb大
如果你在使用U盘或移动硬盘的时候,插入电脑但没有显示,而会在屏幕右下角弹出usb mass storage device(usb大容量存储设备),且在设备
DeviceIoControl这个api我们用的不多,但是很重要,有时会帮助我们实现一些特别的需求, 如获取硬件设备信息、与硬件设备通信(读写数据
Apple Mobile Device USB Driver驱动手动安装教程
前提电脑安装有itunse软件,这篇文章是解决PP助手或者爱思助手链接不上iPhone手机的解决方案之一,也是现在最常见的问题之一!有图有教
使用opencv VideoCapture遇到问题:Unable to stop the
使用OpenCV的VideoCapture 读取.mp4文件时出现以下错误:Unable to stop the stream: Inappropriate ioctl for device 此问题由于
device相关的操作接口: struct device *device_create(struct class *class, struct device *parent, dev_t devt, void