USB 協議的完美總結

USB協議[轉]__總結得很好  (轉載)


一 枚舉過程:
◆ 用戶將一個USB設備插入USB端口,主機爲端口供電,設備此時處於上電狀態。
◆主機檢測設備。
◆集線器使用中斷通道將事件報告給主機。
◆主機發送Get_Port_Status(讀端口狀態)請求,以獲取更多的設備信息。
◆集線器檢測設備是低速運行還是高速運行,並將此信息送給主機,這是對Get_Port_Status請求的響應。
◆主機發送Set_Port_Feature(寫端口狀態)請求給集線器,要求它復位端口。
◆集線器對設備復位。
◆主機使用Chirp K信號來了解全速設備是否支持高速運行。
◆主機發送另一個Get_Port_Status請求,確定設備是否已經從復位狀態退出。
◆設備此時處於缺省狀態,且已準備好在零端點通過缺省通道響應主機控制傳輸。缺省地址爲00h,設備能從總線獲取高達100mA的電流。
◆主機發送Get_Deor(讀設備描述符)報文,以便確定最大數據包大小。設備描述符的八個字節是bMaxPacketSize。
◆通過發送Set_Address(寫地址)請求,主機分配地址,設備此時處於地址狀態。
◆主機發送Get_Deor報文,以獲取更多的設備信息。主機通過發送描述符響應設備請求,隨後發送全部的次級描述符。
◆主機分配並加載設備驅動程序。
◆通過發送Set_Configuration(寫配置)請求,主機的設備驅動程序選擇一個有效配置,設備此時處於配置狀態。
◆主機爲複合設備接口分配驅動程序。
◆如果集線器檢測到有過流現象,或者主機要求集線器關閉電源,則USB總線切斷設備供電電源。在這種情況下,設備與主機無法通信,但設備處於連接狀態。
◆如果在3毫秒內設備在總線上未見任何動作,則它將進入掛起狀態,在掛起狀態設備消耗的總線電能最少。


