找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4286|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

USB枚舉和HID枚舉實例

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:85681 發(fā)表于 2015-7-15 02:03 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式


在說枚舉過程之前,先把一些必須了解的說明白
一.USB包結(jié)構(gòu)和分類
     包的共同特點是,都是以同步域開始,接著是PID,最后以EOP結(jié)束,而設(shè)備端則靠SEI(串行接口引擎,硬件上實現(xiàn))來進(jìn)行這些底層的處理,包括CRC的校驗之類的東東。
    8位的PID,PID0~PID3,用于表示包,高四位進(jìn)行取反,進(jìn)行校驗
    各種包的如下:
    令牌類:OUT,IN ,SOF,SETUP
    數(shù)據(jù)類:DATA0,DATA1,DATA2,MDATA
    握手類:ACK,NCK,STALL,NYET
    特殊類:PRE,ERR,SPLIT,PING
    令牌包用于啟動一次USB傳輸,這些IN,OUT都以主設(shè)備而言的
    SETUP建立控制傳輸過程
    令牌包的結(jié)構(gòu)為,
    同步域+PID+7位地址+4位端點號+5位CRC校驗+EOP
    數(shù)據(jù)包的結(jié)構(gòu)為,
    同步域+PID+字節(jié)0~字節(jié)N+CRC+EOP
    在數(shù)據(jù)包中,我們看到有DATA0和DATA1,這實際上形成了一種數(shù)據(jù)糾錯機制。
    在數(shù)據(jù)發(fā)送成功或者接收時,數(shù)據(jù)包類型切換,如果檢測到包類型沒有切換,說明剛剛的數(shù)據(jù)傳輸沒有發(fā)送成功。否則表示成功接收到數(shù)據(jù)了,雖然也有握手包來說明問題。
   握手包
   同步域+包標(biāo)識+EOP
二.事務(wù)
   不能簡單的通過包來進(jìn)行數(shù)據(jù)傳輸,所以由不同的包組織而成事務(wù),就是所謂的transcation
一個事務(wù)通常由三個不同類型的包組成,令牌包,數(shù)據(jù)包,握手包
令牌包啟動事務(wù),握手包返回信息,數(shù)據(jù)包傳輸數(shù)據(jù),方向由令牌包決定
我們知道USB中有4中傳輸類型,批量傳輸,等時傳輸,中斷傳輸和控制傳輸,控制傳輸一般用于總線的枚舉過程。
控制傳輸事務(wù)有三個過程,包括建立過程,數(shù)據(jù)過程,狀態(tài)過程
其余三種傳輸對應(yīng)一個事務(wù)
我們挑控制傳輸說明問題,其余就簡單了
   這里有個有趣的東西,setup只能使用DATA0,在數(shù)據(jù)傳輸過程中,一旦數(shù)據(jù)傳輸方向發(fā)生變化,就會認(rèn)為進(jìn)入了狀態(tài)過程,數(shù)據(jù)傳輸?shù)牡谝粋過程必須是DATA1包,每次傳輸正確之后是在DATA0和DATA1中切換,而狀態(tài)事務(wù)只能使用DATA1包。
