文档库 最新最全的文档下载
当前位置:文档库 › USB枚举过程 USB Enumeration

USB枚举过程 USB Enumeration

USB枚举过程 USB Enumeration
USB枚举过程 USB Enumeration

标准usB描述符

描述符(Descriptor),是一个完整的数据结构,用于描述一个USB设备的所有属性。USB协议将这些属性信息进行分类,定义了五种标准的描述符,按照等级由高到低依次为:设备描述符、配置描述符、接口描述符和端点描述符,而字符串描述符是可选的。每一个描述符都是由一系列的字段组成,每个字段都是一连串的二进制数,表示相应的意义。

设备描述符给出了USB设备的通用信息,包括对设备及所有设备配置起全程作用的信息。一个USB 设备只能有一个设备描述符,但可以含有一个或多个配置。特别指出的是,缺省控制通道的数据包的长度(即USB设备端点0的长度)在设备描述符中得以说明,其它端点是在端点描述符中定义的。

USB设备的一个配置可以包含一个或多个接口,且每个接口都可以相互独立地工作。所有的USB设备至少要支持一个配置描述符。如果USB设备支持多个配置,则每个配置都需要相应的配置描述符。配置描述符给出了USB设备的属性和能力等配置信息。

接口一般都是由一系列端点所组成的集合体,用于实现某种特定的USB数据传输功能。某些USB设备类型,如HID设备,是在接口描述符中定义的,而不是在配置描述符中。接口描述符不可直接用SetDescriptor和GetDescriptor命令来存取,是作为配置描述符的一部分被返回。接口描述符给出了一个特定接口的属性信息。如果一个结构包含有备用的描述符,则可以在设备配置后加以改变。

端点描述符用于描述接口所使用的非0端点的属性,包括输入/输出方向、端点号和包的大小。端点描述符不可直接用SetDescriptor和GetDescriptor命令来存取,是作为配置描述符的一部分被返回。0端点无描述符。

字符串描述符是一个可选的描述符,其编号对应于前四种类型描述符中内容为索引的字段。

标准usB设备请求命令

USB定义了十一种标准的设备请求命令:Getstatus,ClearFeature,SetFeature,SetAddress,GetDeseriptor,SetDeseriptor,GetConfiguration,SetConfiguration,GetInterface,SetInterface,SynchFrame。这些USB设备请求命令,是通过设定控制传输的“初始设置步骤”中的一个8字节的Data0数据包,由主机发送给设备进行配置的。

通用USB固件程序流程

USB作为数据通信的标准,其软件和固件的流程具有一定的规则。其固件可以分为通用的枚举配置部分和类协议部分。在枚举配置部分,实现USB主机对设备的枚举和配置,使主机确认设备的功能,并提供资源。而类协议部分,则用来实现USB设备各自数据传输的功能,一般有相应的USB的类协议和规定作为编程的规范。例如MassStorage类设备的UFI命令。本节主要讨论USB共同的固件,即枚举配置部分的编程。

在USB的枚举过程,设备的状态可以分为连接态、上电态、缺省态、地址态、配置态和挂起态。这些状态都是一种暂态。

USB设备首次连接到主机后,主机将启动一个被称作总线枚举的进程,来枚举并管理设备状态的改变。编写USB主机或者设备端有关枚举阶段程序的具体过程如下:

(1)USB设备连接到Hub,Hub通过状态改变通道向主机汇报此USB设备己连接上。此时,USB设备处于连接态,它所连接的端口可以供应电流,但其他属性被禁止。

(2)主机通过命令询问Hub,了解连接事件的详细情况。

(3)一旦确定新设备已连上,主机至少等待100ms以使设备的接入操作完成以及电源的稳定工作。然后主机发出端口使能及复位命令给该端口。设备处于低电流上电态和连接态。

(4)Hub将端口的复位信号持续10ms后,端口己经被激活。此时,USB设备处于缺省态,并且可从端口上汲取小于100mA的电流,设备的所有寄存器及状态己经被复位,并通过缺省地址0与主机通信。

(5)主机通过缺省地址0,读取设备描述符,了解默认通道的一系列信息,确认USB设备的属性。

(6)设备配置,主机给设备分配一个唯一的地址,设备转向地址态。

