USB枚舉和HID枚舉實例(6)

在說枚舉過程之前,先把一些必須瞭解的說明白

一.USB包結構和分類

     包的共同特點是,都是以同步域開始,接着是PID,最後以EOP結束,而設備端則靠SEI(串行接口引擎,硬件上實現)來進行這些底層的處理,包括CRC的校驗之類的東東。

    8位的PID,PID0~PID3,用於表示包,高四位進行取反,進行校驗

    各種包的如下:

    令牌類:OUT,IN ,SOF,SETUP

    數據類:DATA0,DATA1,DATA2,MDATA

    握手類:ACK,NCK,STALL,NYET

    特殊類:PRE,ERR,SPLIT,PING

    令牌包用於啓動一次USB傳輸,這些IN,OUT都以主設備而言的

    SETUP建立控制傳輸過程

    令牌包的結構爲,

    同步域+PID+7位地址+4位端點號+5位CRC校驗+EOP

    數據包的結構爲,

    同步域+PID+字節0~字節N+CRC+EOP

    在數據包中,我們看到有DATA0和DATA1,這實際上形成了一種數據糾錯機制。

    在數據發送成功或者接收時,數據包類型切換,如果檢測到包類型沒有切換,說明剛剛的數據傳輸沒有發送成功。否則表示成功接收到數據了,雖然也有握手包來說明問題。

   握手包

   同步域+包標識+EOP

 

二.事務

   不能簡單的通過包來進行數據傳輸,所以由不同的包組織而成事務,就是所謂的transcation

一個事務通常由三個不同類型的包組成,令牌包,數據包,握手包

令牌包啓動事務,握手包返回信息,數據包傳輸數據,方向由令牌包決定

我們知道USB中有4中傳輸類型,批量傳輸,等時傳輸,中斷傳輸和控制傳輸,控制傳輸一般用於總線的枚舉過程。

控制傳輸事務有三個過程,包括建立過程,數據過程,狀態過程

其餘三種傳輸對應一個事務

我們挑控制傳輸說明問題,其餘就簡單了

   這裏有個有趣的東西,setup只能使用DATA0,在數據傳輸過程中,一旦數據傳輸方向發生變化,就會認爲進入了狀態過程,數據傳輸的第一個過程必須是DATA1包,每次傳輸正確之後是在DATA0和DATA1中切換,而狀態事務只能使用DATA1包。

USB設備的檢測機制,在前面已經說過了,說個有意思的二次枚舉的應用(因爲重新上電之後就會有BUS的枚舉設備過程)當設備插入之後,它先被識別成一個設備,該設備負責從主機上下載固件到設備的RAM內,然後設備將上拉電阻斷開(模擬拔下,設備未斷電,可以對口線進行操作就可以了),接着重新連接上拉電阻,當重新檢測到設備時,使用的是已經下載的固件了,這就是不用燒錄器的好處,只要改固件程序。

 

三.USB設備枚舉過程

下面是USB設備枚舉的過程

1. 主機發起第一個控制傳輸(獲取設備描述):

(1)主機SETUP包(發往地址0端點0)、主機數據包(請求設備描述符)、設備握手包ACK。

設備產生端點0數據輸出中斷,固件程序要根據數據包中的主機要求做好準備,這裏是在端點0輸入緩衝區準備好設備描述符。

(2)數據過程,主機先發一個IN令牌包、設備發一個數據包(這個數據已經準備好,SIE收到IN令牌後,直接送到總線上,用戶此時不干預)、主機發ACK包。

此時SIE產生端點0數據輸入中斷,表明主機已經取走了設備所準備的數據,用戶也可以在該中斷處理程序中作自己的處理。(如清理操作等)

此時,主機只接受一次數據,最少8個字節。如果用戶數據沒有發完,又在控制端點輸入緩衝區,準備了數據,主機也不理會。

(3)狀態過程:主機發OUT包(通知設備要輸出)、主機發0字節狀態數據包(這個是0字節,表明自己收到設備描述符)、設備發握手ACK包。

此時設備不會產生端點0數據輸出中斷,此時沒有數據。

 

