在說枚舉過程之前,先把一些必須了解的說明白 一.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字節
|