(7)主机读取所有设备的配置描述符。

(8)基于得到的设备的配置描述符,主机给该设备重新配置一个配置值。此刻,设备就处于配置态并且配置有关的所有接口和端点。然后,USB设备可以从端口得到所要求的最大电量。从设备的角度来讲,它己经准备就绪了。

软件篇

USB设备端固件程序,枚举部分是全部程序的基础和重心,只有主机对设备枚举成功后,主机才能和设备径行正常的通信。

USB的枚举过程分为4个状态

1.接入态

主机检测到USB设备插上,击活端口,并发送复位命令(保持10ms)

2.默认态

主机使用默认地址读取设备描述符 (GET_DESCRIPTOR)

主机分配给设备一个总线上的唯一地址 (SET_ADDRESS)

3.地址态

主机从新的地址获取设备描述符 (GET_DESCRIPTOR)

主机获取所有设备的配置描述符 (GET_DESCRIPTOR)

4.配置态

主机设置描述符(设备,配置) (SET_CONFIGURATION)

主机读取配置状态(可选) (GET_CONFIGURATION)

主机读取接口状态(可选) (GET_INTERFACE)

USB枚举过程USB Enumeration

USB架构中, hub负责检测设备的连接和断开,利用其中断IN端点(Interrupt IN Endpoint)来向主机(Host)报告。在系统启动时,主机轮询它的根hub(Root Hub)的状态看是否有设备(包括子hub和子hub上的设备)连接。USB总线拓扑结构见下图(最顶端为主机的Root Hub):

USB总线拓扑结构

(USB Bus Topology)

一旦获悉有新设备连接上来,主机就会发送一系列的请求(Resqusts)给设备所挂载到的hub,再由hub建立起一条连接主机(Host)和设备(Device)之间的通信通道。然后主机以控制传输(Control Transfer)的方式,通过端点0(Endpoint 0)对设备发送各种请求,设备收到主机发来的请求后回复相应的信息,进行枚举(Enumerate)操作。所有的USB设备必须支持标准请求(Standard Requests),控制传输方式(Control Transfer)和端点0(Endpoint 0)。

从用户角度来看,枚举过程是自动完成并不可见的。但很多初次使用的设备连接时,系统会弹出说新硬件检测到,设备安装

成功,可以使用之类的消息提示框,而且有时还需要用户配合选择安装相关的驱动。

当枚举完成后,这个新添加的设备可在Windows的设备管理器里面看到,当用户删除这个设备/硬件时,系统把这个设备从设备管理器里删除。

对于一般的设备,固件(Firmware)内包含主机所要请求的信息,而有些设备则是完全由硬件来负责响应主机的请求。在主机方面则是由操作系统而非应用程序负责处理相关枚举操作。

枚举步骤

USB协议定义了设备的6种状态,仅在枚举过程种,设备就经历了4个状态的迁移:上电状态(Powered),默认状态(Default),地址状态(Address)和配置状态(Configured)(其他两种是连接状态和挂起状态(Suspend))。

下面步骤是Windows系统下典型的枚举过程,但是固件不能依此就认为所有的枚举操作都是按照这样一个流程行进。设备必须在任何时候都能正确处理所有的主机请求。

1.用户把USB设备插入USB端口或给系统启动时设备上电

这里指的USB端口指的是主机下的根hub或主机下行端口上的hub端口。Hub给端口供电,连接着的设备处于上电状态。

2.Hub监测它各个端口数据线上(D+/D-)的电压

在hub端,数据线D+和D-都有一个阻值在14.25k到24.8k 的下拉电阻Rpd,而在设备端,D+(全速,高速)和D-(低速)上有一个1.5k的上拉电阻Rpu。当设备插入到hub端口时,有上拉电阻的一根数据线被拉高到幅值的90%的电压(大致是3V)。hub检测到它的一根数据线是高电平,就认为是有设备插入,并能根据是D+还是D-被拉高来判断到底是什么设备(全速/低速)插入端口(全速、高速设备的区分在我将来的文章中描述)。如下图。

USB全速/高速设备上电连接

(Full-speed Device Cable and Resistor Connections)

检测到设备后,hub继续给设备供电,但并不急于与设备进行USB传输。