還有一個差不多,如下:
1)集線器檢測新設備
主機集線器監視着每個端口的信號電壓,當有新設備接入時便可覺察。(集線器端口的兩根信號線的每一根都有15kΩ的下拉電阻,而每一個設備在D+都有一個1.5kΩ的上拉電阻。當用USB線將PC和設備接通後,設備的上拉電阻使信號線的電位升高,因此被主機集線器檢測到。)
(2)主機知道了新設備連接後
每個集線器用中斷傳輸來報告在集線器上的事件。當主機知道了這個事件,它給集線器發送一個Get_Status請求來了解更多的消息。返回的消息告訴主機一個設備是什麼時候連接的。
(3)集線器重新設置這個新設備
當主機知道有一個新的設備時,主機給集線器發送一個Set_Feature請求,請求集線器來重新設置端口。集線器使得設備的USB數據線處於重啓(RESET)狀態至少10ms。
(4)集線器在設備和主機之間建立一個信號通路
主機發送一個Get_Status請求來驗證設備是否激起重啓狀態。返回的數據有一位表示設備仍然處於重啓狀態。當集線器釋放了重啓狀態,設備就處於默認狀態了,即設備已經準備好通過Endpoint 0 的默認流程響應控制傳輸。即設備現在使用默認地址0x0與主機通信。
(5)集線器檢測設備速度 
集線器通過測定那根信號線(D+或D-)在空閒時有更高的電壓來檢測設備是低速設備還是全速設備。(全速和高速設備D+有上拉電阻,低速設備D-有上拉電阻)。
以下,需要USB的firmware進行干預
(6)獲取最大數據包長度 
PC向address 0發送USB協議規定的Get_Device_Deor命令,以取得卻缺省控制管道所支持的最大數據包長度,並在有限的時間內等待USB設備的響應,該長度包含在設備描述符的bMaxPacketSize0字段中,其地址偏移量爲7,所以這時主機只需讀取該描述符的前8個字節。注意,主機一次只能列舉一個USB設備,所以同一時刻只能有一個USB設備使用缺省地址0。
以下操作雷同,不同操作系統設定時延是不一樣的,比如說win2k大概是幾毫秒,如果沒有反應就再發送一次命令,重複三次。 
(7)主機分配一個新的地址給設備
主機通過發送一個Set_Address請求來分配一個唯一的地址給設備。設備讀取這個請求,返回一個確認,並保存新的地址。從此開始所有通信都使用這個新地址。
(8)主機向新地址重新發送Get_Device_Deor命令,此次讀取其設備描述符的全部字段,以瞭解該設備的總體信息,如VID,PID。
(9)主機向設備循環發送Get_Device_Configuration命令,要求USB設備回答,以讀取全部配置信息。
(10)主機發送Get_Device_String命令,獲得字符集描述(unicode),比如產商、產品描述、型號等等。
(11)此時主機將會彈出窗口,展示發現新設備的信息,產商、產品描述、型號等。
(12)根據Device_Deor和Device_Configuration應答,PC判斷是否能夠提供USB的Driver,一般win2k能提供幾大類的設備,如遊戲操作杆、存儲、打印機、掃描儀等,操作就在後臺運行。但是Win98卻不可以,所以在此時將會彈出對話框,索要USB的Driver。
(13)加載了USB設備驅動以後,主機發送Set_Configuration(x)命令請求爲該設備選擇一個合適的配置(x代表非0的配置值)。如果配置成功,USB設備進入“配置”狀態,並可以和客戶軟件進行數據傳輸。
此時,常規的USB完成了其必須進行的配置和連接工作。查看註冊表,能夠發現相應的項目已經添加完畢,至此設備應當可以開始使用。不過,USB協議還提供了一些用戶可選的協議,設備如果不應答,也不會出錯,但是會影響到系統的功能。

 

    1.當主機用輪詢的方式檢測到USB端口有新的設備插入時,主機就會給HUB發送總線復位命令,要求HUB進行總線復位。
              設備連接到主機並初始化完成(Softconnect 位被設置爲 1),主機檢測到D+與D-之間有電壓差,就認爲有新的設置接入。主機等待100ms後發出復位請求。設備接到復位請求後將產生一個外部中斷信號。

     2.主機使用默認地址0,來讀取設備的描述符。
             發送 Get_descriptor標準請求。主機向D12發送一個八字節請求:80 06 00 01 00 00 40 00    D12接收到請求後產生一箇中斷,我們可以通過讀中斷寄存器知道中斷源,並且可以加讀最後狀態寄存器來確定第一個接到的包是否爲一個Setup包。當控制器處理程序判斷出它是一個Get_descriptor請求是,把設備描述符的前16個字節發送到端點0緩衝區中。剩下的2個字節描述符第一次請求時不再發送。

     3.主機給設備分配一個地址
              當主機收到正確的前16字節描述符後,會給設備分配一個地址,我的PC分配的地址爲:0x03(這個要看你的機子當時的USB接口設備數目而定) Set_Address 請求所發送的數據爲:00 05 03 00 00 00 00 00 ,其中的03就表示主機爲設備分配的地址爲0x03,在以後的通信裏設備就只對0x03地址作出應答。當D12產生一個接收中斷後,跟據所分配的地址設置D12的地址寄存器相應位

    4.主機以地址0x03 ,重新請求設備描述符
        主機發送設備描述符標準請求Get_descriptor :80 06 00 01 00 00 12 00  此次將要求把18個字節全部發送完。所以主機要分兩次來讀取。第一次發送16個字節,第三次發送兩個字節,最後主機發送0表示發送完畢的應答。

    5.主機發送Get_configuration請求
         由於事先沒有知道描述符的長度,所以先以0xff的長度進行請求。其數據爲:80 06 00 02 00 00 FF 00   我用的是周立功公司賣的D12開發板光盤資料中提供的驅動程序,發送的應答是一個描述集合其結構如下:
typedef struct USB_DESCRIPTOR {
    USB_CONFIGURATION_DESCRIPTOR ConfigDescr;        //配置描述符
    USB_INTERFACE_DESCRIPTOR InterfaceDescr;        //接口描述符
    USB_ENDPOINT_DESCRIPTOR EP1_TXDescr;            //端點1輸入描述符
    USB_ENDPOINT_DESCRIPTOR EP1_RXDescr;            //端點1輸出描述符
    USB_ENDPOINT_DESCRIPTOR EP2_TXDescr;            //端點2輸入描述符
    USB_ENDPOINT_DESCRIPTOR EP2_RXDescr;            //端點2輸出描述符
} USB_DESCRIPTOR, *PUSB_DESCRIPTOR;


     6.Set_Conficuration
           當讀取完成描述符之後,需要對設備進行配置,使得設備從地址狀態進入配置狀態。這個在寫固件的時候可以提高運行效率。
      
     7.讀取配置狀態。  
  
     8.當主機能正確地收到這些數據之後,就可以加載D12的驅動程序。這時就可能作應用中的數據傳輸了。

         使用USB View 採集到的數據:

Device Descriptor:
bcdUSB:             0x0100
bDeviceClass:         0xDC
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x10 (16)
idVendor:           0x0471
idProduct:          0x0666
bcdDevice:          0x0100
iManufacturer:        0x00
iProduct:             0x00
iSerialNumber:        0x00
bNumConfigurations:   0x01

ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed:     Full
Device Address:       0x02
Open Pipes:              4

Endpoint Descriptor:
bEndpointAddress:     0x81
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x01
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x82
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x02
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A


       參考資料:《PDIUSBD12 USB固件編程和驅動開發》
                                           驅動開發網

 
USB 基本知識

 

USB的重要關鍵字:

1、端點:位於USB設備或主機上的一個數據緩衝區,用來存放和發送USB的各種數據,每一個端點都有惟一的確定地址,有不同的傳輸特性(如輸入端點、輸出端點、配置端點、批量傳輸端點)

2、幀:時間概念,在USB中,一幀就是1MS,它是一個獨立的單元,包含了一系列總線動作,USB將1幀分爲好幾份,每一份中是一個USB的傳輸動作。

3、上行、下行:設備到主機爲上行,主機到設備爲下行

 

 

下面以一問一答的形式開始學習吧。

 

問題一:USB的傳輸線結構是如何的呢?

答案一:一條USB的傳輸線分別由地線、電源線、D+、D-四條線構成,D+和D-是差分輸入線,它使用的是3.3V的電壓(注意哦,與CMOS的5V電平不同),而電源線和地線可向設備提供5V電壓,最大電流爲500MA(可以在編程中設置的,至於硬件的實現機制,就不要管它了)。

 

問題二:數據是如何在USB傳輸線裏面傳送的

答案二:數據在USB線裏傳送是由低位到高位發送的。

 

問題三:USB的編碼方案?

答案三:USB採用不歸零取反來傳輸數據,當傳輸線上的差分數據輸入0時就取反,輸入1時就保持原值,爲了確保信號發送的準確性,當在USB總線上發送一個包時,傳輸設備就要進行位插入***作(即在數據流中每連續6個1後就插入一個0),從而強迫NRZI碼發生變化。這個瞭解就行了,這些是由專門硬件處理的。

 

問題四:USB的數據格式是怎麼樣的呢?

答案四:和其他的一樣,USB數據是由二進制數字串構成的,首先數字串構成域(有七種),域再構成包,包再構成事務(IN、OUT、SETUP),事務最後構成傳輸(中斷傳輸、並行傳輸、批量傳輸和控制傳輸)。下面簡單介紹一下域、包、事務、傳輸,請注意他們之間的關係。

(一)域:是USB數據最小的單位,由若干位組成(至於是多少位由具體的域決定),域可分爲七個類型:

1、同步域(SYNC),八位,值固定爲0000 0001,用於本地時鐘與輸入同步

2、標識域(PID),由四位標識符+四位標識符反碼構成,表明包的類型和格式,這是一個很重要的部分,這裏可以計算出,USB的標識碼有16種,具體分類請看問題五。

