2 USB標准設備請求的結構

2.1 標准請求
bmRequestType 的D6~D5為00的請求,USB協議定義了11個標准請求(bRequest),其名字與相應的bRequest的值如下表:

表3.5.3是各個標准請求的結構及需要傳輸的數據,常用的幾個請求有:GET_DESCRIPTOR、SET_ADDRESS和SET_CONFIGURATION。下面詳細介紹這幾個請求:

2.1.1 GET_DESCRIPTOR 請求

需要注意的是 wValue, wIndex, wLength 這三個域都是兩字節的,在USB協議中規定,使用的是小段結構,即第字節在先,高字節在后。
- wValue,的第一字節(字符)表示同一中描述類型(比如字符串描述符)中具體的某個描述符(如廠商或者產品字符),第二字節表示描述類型的編號。
- wIndex,只在獲取字符串描述符中表示語言的ID號,除此之外為0。
- wLength,表示要求設備返回數據的字節數,設備實際返回可以比它小。
對於全速和低速模式 ,獲取描述符的標准請求只有三種:獲取設備、配置、字符串的描述符,另外的接口和端點描述符是跟隨配置描述符一並返回的,不能單獨請求返回。

2.1.2 SET_ADDRESS 請求
當設備復位后,都使用默認地址0。主機從地址0的設備獲取設備描述符,一旦收到第一次設備描述符之后,主機就會發送設置地址的請求,以盡量減少設備使用公共地址0的時間。

2.1.3 SET_CONFIGURATION 請求
SET_CONFIGURATION和SET_ADDRESS請求很類似,區別是wValue的意義:SET_ADDRESS中,wValue的第一字節(低字節)表示設備的地址;SET_CONFIGURATION則為配置的值。該值與配置描述符的配置編號一致時,表示選中該配置,通常為1,因為大多數USB設備只有一種設置;若為0,則設備進入地址設置狀態。

獲取描述符請求是在枚舉過程中用得最多的一個請求,舉一個主機的例子:
0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00
它是一個請求設備描述符的標准請求,請求的數據長度64字節。
2.2 描述符類型的實現
2.2.1 設備描述符的實現
每個設備必須有且僅有一個設備描述符,結構如表3.6.1所示。

- bLength,表示該描述符的長度,固定的,共18字節。
- bDescriptorType,描述符的類型,取值如表3.5.5所示。
- bcdUSB,設備使用的USB協議版本。USB1.1可以寫成0x0110,小端結構:0x10,0x01;同理USB2.0可以寫成0x0200,小端結構:0x00,0x02。
- bDeviceClass,設備使用的類代碼,一般為0。當為0時,bDeviceSubClass必須為0,且bDeviceProtocol也應該為0。當為0xff,表示使用自定義設備類。
- bDeviceSubClass,設備使用的子類代碼。
- bDeviceProtocol,設備使用的協議,為0時不用類所定義的協議,為0xff時使用自定義協議。需要結合設備類和設備子類使用才有意義。
- bMaxPackSize0,端點0的最大包長。取值可以是8、16、32、64。
- idVender,廠商ID。由USB協會分配,不能隨意使用,此外主機驅動一般根據廠商ID、產品ID已經產品序列號來安裝驅動程序。
- idProduct,產品ID。
- iManufacturer、iProduct、iSerialNumber,相應字符串的索引值,放在wValue的第一字節。為0時,表示沒有。
- bNumConfigurations,大部分USB設備只有一個配置,即該字段值為1。
代碼如下:
/* USB Standard Device Descriptor,設備描述符 */ const uint8_t Virtual_Com_Port_DeviceDescriptor[] = { 0x12, /* bLength,該描述符長度(18字節) */ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType,設備描述符為0x01 */ 0x00, 0x02, /* bcdUSB = 2.00, 本設備使用的USB版本 */ 0x02, /* bDeviceClass: CDC,類代碼 */ 0x00, /* bDeviceSubClass:子類代碼 */ 0x00, /* bDeviceProtocol:設備所使用的協議 */ 0x40, /* bMaxPacketSize0:端點0最大包長 */ 0x83, 0x04, /* idVendor = 0x0483:廠商ID */ 0x40, 0x57, /* idProduct = 0x5740: 產品ID */ 0x00, 0x02, /* bcdDevice = 2.00: 設備版本號 */ 1, /* iManufacturer: 描述廠商的字符串索引 */ 2, /* iProduct: 描述產品的字符串索引 */ 3, /* iSerialNumber: 描述序列號的字符串索引 */ 0x01 /* bNumConfigurations:可能的配置數 */ };
2.2.2 配置描述符的結構

- bmAtrributes:D7,保留必須為1。D6為供電方式,1表示設備自供電,0表示設備是總線供電的。D5為1時表示支持遠程喚醒,0不支持。D4~D0,保留設為0。
2.2.3 接口描述符

2.2.4 端點描述符

- bEndPointAddress:最高位D7為該端點的傳輸方向,1為主機輸入(像Input的首字母),0為主機輸出(像Output首字母)
- bmAttributes:最低位D1~D0:表示傳輸類型,0為控制傳輸,1為等時傳輸,2為批量傳輸,3為中斷傳輸。
- 如果該端點是非等時傳輸,D7~D2為0。否則,D3~D2表示同步的類型:0為無同步,1為異步,2為適配,3為同步。
- D5~D4表示用途:0為數據端點,1為反饋端點,2為暗含反饋的數據端點,3是保留值。D7~D6,保留。
- bInterval:對於中斷端點,表示查詢的幀間隔數。
2.2.5 HID描述符的結構
USB鼠標屬於HID類,HID類的設備在配置描述時還需要一個HID描述符,它是一個類描述符,應該跟在接口描述符后面。

- bLength:是該描述符的總長度,它的大小與該描述符中下級描述符的個數有關。例如只有一個下級描述符時,總長為 1+1+2+1+1+1+2=9字節。
- bcdHID:使用USB HID1.1協議,因此為0x0110。
- bCountryCode:美式鍵盤為33,即0x21。
- bNumDescriptors:下級描述符的數量,至少為1。
- bDescriptorType:下級描述符的類型,報告描述符的編號為0x22,物理描述符的編號為0x23。