3. Host了解连接的设备

每个hub利用它自己的中断端点向主机报告它的各个端口的状态(对于这个过程,设备是看不到的,也不必关心),报告的

内容只是hub端口的设备连接/断开的事件。如果有连接/断开事件发生,那么host会发送一个 Get_Port_Status请求(request)以了解更多hub上的信息。Get_Port_Status等请求属于所有hub都要求支持的hub类标准请求(standard

hub-class requests)。

4.Hub检测所插入的设备是高速还是低速设备

hub通过检测USB总线空闲(Idle)时差分线的高低电压来判断所连接设备的速度类型,当host发来Get_Port_Status请求时,hub就可以将此设备的速度类型信息回复给host。(USB 2.0规范要求速度检测要先于复位(Reset)操作)。

5.hub复位设备

当主机获悉一个新的设备后,主机控制器就向hub发出一个Set_Port_Feature请求让hub复位其管理的端口。hub通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。当然,hub不会把这样的复位信号发送给其他已有设备连接的端口,所以其他连在该hub上的设备自然看不到复位信号,不受影响。

6.Host检测所连接的全速设备是否是支持高速模式

因为根据USB 2.0协议,高速(High Speed)设备在初始时是默认全速(Full Speed )状态运行,所以对于一个支持USB 2.0的高速hub,当它发现它的端口连接的是一个全速设备时,会进

行高速检测,看看目前这个设备是否还支持高速传输,如果是,那就切到高速信号模式,否则就一直在全速状态下工作。

同样的,从设备的角度来看,如果是一个高速设备,在刚连接bub或上电时只能用全速信号模式运行(根据USB 2.0协议,高速设备必须向下兼容USB 1.1的全速模式)。随后hub会进行高速检测,之后这个设备才会切换到告诉模式下工作。假如所连接的hub不支持USB 2.0,即不是高速hub,不能进行高速检测,设备将一直以全速工作。

高速设备检测的过程在我另外一篇文章(USB2.0速度识别)中有详细描述,这里不具体深入。

7. Hub建立设备和主机之间的信息通道

主机不停得向hub发送 Get_Port_Status请求,以查询设备是否复位成功。Hub返回的报告信息中有专门的一位用来标志设备的复位状态。

当hub撤销了复位信号,设备就处于默认/空闲状态(Default state),准备着主机发来的请求。设备和主机之间的通信通过控制传输,默认地址0,端点号0进行。在此时,设备能从总线上得到的最大电流是100mA。

8.主机发送Get_Descriptor请求获取默认管道的最大包长度

默认管道(Default Pipe)在设备一端来看就是端点0。主机此时发送的请求是默认地址0,端点0,虽然所有位分配地址

的设备都是通过地址0来获取主机发来的信息,但由于枚举过程不是多个设备并行处理,而是一次枚举一个设备的方式进行,所以不会发生多个设备同时响应主机发来的请求。

设备描述符的第8字节代表设备端点0的最大包大小。对于Windows系统来说,Get_Descriptor请求中的wLength一项都会设为64,虽然说设备所返回的设备描述符(Device Descriptor)长度只有18字节,但系统也不在乎,此时,描述符的长度信息对它来说是最重要的,其他的瞄一眼就过了。Windows系统还有个怪癖,当完成第一次的控制传输后,也就是完成控制传输的状态阶段,系统会要求hub对设备进行再一次的复位操作(USB规范里面可没这要求)。再次复位的目的是使设备进入一个确定的状态。

9.主机给设备分配一个地址

主机控制器通过Set_Address请求向设备分配一个唯一的

地址。在完成这次传输之后,设备进入地址状态(Address state),之后就启用新地址继续与主机通信。这个地址对于设备来说是终生制的,设备在,地址在;设备消失(被拔出,复位,系统重启),地址被收回。同一个设备当再次被枚举后得到的地址不一定是上次那个了。

10.主机获取设备的信息

主机发送 Get_Descriptor请求到新地址读取设备描述符,这次主机发送Get_Descriptor请求可算是诚心,它会认真解析设备描述符的内容。设备描述符内信息包括端点0的最大包长度,设备所支持的配置(Configuration)个数,设备类型,VID (Vendor ID,由USB-IF分配), PID(Product ID,由厂商自己定制)等信息。Get_Descriptor请求(Device type)和设备描述符(已抹去VID,PID等信息)见下图:

标准Get_Descriptor请求

(Get_Descriptor Request)

设备描述符(Device Descriptor)

之后主机发送Get_Descriptor请求,读取配置描述符(Configuration Descriptor),字符串等,逐一了解设备更详

细的信息。事实上,对于配置描述符的标准请求中,有时wLength 一项会大于实际配置描述符的长度(9字节),比如255。这样的效果便是:主机发送了一个

Get_Descriptor_Configuration 的请求,设备会把接口描述符,端点描述符等后续描述符一并回给主机,主机则根据描述符头部的标志判断送上来的具体是何种描述符。

11.主机给设备挂载驱动(复合设备除外)

主机通过解析描述符后对设备有了足够的了解,会选择一个最合适的驱动给设备。在驱动的选择过程中,Windows系统会和系统inf文件里的厂商ID,产品ID,有时甚至用到设备返回来的产品版本号进行匹配。如果没有匹配的选项,Windows会根据设备返回来的类,子类,协议值信息选择。如果该设备以前在系统上成功枚举过,操作系统会根据以前记录的登记信息而非inf 文件挂载驱动。当操作系统给设备指定了驱动之后,就由驱动来负责对设备的访问。

对于复合设备,通常应该是不同的接口(Interface)配置给不同的驱动,因此,需要等到当设备被配置并把接口使能后才可以把驱动挂载上去。

设备-配置-接口-端点关系见下图:

USB 设备-配置-接口-端点关系

(Device Configuration)

实际情况没有上述关系复杂。一般来说,一个设备就一个配置,一个接口,如果设备是多功能符合设备,则有多个接口。端点一般都有好几个,比如Mass Storage设备一般就有两个端点(控制端点0除外)。

12. 设备驱动选择一个配置

驱动(注意,这里是驱动,之后的事情都是有驱动来接管负责与设备的通信)根据前面设备回复的信息,发送

Set_Configuration请求来正式确定选择设备的哪个配置(Configuration)作为工作配置(对于大多数设备来说,一般只有一个配置被定义)。至此,设备处于配置状态,当然,设备也应该使能它的各个接口(Interface)。

对于复合设备,主机会在这个时候根据设备接口信息,给它们挂载驱动。

分享

5种USB描述符的定义详解!

来源:董丽伟的日志

标准的USB设备有5种USB描述符:设备描述符,配置描述符,字符串描述符,接口描述符,端点描述符.

一个设备只有一个设备描述符,下面详解:

设备描述符:

typedef struct _USB_DEVICE_DESCRIPTOR_

{

BYTE bLength,

BYTE bDescriptorType,

WORD bcdUSB,

BYTE bDeviceClass,

BTYE bDeviceSubClass,

BYTE bDeviceProtol,

BYTE bMaxPacketSize0,

WORD idVenderI,

WORD idProduct,

WORD bcdDevice,

BYTE iManufacturer,

BYTE iProduct,

BYTE iSerialNumber,

BYTE iNumConfiguations

}USB_DEVICE_DESCRIPTOR;

bLength : 描述符大小.固定为0x12.

bDescriptorType : 设备描述符类型.固定为0x01.

bcdUSB : USB 规范发布号.表示了本设备能适用于那种协议,如2.0=0200,1.1=0110等.

bDeviceClass : 类型代码(由USB指定)。当它的值是0时,表示所有接口在配置描述符里,并且所有接口是独立的。当它的值是1到FEH时,表示不同的接口关联的。当它的值是FFH 时,它是厂商自己定义的.

bDeviceSubClass : 子类型代码(由USB分配).如果bDeviceClass值是0,一定要设置为0.其它情况就根据USB-IF组织定义的编码.

bDeviceProtocol : 协议代码(由USB分配).如果使用USB-IF组织定义的协议,就需要设置这里的值,否则直接设置为0。如果厂商自己定义的可以设置为FFH.

bMaxPacketSize0 : 端点0最大分组大小(只有8,16,32,64有效).

idVendor : 供应商ID(由USB分配).

idProduct : 产品ID(由厂商分配).由供应商ID和产品ID,就可以让操作系统加载不同的驱动程序.