2、枚舉過程中,第二個來回:設置地址。

第一個來回成功以後,主機再次復位總線。進入地址設置控制傳輸階段。

(1)主機SETUP包(發往地址0端點0)、主機數據包(請求設置地址)、設備握手包ACK。所以SETUP包後面都會跟一個表明主機SETUP目的的數據包,要麼GET,要麼SET。

設備產生端點0數據輸出中斷,固件程序要根據數據包中的主機要求做好準備,這裏是在根據主機發來的地址寫入自己的地址控制寄存器。

(2)數據過程,本次傳輸沒有數據。

(3)狀態過程:主機發IN包(通知設備要返回數據)、設備發0字節狀態數據包(表明地址設置已經成功)、主機發握手ACK包(地址設置已經生效)。

此時設備不會產生端點0數據輸入中斷,此時沒有數據。

 

3、枚舉過程中,第三個來回:主機使用新地址獲取完整的設備描述符。

主機採用新地址發起第一個控制傳輸:

(1)主機SETUP包(發往新的地址端點0)、主機數據包(請求設備描述符)、設備握手包ACK。

設備產生端點0數據輸出中斷,固件程序要根據數據包中的主機要求做好準備,這裏是在端點0輸入緩衝區準備好設備描述符。

(2)數據過程,主機先發一個IN令牌包、設備發一個數據包(這個數據已經準備好,SIE收到IN令牌後,直接送到總線上,用戶此時不干預)、主機發ACK包。

此時SIE產生端點0數據輸入中斷,表明主機已經取走了設備所準備的數據,用戶可以該中斷處理程序中要做如下處理:如果一次沒有將描述符送完,要再次將剩下的內容填充端點0輸入緩衝區。

第二次數據傳輸:主機再發一個IN令牌包、設備發一個數據包、主機發ACK包。

此時SIE再次產生端點0數據輸入中斷,如果數據已經發完了。這裏就不處理了。進入狀態過程。

(3)狀態過程:主機發OUT包(通知設備要輸出)、主機發0字節狀態數據包(表明自己收到設備描述符)、設備發握手ACK包。

接下來獲取配置描述符、配置集合、字符串描述符、報告描述符的過程差不多,這裏就不再敘述了。

具體可以看下圖:

 

上面說的前兩個過程在BUS bound中是看不到的,上圖來自網絡

具體的上面已經說得很清楚了

其中紅線的部分就是設置的地址,

 

set_address請求的結構爲

bmrequestType 0x00

SET_ADDRESS 0x05

wValue 設備地址(上面提到的0x0002,設備地址一般從地址0開始分配)

wIndex 0x0000

wLength 0x0000

具體可以看文檔

四.USB HID設備(鼠標)的枚舉過程

以上的截圖是通過BUS BOUND得到的,不過沒有set_address前的枚舉過程而已。

(1)   取得設備描述符    get device descriptor

80 06 00 01 00 00 12 00

80         標準請求數據傳輸方向設備到主機

06         取得描述符請求Get Descriptor

0100     01表示的設備描述符 00描述符的索引

0000     讀取描述符時字符串的語言ID號

0012     18字節需要返回取得的字節數

(2)   設備描述符

12 01 10 01 00 00 00 08 3a 09 10 25 00 01 01 02 00 01

12         18字節設備描述符長度

01         設備描述符

0110     USB設備的USB協議爲1.1

00          設備使用的類代碼一般這裏定義爲0 協議在接口描述符中定義

00         子類代碼

00         設備使用的協議

08         端點0的最大包長

093a      廠商的ID

2510            產品ID              這兩個值可以在設備屬性中看到

0100      版本號1.0

01          描述廠商的字符串的索引值    

02          產品的字符串索引值

00          設備的序列號字符串索引值   爲0表示沒有序列號字符串

01          設備有多少種配置      

(3)   取得配置描述符 Get Descriptor

80 06 00 02 00 00 09 00

這裏取得描述符(1)類似

02 表示取得配置描述符

00 09 希望取得的配置描述符長度

(4)   配置描述符