3、地址域(ADDR):七位地址,代表了設備在主機上的地址,地址000 0000被命名爲零地址,是任何一個設備第一次連接到主機時,在被主機配置、枚舉前的默認地址,由此可以知道爲什麼一個USB主機只能接127個設備的原因。

4、端點域(ENDP),四位,由此可知一個USB設備有的端點數量最大爲16個。

5、幀號域(FRAM),11位,每一個幀都有一個特定的幀號,幀號域最大容量0x800,對於同步傳輸有重要意義(同步傳輸爲四種傳輸類型之一,請看下面)。

6、數據域(DATA):長度爲0~1023字節,在不同的傳輸類型中,數據域的長度各不相同,但必須爲整數個字節的長度

7、校驗域(CRC):對令牌包和數據包(對於包的分類請看下面)中非PID域進行校驗的一種方法,CRC校驗在通訊中應用很泛,是一種很好的校驗方法,至於具體的校驗方法這裏就不多說,請查閱相關資料,只須注意CRC碼的除法是模2運算,不同於10進制中的除法。

(二)包:由域構成的包有四種類型,分別是令牌包、數據包、握手包和特殊包,前面三種是重要的包,不同的包的域結構不同,介紹如下

1、令牌包:可分爲輸入包、輸出包、設置包和幀起始包(注意這裏的輸入包是用於設置輸入命令的,輸出包是用來設置輸出命令的,而不是放據數的)

其中輸入包、輸出包和設置包的格式都是一樣的:

SYNC+PID+ADDR+ENDP+CRC5(五位的校驗碼)  

(上面的縮寫解釋請看上面域的介紹,PID碼的具體定義請看問題五)

幀起始包的格式:

SYNC+PID+11位FRAM+CRC5(五位的校驗碼)

2、數據包:分爲DATA0包和DATA1包,當USB發送數據的時候,當一次發送的數據長度大於相應端點的容量時,就需要把數據包分爲好幾個包,分批發送,DATA0包和DATA1包交替發送,即如果第一個數據包是DATA0,那第二個數據包就是DATA1。但也有例外情況,在同步傳輸中(四類傳輸類型中之一),所有的數據包都是爲DATA0,格式如下:

SYNC+PID+0~1023字節+CRC16

3、握手包:結構最爲簡單的包,格式如下

SYNC+PID

(註上面每種包都有不同類型的,USB1.1共定義了十種包,具體請見問題五)

(三)事務:分別有IN事務、OUT事務和SETUP事務三大事務,每一種事務都由令牌包、數據包、握手包三個階段構成,這裏用階段的意思是因爲這些包的發送是有一定的時間先後順序的,事務的三個階段如下:

1、令牌包階段:啓動一個輸入、輸出或設置的事務

2、數據包階段:按輸入、輸出發送相應的數據

3、握手包階段:返回數據接收情況,在同步傳輸的IN和OUT事務中沒有這個階段,這是比較特殊的。

事務的三種類型如下(以下按三個階段來說明一個事務):

1、 IN事務:

令牌包階段——主機發送一個PID爲IN的輸入包給設備,通知設備要往主機發送數據;

數據包階段——設備根據情況會作出三種反應(要注意:數據包階段也不總是傳送數據的,根據傳輸情況還會提前進入握手包階段)

1) 設備端點正常,設備往入主機裏面發出數據包(DATA0與DATA1交替);

2) 設備正在忙,無法往主機發出數據包就發送NAK無效包,IN事務提前結束,到了下一個IN事務才繼續;

3) 相應設備端點被禁止,發送錯誤包STALL包,事務也就提前結束了,總線進入空閒狀態。

握手包階段——主機正確接收到數據之後就會向設備發送ACK包。

2、 OUT事務:

令牌包階段——主機發送一個PID爲OUT的輸出包給設備,通知設備要接收數據;

數據包階段——比較簡單,就是主機會設備送數據,DATA0與DATA1交替

握手包階段——設備根據情況會作出三種反應

1)設備端點接收正確,設備往入主機返回ACK,通知主機可以發送新的數據,如果數據包發生了CRC校驗錯誤,將不返回任何握手信息;