bcdDevice : 设备出产编码.由厂家自行设置.

iManufacturer : 厂商描述符字符串索引.索引到对应的字符串描述符.为0则表示没有.

iProduct : :产品描述符字符串索引.同上.

iSerialNumber : 设备序列号字符串索引.同上.

bNumConfigurations : 可能的配置数.指配置字符串的个数.

配置描述符:

typedef struct _USB_CONFIGURATION_DESCRIPTOR_

{

BYTE bLength,

BYTE bDescriptorType,

WORD wTotalLength,

BYTE bNumInterfaces,

BYTE bConfigurationValue,

BYTE iConfiguration,

BYTE bmAttributes,

BYTE MaxPower

}USB_CONFIGURATION_DESCRIPTOR;

bLength : 描述符大小.固定为0x09.

bDescriptorType : 配置描述符类型.固定为0x02.

wTotalLength : 返回整个数据的长度.指此配置返回的配置描述符,接口描述符以及端点描述符的全部大小.

bNumInterfaces : 配置所支持的接口数.指该配置配备的接口数量,也表示该配置下接口描述符数量.

bConfigurationValue : 作为Set Configuration的一个参数选择配置值.

iConfiguration : 用于描述该配置字符串描述符的索引.

bmAttributes : 供电模式选择.Bit4-0保留,D7:总线供电,D6:自供电,D5:远程唤醒.MaxPower : 总线供电的USB设备的最大消耗电流.以2mA为单位.

接口描述符:

typedef struct _USB_INTERFACE_DESCRIPTOR_

{

BYTE bLength,

BYTE bDescriptorType,

BYTE bInterfaceNumber,

BYTE bAlternateSetting,

BYTE bNumEndpoint,

BYTE bInterfaceClass,

BYTE bInterfaceSubClass,

BYTE bInterfaceProtocol,

BYTE iInterface

}USB_INTERFACE_DESCRIPTOR;

bLength : 描述符大小.固定为0x09.

bDescriptorType : 接口描述符类型.固定为0x04.

bInterfaceNumber: 该接口的编号.

bAlternateSetting : 用于为上一个字段选择可供替换的位置.即备用的接口描述符标号.bNumEndpoint : 使用的端点数目.端点0除外.

bInterfaceClass : 类型代码(由USB分配).

bInterfaceSunClass : 子类型代码(由USB分配).

bInterfaceProtocol : 协议代码(由USB分配).

iInterface : 字符串描述符的索引.

端点描述符:

typedef struct _USB_ENDPOINT_DESCRIPTOR_

{

BYTE bLength,

BYTE bDescriptorType,

BYTE bEndpointAddress,

BYTE bmAttributes,

WORD wMaxPacketSize,

BYTE bInterval

}USB_ENDPOINT_DESCRIPTOR;

bLength : 描述符大小.固定为0x07.

bDescriptorType : 接口描述符类型.固定为0x05.

bEndpointAddress : USB设备的端点地址.Bit7,方向,对于控制端点可以忽略,1/0:IN/O UT.Bit6-4,保留.BIt3-0:端点号.

bmAttributes : 端点属性.Bit7-2,保留.BIt1-0:00控制,01同步,02批量,03中断.wMaxPacketSize : 本端点接收或发送的最大信息包大小.

bInterval : 轮训数据传送端点的时间间隔.对于批量传送和控制传送的端点忽略.对于同步传送的端点,必须为1,对于中断传送的端点,范围为1-255.

字符串描述符:

typedef struct _USB_STRING_DESCRIPTION_

{

BYTE bLength,

BYTE bDescriptionType,

BYTE bString[1];

}USB_STRING_DESCRIPTION;

bLength : 描述符大小.由整个字符串的长度加上bLength和bDescriptorType的长度决定.bDescriptorType : 接口描述符类型.固定为0x03.

bString[1] : Unicode编码字符串.

USB描述符

USB是个通用的总线,端口都是统一的。但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的

设备的呢?这就要依赖于描述符了。

USB的描述符主要有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,HID描述符,报告描述符等等。关于报告描述符,请看我以前写的:《USB HID报告及报告描述符简介》

https://www.wendangku.net/doc/857681663.html,/93/198.aspx 。

