USB描述符解析
USB描述符信息会被存储在USB设备中,在设备枚举过程中,USB主机会向USB设备发送GetDescriptor请求,USB设备在收到这个请求之后,会将USB描述符信息返回给USB主机,USB主机分析返回来的数据,判断出该设备是哪一种USB设备,按照描述符中的一些配置信息与设备建立相应的数据通道。USB描述符信息在USB协议中有详细描述。
标准的USB设备有5种USB描述符:设备描述符,配置描述符,字符串描述符,接口描述符,端点描述符。下面详解:
1.设备描述符 一个设备只有一个设备描述符,列出这个设备的配置参数
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 : 可能的配置数.指配置字符串的个数
2.配置描述符 一个设备中可以有多个配置描述符,每套配置描述符含有接口描述符,端点描述符
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:当使用SetConfiguration和GetConfiguration请求时所指定的配置索引值
iConfiguration: 用于描述该配置字符串描述符的索引.
bmAttributes: 供电模式选择.D7:总线供电,D6:自供电,D5:远程唤醒,D4~D0:保留
MaxPower: 总线供电的USB设备的最大消耗电流.以2mA为单位.例如0x32为50*2=100mA
3.接口描述符 一个配置描述符内可以含有多个接口,数量由配置描述符决定
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分配)
bInterfaceSubClass:子类型代码(由USB分配)
bInterfaceProtocol:协议代码(由USB分配)
iInterface:字符串描述符的索引
4.端点描述符 每个接口所需要的端点及其设置,数量由配置描述符决定
typedef struct _USB_ENDPOINT_DESCRIPTOR_
{
BYTE bLength,
BYTE bDescriptorType,
BYTE bEndpointAddress,
BYTE bmAttributes,
WORD wMaxPacketSize,
BYTE bInterval
}USB_ENDPOINT_DESCRIPTOR;
bLength : 描述符大小.固定为0x07.
bDescriptorType : 接口描述符类型.固定为0x05.
bEndpointType : USB设备的端点地址.D7端点方向,对于控制端点可以忽略,1/0:IN/OUT.D6-D4,保留.D3-D0:端点号.
bmAttributes : 端点属性.D7-D2,保留.D1-D0,传输类型:00控制,01同步,02批量,03中断.
wMaxPacketSize : 本端点接收或发送的最大信息包大小.
bInterval : 轮询数据传送端点的时间间隔.对于批量传送和控制传送的端点忽略.对于同步传送的端点,必须为1,对于中断传送的端点,范围为1-255.
5.字符串描述符 字符串描述符是可选的.如果不支持字符串描述符,其设备,配置,接口描述符内的所有字符串描述符索引都必须为0,每个字符串描述符都有一个索引,USB主机会在请求时按照顺序获取对应的字符串描述符,默认0位语言字符串描述符,后边都由每个描述符内容中指定,一般1为设备厂商字符串描述符,2为产品描述符,3为设备序列号字符串描述符,4为接口描述符
typedef struct _USB_STRING_DESCRIPTION_
{
BYTE bLength,
BYTE bDescriptionType,
BYTE bString[];
}USB_STRING_DESCRIPTION;
bLength : 描述符大小.由整个字符串的长度加上bLength和bDescriptorType的长度决定.
bDescriptorType : 接口描述符类型.固定为0x03.
bString[] : Unicode编码字符串.
下边是一套USB_CCID的设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符
CCID描述符配置
/*------------Descriptor of USB Device---------------------------*/
const UINT8 DeviceDescFS[18]=
{
0x12, //bLength //设备描述符的字节数大小,为0x12
0x01, //bDescriptorType //设备描述符类型编号,为0x01
0x00, //bcdUSB //USB规范版本号(BCD码) 0x0110
0x02,
0x00, //bDeviceClass //USB分配的设备类代码,0x01~0xfe 为标准设备类,0xff 为厂商自定义类型 0x00 不是在设备描述符中定义的,如HID
0x00, //bDeviceSubClass //USB分配的设备子类代码,同上,值由USB 规定和分配的
0x00, //bDeviceProtocl //USB分配的设备协议代码,同上
CTRL_PACKET_LEN, //bMaxPacketSize0 //端点0控制传输所支持的最大数据包长度,单位字节
0x12, //idVendor //厂商编号VID=0x2012
0x20,
0x02, //idProduct //产品编号PID=0x1402
0x14,
0x01, //bcdDevice //设备出厂编号bcdDevice=0x0100
0x02,
0x04, //iManufacturer //描述厂商字符串的索引Index of Vendor
0x1C, //iProduct //描述产品字符串的索引Index of Producr
0x14, //iSerialNumber //描述设备序列号字符串的索引0x03;//Index of SN
0x01 //bNumConfiguration//可能的配置数量
};
/*------------Descriptor of USB Configuation---------------------------*/
#define USB_SIZ_CONFIG_DESC (93 + 77)
UINT8 USBD_CCID_ConfigDescriptor[] =
{
/*Configuation Descriptor*/
0x09,/* bLength: Configuation Descriptor size */
0x02,/* bDescriptorType: Configuration */
LOBYTE(USB_SIZ_CONFIG_DESC),/* wTotalLength:no of returned bytes low*/
HIBYTE(USB_SIZ_CONFIG_DESC),,/* wTotalLength:no of returned bytes higt*/
0x02, /* bNumInterfaces: 2 interface */
0x01, /* bConfigurationValue: Configuration value */
0x04, /* iConfiguration: Index of string descriptor describing the configuration */
0x80, /* bmAttributes:bus powered */
0x32, /* MaxPower 200 mA */
/*Interface Descriptor*/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: Interface descriptor type*/
0x01, /* bInterfaceNumber: Number of Interface */ //接口号
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints*/ //接口端点数量
0x0B, /* bInterfaceClass: Smart Card */ //接口类型:0x0B智能卡类型
0x00, /* bInterfaceSubClass : SCSI transparent*/
0x00, /* nInterfaceProtocol */
0X05, /* iInterface: */ //接口字符串描述符的索引
//CCID class desc
0x36, //bLength //描述符长度, = 36H
0x21, //bDescriptorType //描述符类型, = 21H
0x10,0x01, //bcdCCID //CCID类规范版本号 = 1.1
0x00, //bMaxSlotIndex //所支持的最大插槽数 1个
0x03, //bVoltageSupport 5.0V //所支持卡的操作电压 01--5V; 02--3V; 04--1.8V 5V&3V
0x03,0x00,0x00,0x00, //dwProtocols T = 0 //所支持的卡通讯协议T=0&T=1
0xb8,0x0b,0x00,0x00, //dwDefaultClock 3MHz //默认卡操作时钟,以KHz为单位 3000KHz
0xb8,0x0b,0x00,0x00, //dwMaximumClock 3MHz //所支持的最小时钟 3000KHz
0x00, //bNumClockSupported 1 //所支持的时钟数 仅支持默认时钟
0x80,0x25,0x00,0x00, //dwDataRate 9600bps //默认IC卡通讯的位速率 9600
0x80,0x25,0x00,0x00, //dwMaxDataRate 115200bps //所支持的与IC卡通讯的最大位速率 9600
0x00, //bNumDataRatesSupported 1 //所支持的位速率数 仅支持默认速率
0xFE,0x00,0x00,0x00, //dwMaxIFSD //T=1协议下的最大FSD 254
0x00,0x00,0x00,0x00, //dwSynchProtocols //所支持的同步协议 当前版本为0x00000000
0x00,0x00,0x00,0x00, //dwMechanical //所支持的机械特性,00-无任何特性
0xBA,0x00,0x02,0x00, //dwFeatures //卡片特性 0x0002008A/0x0004023A
0x80,0x01,0x00,0x00, //dwMaxCCIDMessageLength //最大CCID信息长度 短格式下为261+10,此处设为384
0x00, //bClassGetResponse //GetReponse指令获取数据的缺省值 00
0x00, //bClassEnvelope //Envelope指令缺省值 00
0x00,0x00, //wLcdLayout //液晶尺寸0x0000 没有液晶
0x00, //bPINSupport //密码支持 不支持PIN
0x01, //bMaxCCIDBusySlots //所支持的可同时操作的插槽数 1个
/*Endpoint 1 Descriptor*/
0x07, //bLength //端点描述符的字节数大小
0x05, //bDescriptorType //端点描述符类型编号
EP1IN_NUMBER, //bEndpointAddress //端点地址及输入输出属性
0x02, //bmAttributes //端点的传输类型属性
0x40, //wMaxPacketSize //端点收、发的最大包的大小
0x00,
0x01, //bInterval //主机查询端点的时间间隔
/*Endpoint 1 Descriptor*/
0x07, //bLength //端点描述符的字节数大小
0x05, //bDescriptorType //端点描述符类型编号
EP1OUT_NUMBER, //bEndpointAddress //端点地址及输入输出属性
0x02, //bmAttributes //端点的传输类型属性
0x40, //wMaxPacketSize //端点收、发的最大包的大小
0x00,
0x01, //bInterval //主机查询端点的时间间隔
/*Endpoint 2 Descriptor*/
0x07, //bLength //端点描述符的字节数大小
0x05, //bDescriptorType //端点描述符类型编号
EP2IN_NUMBER, //bEndpointAddress //端点地址及输入输出属性
0x03, //bmAttributes //端点的传输类型属性
0x08, //wMaxPacketSize //端点收、发的最大包的大小//产生 xact error
0x00,
0x0a, //bInterval //主机查询端点的时间间隔
/*Interface Descriptor*/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: Interface */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints*/
0x0B, /* bInterfaceClass: Smart Card */
0x00, /* bInterfaceSubClass : SCSI transparent*/
0x00, /* nInterfaceProtocol */
0X06, /* iInterface: */
0x36,
0x21,
0x10,0x01,
0x00,
0x03,
0x03,0x00,0x00,0x00,
0xb8,0x0b,0x00,0x00,
0xb8,0x0b,0x00,0x00,
0x00,
0x80,0x25,0x00,0x00,
0x80,0x25,0x00,0x00,
0x00,
0xfe,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,
0xba,0x00,0x02,0x00,
0x80,0x01,0x00,0x00,
0x00,
0x00,
0x00,0x00,
0x00,
0x01,
/*Endpoint 3 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
0x05, /* bDescriptorType: Endpoint */
EP3OUT_NUMBER, /* bEndpointAddress: (OUT3) */
0x02, /* bmAttributes: Bulk */
0x40, /* wMaxPacketSize: */
0x00,
0x0A, /* bInterval: ignore for Bulk transfer */
/*Endpoint 3 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
0x05, /* bDescriptorType: Endpoint */
EP3IN_NUMBER, /* bEndpointAddress: (IN3) */
0x02, /* bmAttributes: Bulk */
0x40, /* wMaxPacketSize: */
0x00,
0x0A, /* bInterval: ignore for Bulk transfer */
};
/*------------Descriptor of Device String---------------------------*/
uint8_t USBD_LangIDDesc[0x04] =
{
0x04, /* bLength */
0x03, /* bDescriptorType */
0x09, /*English(US)*/
0x04,
};
#define USB_SIZ_STRING_SERIAL (10)
uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] =
{
USB_SIZ_STRING_SERIAL, /* bLength */
0x03, /* bDescriptorType */
'8', 0, '0', 0, '0', 0, '0', 0
};
uint8_t USBD_Interface1Strings[USB_DESCRIPTOR_LENGTH_STRING3] = {
sizeof(USBD_Interface1Strings),
0x03,
'S',0,'M',0,'A',0,'R',0,'T',0,' ',0,'C',0,'A',0,'R',0,'D',0,
};