2) 設備正在忙,無法往主機發出數據包就發送NAK無效包,通知主機再次發送數據;

3) 相應設備端點被禁止,發送錯誤包STALL包,事務提前結束,總線直接進入空閒狀態。

3、SETUT事務:

令牌包階段——主機發送一個PID爲SETUP的輸出包給設備,通知設備要接收數據;

數據包階段——比較簡單,就是主機會設備送數據,注意,這裏只有一個固定爲8個字節的DATA0包,這8個字節的內容就是標準的USB設備請求命令(共有11條,具體請看問題七)

握手包階段——設備接收到主機的命令信息後,返回ACK,此後總線進入空閒狀態,並準備下一個傳輸(在SETUP事務後通常是一個IN或OUT事務構成的傳輸)

(四)傳輸:傳輸由OUT、IN、SETUP事務其中的事務構成,傳輸有四種類型,中斷傳輸、批量傳輸、同步傳輸、控制傳輸,其中中斷傳輸和批量轉輸的結構一樣,同步傳輸有最簡單的結構,而控制傳輸是最重要的也是最複雜的傳輸。

1、中斷傳輸:由OUT事務和IN事務構成,用於鍵盤、鼠標等HID設備的數據傳輸中

2、批量傳輸:由OUT事務和IN事務構成,用於大容量數據傳輸,沒有固定的傳輸速率,也不佔用帶寬,當總線忙時,USB會優先進行其他類型的數據傳輸,而暫時停止批量轉輸。

3、同步傳輸:由OUT事務和IN事務構成,有兩個特殊地方,第一,在同步傳輸的IN和OUT事務中是沒有返回包階段的;第二,在數據包階段所有的數據包都爲DATA0

4、控制傳輸:最重要的也是最複雜的傳輸,控制傳輸由三個階段構成(初始設置階段、可選數據階段、狀態信息步驟),每一個階段可以看成一個的傳輸,也就是說控制傳輸其實是由三個傳輸構成的,用來於USB設備初次加接到主機之後,主機通過控制傳輸來交換信息,設備地址和讀取設備的描述符,使得主機識別設備,並安裝相應的驅動程序,這是每一個USB開發者都要關心的問題。

1、初始設置步驟:就是一個由SET事務構成的傳輸

2、可選數據步驟:就是一個由IN或OUT事務構成的傳輸,這個步驟是可選的,要看初始設置步驟有沒有要求讀/寫數據(由SET事務的數據包階段發送的標準請求命令決定)

3、 狀態信息步驟:顧名思義,這個步驟就是要獲取狀態信息,由IN或OUT事務構成構成的傳輸,但是要注意這裏的IN和OUT事務和之前的INT和OUT事務有兩點不同:

1) 傳輸方向相反,通常IN表示設備往主機送數據,OUT表示主機往設備送數據;在這裏,IN表示主機往設備送數據,而OUT表示設備往主機送數據,這是爲了和可選數據步驟相結合;

2) 在這個步驟裏,數據包階段的數據包都是0長度的,即SYNC+PID+CRC16

除了以上兩點有區別外,其他的一樣,這裏就不多說

(思考:這些傳輸模式在實際***作中應如何通過什麼方式去設置?)

 



問題五:標識碼(PID)有哪些?

答案五:如同前面所說的標識碼由四位數據組成,因此可以表示十六種標識碼,在USB1.1規範裏面,只用了十種標識碼,USB2.0使用了十六種標識碼,標識碼的作用是用來說明包的屬性的,標識碼是和包聯繫在一起的,首先簡單介紹一下數據包的類型,數據包分爲令牌包、數據、握手包和特殊包四種(具體分類請看問題七),標識碼分別有以下十六種:

令牌包 :

0x01  輸出(OUT)啓動一個方向爲主機到設備的傳輸,幷包含了設備地址和標號

0x09  輸入 (IN) 啓動一個方向爲設備到主機的傳輸,幷包含了設備地址和標號

0x05  幀起始(SOF)表示一個幀的開始,並且包含了相應的幀號

0x0d  設置(SETUP)啓動一個控制傳輸,用於主機對設備的初始化