一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义

了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;

端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置

描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置

集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。

每种描述符都有自己独立的编号,如下:

#define DEVICE_DESCRIPTOR 0x01 //设备描述符

#define CONFIGURATION_DESCRIPTOR 0x02 //配置描述符

#define STRING_DESCRIPTOR 0x03 //字符串描述符

#define INTERFACE_DESCRIPTOR 0x04 //接口描述符

#define ENDPOINT_DESCRIPTOR 0x05 //端点描述符

下面分别详细介绍一下各描述符。

1.设备描述符

//定义标准的设备描述符结构

typedef struct _DEVICE_DCESCRIPTOR_STRUCT

{

BYTE blength; //设备描述符的字节数大小

BYTE bDescriptorType; //设备描述符类型编号

WORD bcdUSB; //USB版本号

BYTE bDeviceClass; //USB分配的设备类代码

BYTE bDeviceSubClass; //USB分配的子类代码

BYTE bDeviceProtocol; //USB分配的设备协议代码

BYTE bMaxPacketSize0; //端点0的最大包大小

WORD idVendor; //厂商编号

WORD idProduct; //产品编号

WORD bcdDevice; //设备出厂编号

BYTE iManufacturer; //设备厂商字符串的索引

BYTE iProduct; //描述产品字符串的索引

BYTE iSerialNumber; //描述设备序列号字符串的索引

BYTE bNumConfigurations; //可能的配置数量

}

DEVICE_DESCRIPTOR_STRUCT, * pDEVICE_DESCRIPTOR_STRUCT;

//实际的设备描述符示例

code DEVICE_DESCRIPTOR_STRUCT device_descriptor= //设备描述符

{

sizeof(DEVICE_DESCRIPTOR_STRUCT), //设备描述符的字节数大小,这里是18字节DEVICE_DESCRIPTOR, //设备描述符类型编号,设备描述符是01

0x1001, //USB版本号,这里是USB01.10,即USB1.1。由于51是大端模式,所以高低字节交换0x00, //USB分配的设备类代码,0表示类型在接口描述符中定义

0x00, //USB分配的子类代码,上面一项为0时,本项也要设置为0

0x00, //USB分配的设备协议代码,上面一项为0时,本项也要设置为0

0x10, //端点0的最大包大小,这里为16字节

0x7104, //厂商编号,这个是需要跟USB组织申请的ID号,表示厂商代号。0xf0ff, //该产品的编号,跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序0x0100, //设备出厂编号

0x01, //设备厂商字符串的索引,在获取字符串描述符时,使用该索引号来识别不同的字符串0x02, //描述产品字符串的索引,同上

0x03, //描述设备序列号字符串的索引,同上

0x01 //可能的配置数为1,即该设备只有一个配置

};

2.配置描述符

//定义标准的配置描述符结构

typedef struct _CONFIGURATION_DESCRIPTOR_STRUCT

{

BYTE bLength; //配置描述符的字节数大小

BYTE bDescriptorType; //配置描述符类型编号

WORD wTotalLength; //此配置返回的所有数据大小

BYTE bNumInterfaces; //此配置所支持的接口数量

BYTE bConfigurationValue; //Set_Configuration命令所需要的参数值BYTE iConfiguration; //描述该配置的字符串的索引值

BYTE bmAttributes; //供电模式的选择

BYTE MaxPower; //设备从总线提取的最大电流

}

CONFIGURATION_DESCRIPTOR_STRUCT, * pCONFIGURATION_DESCRIPTOR_STRUCT;

2.接口描述符

//定义标准的接口描述符结构

typedef struct _INTERFACE_DESCRIPTOR_STRUCT

{

BYTE bLength; //接口描述符的字节数大小

BYTE bDescriptorType; //接口描述符的类型编号

BYTE bInterfaceNumber; //该接口的编号

BYTE bAlternateSetting; //备用的接口描述符编号

BYTE bNumEndpoints; //该接口使用的端点数,不包括端点0

BYTE bInterfaceClass; //接口类型

BYTE bInterfaceSubClass; //接口子类型

BYTE bInterfaceProtocol; //接口遵循的协议

BYTE iInterface; //描述该接口的字符串索引值

}

INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT;

