[原创] USB入门系列之七 —— USB的描述符及各种描述符之间的依赖关系<br /><br /> USB是个通用的总线,端口都是统一的。但是USB设备却各种各样,<br />例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的<br />设备的呢?这就要依赖于描述符了。<br /> USB的描述符主要有设备描述符,配置描述符,接口描述符,<br />端点描述符,字符串描述符,HID描述符,报告描述符等等。<br />关于报告描述符,请看我以前写的:《USB HID报告及报告描述符简介 》<br /> http://group.**/93/198.aspx。<br /><br /> 一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多<br />少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义<br />了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描<br />述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;<br />端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的<br />描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置<br />描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,<br />先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置<br />集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。<br />其中可能还会有获取设备序列号,厂商字符串,产品字符串等。<br /> <br /> 每种描述符都有自己独立的编号,如下:<br />#define DEVICE_DESCRIPTOR 0x01 //设备描述符<br />#define CONFIGURATION_DESCRIPTOR 0x02 //配置描述符<br />#define STRING_DESCRIPTOR 0x03 //字符串描述符<br />#define INTERFACE_DESCRIPTOR 0x04 //接口描述符<br />#define ENDPOINT_DESCRIPTOR 0x05 //端点描述符<br /> <br />下面分别详细介绍一下各描述符。<br /><br />1.设备描述符<br /><br />//定义标准的设备描述符结构<br /><br />typedef struct _DEVICE_DCESCRIPTOR_STRUCT<br />{<br /> BYTE blength; //设备描述符的字节数大小<br /> BYTE bDescriptorType; //设备描述符类型编号<br /> WORD bcdUSB; //USB版本号<br /> BYTE bDeviceClass; //USB分配的设备类代码<br /> BYTE bDeviceSubClass; //USB分配的子类代码<br /> BYTE bDeviceProtocol; //USB分配的设备协议代码<br /> BYTE bMaxPacketSize0; //端点0的最大包大小<br /> WORD idVendor; //厂商编号<br /> WORD idProduct; //产品编号<br /> WORD bcdDevice; //设备出厂编号<br /> BYTE iManufacturer; //设备厂商字符串的索引<br /> BYTE iProduct; //描述产品字符串的索引<br /> BYTE iSerialNumber; //描述设备序列号字符串的索引<br /> BYTE bNumConfigurations; //可能的配置数量<br />}<br />DEVICE_DESCRIPTOR_STRUCT, * pDEVICE_DESCRIPTOR_STRUCT;<br /><br />//实际的设备描述符示例<br />code DEVICE_DESCRIPTOR_STRUCT device_descriptor= //设备描述符<br />{<br /> sizeof(DEVICE_DESCRIPTOR_STRUCT), //设备描述符的字节数大小,这里是18字节<br /> DEVICE_DESCRIPTOR, //设备描述符类型编号,设备描述符是01<br /> 0x1001, //USB版本号,这里是USB01.10,即USB1.1。由于51是大端模式,所以高低字节交换<br /> 0x00, //USB分配的设备类代码,0表示类型在接口描述符中定义<br /> 0x00, //USB分配的子类代码,上面一项为0时,本项也要设置为0<br /> 0x00, //USB分配的设备协议代码,上面一项为0时,本项也要设置为0<br /> 0x10, //端点0的最大包大小,这里为16字节<br /> 0x7104, //厂商编号,这个是需要跟USB组织申请的ID号,表示厂商代号。<br /> 0xf0ff, //该产品的编号,跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序<br /> 0x0100, //设备出厂编号<br /> 0x01, //设备厂商字符串的索引,在获取字符串描述符时,使用该索引号来识别不同的字符串<br /> 0x02, //描述产品字符串的索引,同上<br /> 0x03, //描述设备序列号字符串的索引,同上<br /> 0x01 //可能的配置数为1,即该设备只有一个配置<br />};<br /><br />2.配置描述符<br /><br />//定义标准的配置描述符结构<br /><br />typedef struct _CONFIGURATION_DESCRIPTOR_STRUCT<br />{<br /> BYTE bLength; //配置描述符的字节数大小<br /> BYTE bDescriptorType; //配置描述符类型编号<br /> WORD wTotalLength; //此配置返回的所有数据大小<br /> BYTE bNumInterfaces; //此配置所支持的接口数量<br /> BYTE bConfigurationValue; //Set_Configuration命令所需要的参数值<br /> BYTE iConfiguration; //描述该配置的字符串的索引值<br /> BYTE bmAttributes; //供电模式的选择<br /> BYTE MaxPower; //设备从总线提取的最大电流<br />}<br />CONFIGURATION_DESCRIPTOR_STRUCT, * pCONFIGURATION_DESCRIPTOR_STRUCT;<br /><br />2.接口描述符<br /><br />//定义标准的接口描述符结构<br /><br />typedef struct _INTERFACE_DESCRIPTOR_STRUCT<br />{<br /> BYTE bLength; //接口描述符的字节数大小<br /> BYTE bDescriptorType; //接口描述符的类型编号<br /> BYTE bInterfaceNumber; //该接口的编号<br /> BYTE bAlternateSetting; //备用的接口描述符编号<br /> BYTE bNumEndpoints; //该接口使用的端点数,不包括端点0<br /> BYTE bInterfaceClass; //接口类型<br /> BYTE bInterfaceSubClass; //接口子类型<br /> BYTE bInterfaceProtocol; //接口遵循的协议<br /> BYTE iInterface; //描述该接口的字符串索引值<br />}<br />INTERFACE_DESCRIPTOR_STRUCT, * pINTERFACE_DESCRIPTOR_STRUCT;<br /><br />4.端点描述符<br /><br />//定义标准的端点描述符结构<br /><br />typedef struct _ENDPOINT_DESCRIPTOR_STRUCT<br />{<br /> BYTE bLegth; //端点描述符字节数大小<br /> BYTE bDescriptorType; //端点描述符类型编号<br /> BYTE bEndpointAddress; //端点地址及输入输出属性<br /> BYTE bmAttributes; //端点的传输类型属性<br /> WORD wMaxPacketSize; //端点收、发的最大包大小<br /> BYTE bInterval; //主机查询端点的时间间隔<br />}<br />ENDPOINT_DESCRIPTOR_STRUCT, * pENDPOINT_DESCRIPTOR_STRUCT;<br /><br />下面是一个配置描述符集合的定义<br />typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT<br />{<br /> CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;<br /> INTERFACE_DESCRIPTOR_STRUCT interface_descritor;<br /> ENDPOINT_DESCRIPTOR_STRUCT endpoint_descriptor[ENDPOINT_NUMBER];<br />}CON_INT_ENDP_DESCRIPTOR_STRUCT;<br /><br />配置描述符集合的示例<br /><br /><br />code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor= //配置描述符集合<br />{<br />//configuration_descriptor //配置描述符<br />{<br /> sizeof(CONFIGURATION_DESCRIPTOR_STRUCT), //配置描述符的字节数大小,这里为9<br /> CONFIGURATION_DESCRIPTOR, //配置描述符类型编号,配置描述符为2<br /> (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+<br /> sizeof(INTERFACE_DESCRIPTOR_STRUCT)+<br /> sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+<br /> (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+<br /> sizeof(INTERFACE_DESCRIPTOR_STRUCT)+<br /> sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256, //配置描述符集合的总大小<br /> 0x01, //只包含一个接口<br /> 0x01, //该配置的编号<br /> 0x00, //iConfiguration字段<br /> 0x80, //采用总线供电,不支持远程唤醒<br /> 0xC8 //从总线获取最大电流400mA<br />},<br />//interface_descritor //接口描述符<br />{<br /> sizeof(INTERFACE_DESCRIPTOR_STRUCT), //接口描述符的字节数大小,这里为9<br /> INTERFACE_DESCRIPTOR, //接口描述符类型编号,接口描述符为3<br /> 0x00, //接口编号为4<br /> 0x00, //该接口描述符的编号为0<br /> ENDPOINT_NUMBER, //非0端点数量为2,只使用端点主端点输入和输出<br /> 0x08, //定义为USB大容量存储设备<br /> 0x06, //使用的子类,为简化块命令<br /> 0x50, //使用的协议,这里使用单批量传输协议<br /> 0x00 //接口描述符字符串索引,为0,表示没有字符串<br />},<br /><br />//endpoint_descriptor[]<br />{<br /> { //主端点输入描述<br /> sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7<br /> ENDPOINT_DESCRIPTOR, //端点描述符类型编号,端点描述符为5<br /> MAIN_POINT_IN, //端点号,主输入端点<br /> ENDPOINT_TYPE_BULK, //使用的传输类型,批量传输<br /> 0x4000, //该端点支持的最大包尺寸,64字节<br /> 0x00 //中断扫描时间,对批量传输无效<br /> },<br /> <br /> { //主端点输出描述<br /> sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小,这里为7<br /> ENDPOINT_DESCRIPTOR, //端点描述符类型编号,端点描述符为5<br /> MAIN_POINT_OUT, //端点号,主输出端点<br /> ENDPOINT_TYPE_BULK, //使用的传输类型,批量传输<br /> 0x4000, //该端点支持的最大包尺寸,64字节<br /> 0x00 //中断扫描时间,对批量传输无效<br /> }<br />}<br />};<br /><br />其中关于端点的类型定义如下<br />//定义的端点类型<br />#define ENDPOINT_TYPE_CONTROL 0x00 //控制传输<br />#define ENDPOINT_TYPE_ISOCHRONOUS 0x01 //同步传输<br />#define ENDPOINT_TYPE_BULK 0x02 //批量传输<br />#define ENDPOINT_TYPE_INTERRUPT 0x03 //中断传输<br /><br />端点号的定义如下<br />#define MAIN_POINT_OUT 0x02 //2号输出端点<br />#define MAIN_POINT_IN 0x82 //2号输入端点<br /><br /> <br /><br />(来自USB小组专区:http://group.**/93/<br /> By computer00 @ 2007-09-14)<br />
|