數據包 :

0x03  偶數據包(DATA0),

0x0b  奇數據包(DATA1)

握手包:

0x02  確認接收到無誤的數據包(ACK)

0x0a  無效,接收(發送)端正在忙而無法接收(發送)信息

0x0e  錯誤,端點被禁止或不支持控制管道請求

特殊包 0x0C  前導,用於啓動下行端口的低速設備的數據傳輸

 

 

問題六:USB主機是如何識別USB設備的?

答案六:當USB設備插上主機時,主機就通過一系列的動作來對設備進行枚舉配置(配置是屬於枚舉的一個態,態表示暫時的狀態),這這些態如下:

        1、接入態(Attached):設備接入主機後,主機通過檢測信號線上的電平變化來發現設備的接入;

        2、供電態(Powered):就是給設備供電,分爲設備接入時的默認供電值,配置階段後的供電值(按數據中要求的最大值,可通過編程設置)

        3、缺省態(Default):USB在被配置之前,通過缺省地址0與主機進行通信;

        4、地址態(Address):經過了配置,USB設備被複位後,就可以按主機分配給它的唯一地址來與主機通信,這種狀態就是地址態;

        5、配置態(Configured):通過各種標準的USB請求命令來獲取設備的各種信息,並對設備的某此信息進行改變或設置。

        6、掛起態(Suspended):總線供電設備在3ms內沒有總線***作,即USB總線處於空閒狀態的話,該設備就要自動進入掛起狀態,在進入掛起狀態後,總的電流功耗不超過280UA。

 

問題七:剛纔在答案四提到的標準的USB設備請求命令究竟是什麼?

答案七:標準的USB設備請求命令是用在控制傳輸中的“初始設置步驟”裏的數據包階段(即DATA0,由八個字節構成),請看回問答四的內容。標準USB設備請求命令共有11個,大小都是8個字節,具有相同的結構,由5個字段構成(字段是標準請求命令的數據部分),結構如下(括號中的數字表示字節數,首字母bm,b,w分別表示位圖、字節,雙字節):

bmRequestType(1)+bRequest(1)+wvalue(2)+wIndex(2)+wLength(2)

各字段的意義如下:

1、bmRequestType:D7D6D5D4D3D2D1D0

D7=0主機到設備

=1設備到主機;

D6D5=00標準請求命令

     =01 類請求命令

     =10用戶定義的命令    

=11保留值

D4D3D2D1D0=00000 接收者爲設備

            =00001 接收者爲設備

            =00010 接收者爲端點

            =00011 接收者爲其他接收者

            =其他  其他值保留

2、bRequest:請求命令代碼,在標準的USB命令中,每一個命令都定義了編號,編號的值就爲字段的值,編號與命令名稱如下(要注意這裏的命令代碼要與其他字段結合使用,可以說命令代碼是標準請求命令代碼的核心,正是因爲這些命令代碼而決定了11個USB標準請求命令):

0) 0  GET_STATUS:用來返回特定接收者的狀態

1) 1  CLEAR_FEATURE:用來清除或禁止接收者的某些特性

2) 3  SET_FEATURE:用來啓用或激活命令接收者的某些特性

3) 5  SET_ADDRESS:用來給設備分配地址

4) 6  GET_DEscriptOR:用於主機獲取設備的特定描述符

5) 7  SET_DEscriptOR:修改設備中有關的描述符,或者增加新的描述符

6) 8  GET_CONFIGURATION:用於主機獲取設備當前設備的配置值(注同上面的不同) 

7) 9  SET_CONFIGURATION:用於主機指示設備採用的要求的配置

8) 10  GET_INTERFACE:用於獲取當前某個接口描述符編號

9) 11  SET_INTERFACE:用於主機要求設備用某個描述符來描述接口

10) 12 SYNCH_FRAME:用於設備設置和報告一個端點的同步幀

以上的11個命令要說得明白真的有一匹布那麼長,請各位去看書吧,這裏就不多說了,控制傳輸是USB的重心,而這11個命令是控制傳輸的重心,所以這11個命令是重中之重,這個搞明白了,USB就算是入門了。

 