USB設(shè)備的檢測機制,在前面已經(jīng)說過了,說個有意思的二次枚舉的應(yīng)用(因為重新上電之后就會有BUS的枚舉設(shè)備過程)當(dāng)設(shè)備插入之后,它先被識別成一個設(shè)備,該設(shè)備負(fù)責(zé)從主機上下載固件到設(shè)備的RAM內(nèi),然后設(shè)備將上拉電阻斷開(模擬拔下,設(shè)備未斷電,可以對口線進(jìn)行操作就可以了),接著重新連接上拉電阻,當(dāng)重新檢測到設(shè)備時,使用的是已經(jīng)下載的固件了,這就是不用燒錄器的好處,只要改固件程序。
三.USB設(shè)備枚舉過程
下面是USB設(shè)備枚舉的過程
1. 主機發(fā)起第一個控制傳輸(獲取設(shè)備描述):
(1)主機SETUP包(發(fā)往地址0端點0)、主機數(shù)據(jù)包(請求設(shè)備描述符)、設(shè)備握手包ACK。
設(shè)備產(chǎn)生端點0數(shù)據(jù)輸出中斷,固件程序要根據(jù)數(shù)據(jù)包中的主機要求做好準(zhǔn)備,這里是在端點0輸入緩沖區(qū)準(zhǔn)備好設(shè)備描述符。
(2)數(shù)據(jù)過程,主機先發(fā)一個IN令牌包、設(shè)備發(fā)一個數(shù)據(jù)包(這個數(shù)據(jù)已經(jīng)準(zhǔn)備好,SIE收到IN令牌后,直接送到總線上,用戶此時不干預(yù))、主機發(fā)ACK包。
此時SIE產(chǎn)生端點0數(shù)據(jù)輸入中斷,表明主機已經(jīng)取走了設(shè)備所準(zhǔn)備的數(shù)據(jù),用戶也可以在該中斷處理程序中作自己的處理。(如清理操作等)
此時,主機只接受一次數(shù)據(jù),最少8個字節(jié)。如果用戶數(shù)據(jù)沒有發(fā)完,又在控制端點輸入緩沖區(qū),準(zhǔn)備了數(shù)據(jù),主機也不理會。
(3)狀態(tài)過程:主機發(fā)OUT包(通知設(shè)備要輸出)、主機發(fā)0字節(jié)狀態(tài)數(shù)據(jù)包(這個是0字節(jié),表明自己收到設(shè)備描述符)、設(shè)備發(fā)握手ACK包。
此時設(shè)備不會產(chǎn)生端點0數(shù)據(jù)輸出中斷,此時沒有數(shù)據(jù)。
2、枚舉過程中,第二個來回:設(shè)置地址。
第一個來回成功以后,主機再次復(fù)位總線。進(jìn)入地址設(shè)置控制傳輸階段。
(1)主機SETUP包(發(fā)往地址0端點0)、主機數(shù)據(jù)包(請求設(shè)置地址)、設(shè)備握手包ACK。所以SETUP包后面都會跟一個表明主機SETUP目的的數(shù)據(jù)包,要么GET,要么SET。
設(shè)備產(chǎn)生端點0數(shù)據(jù)輸出中斷,固件程序要根據(jù)數(shù)據(jù)包中的主機要求做好準(zhǔn)備,這里是在根據(jù)主機發(fā)來的地址寫入自己的地址控制寄存器。
(2)數(shù)據(jù)過程,本次傳輸沒有數(shù)據(jù)。
(3)狀態(tài)過程:主機發(fā)IN包(通知設(shè)備要返回數(shù)據(jù))、設(shè)備發(fā)0字節(jié)狀態(tài)數(shù)據(jù)包(表明地址設(shè)置已經(jīng)成功)、主機發(fā)握手ACK包(地址設(shè)置已經(jīng)生效)。
此時設(shè)備不會產(chǎn)生端點0數(shù)據(jù)輸入中斷,此時沒有數(shù)據(jù)。
3、枚舉過程中,第三個來回:主機使用新地址獲取完整的設(shè)備描述符。
主機采用新地址發(fā)起第一個控制傳輸:
(1)主機SETUP包(發(fā)往新的地址端點0)、主機數(shù)據(jù)包(請求設(shè)備描述符)、設(shè)備握手包ACK。
設(shè)備產(chǎn)生端點0數(shù)據(jù)輸出中斷,固件程序要根據(jù)數(shù)據(jù)包中的主機要求做好準(zhǔn)備,這里是在端點0輸入緩沖區(qū)準(zhǔn)備好設(shè)備描述符。
(2)數(shù)據(jù)過程,主機先發(fā)一個IN令牌包、設(shè)備發(fā)一個數(shù)據(jù)包(這個數(shù)據(jù)已經(jīng)準(zhǔn)備好,SIE收到IN令牌后,直接送到總線上,用戶此時不干預(yù))、主機發(fā)ACK包。
此時SIE產(chǎn)生端點0數(shù)據(jù)輸入中斷,表明主機已經(jīng)取走了設(shè)備所準(zhǔn)備的數(shù)據(jù),用戶可以該中斷處理程序中要做如下處理:如果一次沒有將描述符送完,要再次將剩下的內(nèi)容填充端點0輸入緩沖區(qū)。
第二次數(shù)據(jù)傳輸:主機再發(fā)一個IN令牌包、設(shè)備發(fā)一個數(shù)據(jù)包、主機發(fā)ACK包。
此時SIE再次產(chǎn)生端點0數(shù)據(jù)輸入中斷,如果數(shù)據(jù)已經(jīng)發(fā)完了。這里就不處理了。進(jìn)入狀態(tài)過程。
(3)狀態(tài)過程:主機發(fā)OUT包(通知設(shè)備要輸出)、主機發(fā)0字節(jié)狀態(tài)數(shù)據(jù)包(表明自己收到設(shè)備描述符)、設(shè)備發(fā)握手ACK包。
接下來獲取配置描述符、配置集合、字符串描述符、報告描述符的過程差不多,這里就不再敘述了。
具體可以看下圖:







上面說的前兩個過程在BUS bound中是看不到的,上圖來自網(wǎng)絡(luò)
具體的上面已經(jīng)說得很清楚了
其中紅線的部分就是設(shè)置的地址,
set_address請求的結(jié)構(gòu)為
bmrequestType 0x00
SET_ADDRESS 0x05
wValue 設(shè)備地址(上面提到的0x0002,設(shè)備地址一般從地址0開始分配
wIndex 0x0000
wLength 0x0000
具體可以看文檔
四.USB HID設(shè)備(鼠標(biāo))的枚舉過程





以上的截圖是通過BUS BOUND得到的,不過沒有set_address前的枚舉過程而已。
(1)   取得設(shè)備描述符    get device descriptor
80 06 00 01 00 00 12 00
80         標(biāo)準(zhǔn)請求 數(shù)據(jù)傳輸方向 設(shè)備到主機
06         取得描述符請求Get Descriptor
0100     01表示的設(shè)備描述符 00描述符的索引
0000     讀取描述符時 字符串的語言ID
0012     18字節(jié) 需要返回取得的字節(jié)數(shù)
(2)   設(shè)備描述符
12 01 10 01 00 00 00 08 3a 09 10 25 00 01 01 02 00 01
12         18字節(jié) 設(shè)備描述符長度
01         設(shè)備描述符
0110     USB設(shè)備的USB協(xié)議為1.1
00          設(shè)備使用的類代碼 一般這里定義為0 協(xié)議在接口描述符中定義
00         子類代碼
00         設(shè)備使用的協(xié)議
08         端點0的最大包長
093a      廠商的ID
2510            產(chǎn)品ID              這兩個值可以在設(shè)備屬性中看到
0100      版本號1.0
01          描述廠商的字符串的索引值     
02          產(chǎn)品的字符串索引值
00          設(shè)備的序列號字符串索引值   0表示沒有序列號字符串
01          設(shè)備有多少種配置      
(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字節(jié)
01         該配置所支持的接口數(shù)01 鼠標(biāo)是一個接口,一個接口代表一個功能
01                配置值為01      當(dāng)set config時,如果找到與配置值匹配的,則設(shè)置為此配置
04          配置字符串的索引值
a0                 a0對應(yīng)的二進(jìn)制位10100000 D71是必須的,D61表示為設(shè)備自供電,為0表示總線供電 ,D51表示支持遠(yuǎn)程喚醒 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該接口使用的端點數(shù)   只是用一個端點(中斷端點)不包括0端點
03 該接口所使用的類 USB鼠標(biāo)為HID類,編碼03
01 該接口所使用的子類01 這個子類支持BIOS引導(dǎo)啟動的子類
02 協(xié)議 01為鍵盤 02 為鼠標(biāo)
00 接口所使用的字符串索引值00 為沒有
類描述符(HID類)
09 21 11 01 00 01 22 3e 00
09 類描述長度
21 HID描述符
0111 使用的HID協(xié)議1.11
00  設(shè)備適用的國家
01 下級描述符的數(shù)量 至少為1,報告描述符或者物理描述符
22  下級描述符的類型 0x22報告描述符 0x23物理描述符
003e 下級描述符的長度 當(dāng)有多個下級描述符時,上述兩值交替下去
端點描述符
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~D20
0004 支持最大的包長度 最大長度為4 對于高速設(shè)備這里有新的解釋
0a    表示端點查詢的時間 對于中斷端點 表示查詢的幀間隔數(shù)
7)設(shè)置配置
00 09 01 00 00 00 00 00
00 設(shè)置
09 設(shè)置配置
0001 配置的值為1,這里與上面配置1相匹配,選中該配置
0x0000 wIndex
0x0000 wLength
(8) set IDLE請求
這個請求要求設(shè)備在沒有新的事件發(fā)生時,不要從中斷端點中返回數(shù)據(jù)。
HID中類請求有set_idle ,get_idle,get_report,set_report HID鼠標(biāo)可以不用理會
(9)get descriptor
這里取的是接口描述符
81的后五位D4~D0表示請求的接收者
0 設(shè)備
1 接口
2 端點
3 其他
4~31 保留
81 06 00 22 00 00 7e 00
22 請求的描述符為HID的報告描述符 0x23為物理描述符
007e 請求的報告描述符長度(不懂為啥是這個,需要看主設(shè)備驅(qū)動和文檔)
(10)報告描述符
HID中有短條目和長條目之分
一般使用短條目 包括1字節(jié)的前綴和可選的數(shù)據(jù)字節(jié)組成
一般是加1字節(jié) 可選字節(jié)為0,1,2,4字節(jié)
前綴的1字節(jié)的結(jié)構(gòu)為
D7~D4 bTag      條目功能
D3~D2 bType    條目類型 0 主條目 1為全局條目 2為局部條目 3reserved
D1~D0 bSize      條目后面所跟數(shù)據(jù)的字節(jié)數(shù)
00 0字節(jié) 01 1字節(jié) 10 2字節(jié) 11 4字節(jié)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表