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,
};