問題八:在標準的USB請求命令中,經常會看到描述符(Descriptor),這是什麼來的呢?

回答八:Descriptor即描述符,是一個完整的數據結構,可以通過C語言等編程實現,並存儲在USB設備中,用於描述一個USB設備的所有屬性,USB主機是通過一系列命令來要求設備發送這些信息的。它的作用就是通過如問答節中的命令***作來給主機傳遞信息,從而讓主機知道設備具有什麼功能、屬於哪一類設備、要佔用多少帶寬、使用哪類傳輸方式及數據量的大小,只有主機確定了這些信息之後,設備才能真正開始工作,所以描述符也是十分重要的部分,要好好掌握。標準的描述符有5種,USB爲這些描述符定義了編號:

1——設備描述符

2——配置描述符

3——字符描述符

4——接口描述符

5——端點描述符

上面的描述符之間有一定的關係,一個設備只有一個設備描述符,而一個設備描述符可以包含多個配置描述符,而一個配置描述符可以包含多個接口描述符,一個接口使用了幾個端點,就有幾個端點描述符。這間描述符是用一定的字段構成的,分別如下說明:

1、設備描述符

struct _DEVICE_DEscriptOR_STRUCT

{

 BYTE bLength;          //設備描述符的字節數大小,爲0x12

 BYTE bDescriptorType;  //描述符類型編號,爲0x01

 WORD bcdUSB;           //USB版本號

 BYTE bDeviceClass;  //USB分配的設備類代碼,0x01~0xfe爲標準設備類,0xff爲廠商自定義類型

                        //0x00不是在設備描述符中定義的,如HID

    BYTE bDeviceSubClass;   //usb分配的子類代碼,同上,值由USB規定和分配的

    BYTE bDeviceProtocl;    //USB分配的設備協議代碼,同上

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

    WORD idVendor;          //廠商編號

    WORD idProduct;         //產品編號

    WORD bcdDevice;         //設備出廠編號

    BYTE iManufacturer;     //描述廠商字符串的索引

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

    BYTE iSerialNumber;     //描述設備序列號字符串的索引

    BYTE bNumConfiguration; //可能的配置數量

   

}

2、配置描述符

struct _CONFIGURATION_DEscriptOR_STRUCT

{

 BYTE bLength;          //設備描述符的字節數大小,爲0x12

 BYTE bDescriptorType;  //描述符類型編號,爲0x01

 WORD wTotalLength;     //配置所返回的所有數量的大小

 BYTE bNumInterface;    //此配置所支持的接口數量

 BYTE bConfigurationVale;   //Set_Configuration命令需要的參數值

 BYTE iConfiguration;       //描述該配置的字符串的索引值

 BYTE bmAttribute;          //供電模式的選擇

 BYTE MaxPower;             //設備從總線提取的最大電流

}

3、字符描述符

struct _STRING_DEscriptOR_STRUCT

{

 BYTE bLength;          //設備描述符的字節數大小,爲0x12

 BYTE bDescriptorType;  //描述符類型編號,爲0x01

 BYTE SomeDescriptor[36];          //UNICODE編碼的字符串

}

4、接口描述符

struct _INTERFACE_DEscriptOR_STRUCT

{

 BYTE bLength;          //設備描述符的字節數大小,爲0x12

 BYTE bDescriptorType;  //描述符類型編號,爲0x01

 BYTE bInterfaceNunber; //接口的編號

 BYTE bAlternateSetting;//備用的接口描述符編號

 BYTE bNumEndpoints;    //該接口使用端點數,不包括端點0

 BYTE bInterfaceClass;  //接口類型

 BYTE bInterfaceSubClass;//接口子類型

 BYTE bInterfaceProtocol;//接口所遵循的協議

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

}

5、端點描述符

struct _ENDPOIN_DEscriptOR_STRUCT

{

 BYTE bLength;          //設備描述符的字節數大小,爲0x12

 BYTE bDescriptorType;  //描述符類型編號,爲0x01