09 02 22 00 01 01 04 a0 32

09         length

02         configuration descriptor

0022     配置描述符總長度34字節

01         該配置所支持的接口數01 鼠標是一個接口,一個接口代表一個功能

01                配置值爲01      當set config時,如果找到與配置值匹配的,則設置爲此配置

04          配置字符串的索引值

a0                 a0對應的二進制位10100000 D7爲1是必須的,D6爲1表示爲設備自供電,爲0表示總線供電,D5爲1表示支持遠程喚醒爲0表示不支持其餘位爲0

32                    表示需要從總線獲得的最大電流量 2mA*0x32=100mA

(5)     再次取得配置描述符(具體)

80 06 00 02 00 00 22 00

這裏的0x0022就是在上一個描述中得到的

(6)     具體的配置描述符

包括配置描述符,接口描述符,類描述符(如果有的話),端點描述符

09 02 22 00 01 01 04 a0 32 09 04 00 00 01 03 01 02 00 09 21 11 01 00 01 22 3e 00 07 05 81 03 04 00 0a

 

其中配置描述符

09 02 22 00 01 01 04 a0 32

 

接口描述符

09 04 00 00 01 03 01 02 00

09 接口描述符長度

04 接口描述符

00 接口的編號編號爲0(如果有很多接口這裏會逐個顯示)

00 接口的備用編號爲0

01該接口使用的端點數   只是用一個端點(中斷端點)不包括0端點

03 該接口所使用的類 USB鼠標爲HID類,編碼03

01 該接口所使用的子類01 這個子類支持BIOS引導啓動的子類

02 協議 01爲鍵盤 02 爲鼠標

00 接口所使用的字符串索引值00 爲沒有

 

類描述符(HID類)

09 21 11 01 00 01 22 3e 00

09 類描述長度

21 HID描述符

0111 使用的HID協議1.11

00  設備適用的國家

01 下級描述符的數量至少爲1,報告描述符或者物理描述符

22  下級描述符的類型 0x22報告描述符 0x23物理描述符

003e 下級描述符的長度當有多個下級描述符時,上述兩值交替下去

 

端點描述符

07  05 81 03 04 00 0a

07   端點描述符的長度

05  端點描述符類型

81  端點的地址10000001 D7表示傳輸方向 1爲輸入 D6~D4 reserved D3~D0爲端點號端點號爲01

03    端點的屬性 D1~D0表示端點的傳輸類型 11表示爲中斷傳輸 10批量傳輸 01等時傳輸 00控制傳輸非等時傳輸D7~D2爲0

0004 支持最大的包長度最大長度爲4 對於高速設備這裏有新的解釋

0a    表示端點查詢的時間對於中斷端點表示查詢的幀間隔數

(7)設置配置

00 09 01 00 00 00 00 00

00 設置

09 設置配置

0001 配置的值爲1,這裏與上面配置1相匹配,選中該配置

0x0000 wIndex

0x0000 wLength

(8) set IDLE請求

這個請求要求設備在沒有新的事件發生時,不要從中斷端點中返回數據。

HID中類請求有set_idle ,get_idle,get_report,set_report HID鼠標可以不用理會

(9)get descriptor

這裏取的是接口描述符

81的後五位D4~D0表示請求的接收者

0 設備

1 接口

2 端點

3 其他

4~31 保留

81 06 00 22 00 00 7e 00

22 請求的描述符爲HID的報告描述符 0x23爲物理描述符

007e 請求的報告描述符長度(不懂爲啥是這個,需要看主設備驅動和文檔)

(10)報告描述符

HID中有短條目和長條目之分

一般使用短條目包括1字節的前綴和可選的數據字節組成

一般是加1字節可選字節爲0,1,2,4字節

前綴的1字節的結構爲

D7~D4 bTag      條目功能

D3~D2 bType    條目類型 0 主條目 1爲全局條目 2爲局部條目 3reserved

D1~D0 bSize      條目後面所跟數據的字節數

00 0字節 01 1字節 10 2字節 11 4字節

       具體的報告描述符帶看HID文檔,這裏就不多說了。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章