4.端点描述符

//定义标准的端点描述符结构

typedef struct _ENDPOINT_DESCRIPTOR_STRUCT

{

BYTE bLegth; //端点描述符字节数大小

BYTE bDescriptorType; //端点描述符类型编号

BYTE bEndpointAddress; //端点地址及输入输出属性

BYTE bmAttributes; //端点的传输类型属性

WORD wMaxPacketSize; //端点收、发的最大包大小

BYTE bInterval; //主机查询端点的时间间隔

}

ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT;

下面是一个配置描述符集合的定义

typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT

{

CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;

INTERFACE_DESCRIPTOR_STRUCT interface_descritor;

ENDPOINT_DESCRIPTOR_STRUCT endpoint_descriptor[ENDPOINT_NUMBER];

}CON_INT_ENDP_DESCRIPTOR_STRUCT;

配置描述符集合的示例

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor= //配置描述符集合

{

//configuration_descriptor //配置描述符

{

sizeof(CONFIGURATION_DESCRIPTOR_STRUCT), //配置描述符的字节数大小,这里为9 CONFIGURATION_DESCRIPTOR, //配置描述符类型编号,配置描述符为2

(sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+

sizeof(INTERFACE_DESCRIPTOR_STRUCT)+

sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+

(sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+

sizeof(INTERFACE_DESCRIPTOR_STRUCT)+

sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256, //配置描述符集合的总大小0x01, //只包含一个接口

0x01, //该配置的编号

0x00, //iConfiguration字段

0x80, //采用总线供电,不支持远程唤醒

0xC8 //从总线获取最大电流400mA

},

//interface_descritor //接口描述符

{

sizeof(INTERFACE_DESCRIPTOR_STRUCT), //接口描述符的字节数大小,这里为9 INTERFACE_DESCRIPTOR, //接口描述符类型编号,接口描述符为3

0x00, //接口编号为4

0x00, //该接口描述符的编号为0

ENDPOINT_NUMBER, //非0端点数量为2,只使用端点主端点输入和输出

0x08, //定义为USB大容量存储设备

0x06, //使用的子类,为简化块命令

0x50, //使用的协议,这里使用单批量传输协议

0x00 //接口描述符字符串索引,为0,表示没有字符串

},

//endpoint_descriptor[]

{

{ //主端点输入描述

sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7

ENDPOINT_DESCRIPTOR, //端点描述符类型编号,端点描述符为5

MAIN_POINT_IN, //端点号,主输入端点

ENDPOINT_TYPE_BULK, //使用的传输类型,批量传输

0x4000, //该端点支持的最大包尺寸,64字节

0x00 //中断扫描时间,对批量传输无效

},

{ //主端点输出描述

sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7

ENDPOINT_DESCRIPTOR, //端点描述符类型编号,端点描述符为5

MAIN_POINT_OUT, //端点号,主输出端点

ENDPOINT_TYPE_BULK, //使用的传输类型,批量传输

0x4000, //该端点支持的最大包尺寸,64字节

0x00 //中断扫描时间,对批量传输无效

}

}

};

其中关于端点的类型定义如下

//定义的端点类型

#define ENDPOINT_TYPE_CONTROL 0x00 //控制传输

#define ENDPOINT_TYPE_ISOCHRONOUS 0x01 //同步传输

#define ENDPOINT_TYPE_BULK 0x02 //批量传输

#define ENDPOINT_TYPE_INTERRUPT 0x03 //中断传输

端点号的定义如下

#define MAIN_POINT_OUT 0x02 //2号输出端点

#define MAIN_POINT_IN 0x82 //2号输入端点

设备描述符配置包

在USB通讯里,从主控器发出来的第一个配置包就是设备描述符配置包,目的只有一个,就是获取插入的USB属性,以便加载合适的驱动程序。现在就来详细地分析一下设备描述符包的定义。

在USB2.0的协议里找到9.3 USB Device Requests里就找到这个结构的定义,这里我使用C的定义结构如下:

typedef struct_USB_SETUP_PACKET

{

REQUEST_TYPE bmRequestType;

BYTE bRequest;

WORD_BYTE wValue;

WORD_BYTE wIndex;

WORD wLength;

} USB_SETUP_PACKET;

相关文档