 BYTE bEndpointAddress; //端點地址及輸入輸出屬性

 BYTE bmAttribute;      //端點的傳輸類型屬性

 WORD wMaxPacketSize;   //端點收、發的最大包的大小

 BYTE bInterval;        //主機查詢端點的時間間隔

}

 

 






USB枚舉實例轉載:

對2440的USB HOST進行初始化完畢(主要包括對符合OHCI規範的寄存器的初始化—總線復位、中斷使能、清除中斷標誌、電源管理、內存指針寄存器的初始化,各種數據結構的初始化等),等待USB設備的插入,當2440檢測到有設備插入,就要對設備進行枚舉了。那麼爲什麼要對設備進行枚舉呢?起始枚舉就相當於主機和設備建立連接的過程(接頭),Host向Device詢問一些東西,Device將自身的設備類型,如何進行通信報告給Host,這樣Host就知道怎麼着對Device進行操作了。

枚舉的過程實際上用到而且只用到了總線的“控制傳輸(Control Transfer)”的傳輸方式。這種傳輸方式通常用於配置/命令/狀態等情形,其中的設置操作setup和狀態操作status過程的數據包具有USB協議定義的數據結構,因此,控制傳輸只能通過消息管道進行。

一個完整的控制傳輸包括三個過程:1.建立連接    2.數據過程(可選)         3.狀態過程

建立連接的過程都是有Host發起,它開始於一個Setup令牌包,後面緊跟一個DATA0包。如果是控制輸入傳輸,數據過程則爲輸入數據,若是控制輸出傳輸,則數據過程是輸出數據。

數據過程的可選型是指設置過程需要指定數據長度,如果指定爲0,則沒有數據過程。狀態過程跟在數據過程之後,狀態過程恰好和數據過程的數據傳輸方向相反,因爲此階段主要是用來確認之前兩階段的所有數據都已經正確傳輸了。

       好了,下面就結合我的這個實例來看看枚舉的詳細過程:

       1.控制2440向U盤發送第一個Setup包,內容是80 06 00 01 00 00 08 00,其中最後的0008表示得到DEVICE_DCESCRIPTOR的前8個字節,因爲這個包的主要目的是要獲得USB Device中端點0的最大包的大小(第8個字節),所以只需要8個字節就可以了。USB Device返回的設備標識符爲12 01 10 01 00 00 00 40,下面我們需要對0x40記錄下來,將其放到Endpoint Descriptor數據結構的DWORD0的MPS(bit16~bit32)塊中去。

       2.接下來2440發送第二個Setup包,內容是00 05 01 00 00 00 00 00這一個次的作用是爲USB設備分配地址(相當於SD卡中的RCA)。如果USB Device接收並接受了此地址設置包,會返回一個長度爲0的數據包。Host接收到長度爲0的狀態包之後就會返回一個ACK給Device,Device再接收到這個ACK之後,就可以啓用新地址了。這樣Device就得到了一個唯一的設備地址,作爲主機通信的唯一表示。

3.發送第三個Setup包,內容是80 06 00 02 00 00 09 00,這次是爲了獲取配置描述符集合的大小,此位位於讀回數據的第三個字節。U盤返回的數據爲09 02 20 00 01 01 00 80 32,即描述符集合總大小爲0x20。

4.發送第四個Setup包,內容是80 06 00 02 00 00 09 00,和上次不同的僅僅是,這次要讀回來的數據是整個配置描述符區域。U盤返回來的數據是09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06 50 00 07 05 82 02 40 00 00 07 05 02 02 40 00 00。

這時候我們就可以知道該設備是什麼類型的設備,支持什麼樣的操作了。

上述這兩個過程也有的程序就是直接讀取0xff個字符大小,當然同樣可以達到讀回設備描述符集合的目的。

至此,我們已經得到了所需要的設備信息,之後就可以對設備進行配置了。

5.向設備發送第五個Setup包,數據爲00 09 01 00 00 00 00 00,USB Device返回一個長度爲0的數據包,表明數據正確接收。

至此,USB的枚舉過程就完成了。


發佈了25 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章