USB主機在檢測到USB設備插入后,就要對設備進行枚舉了。為什么要枚舉?枚舉就是從設備讀取各種描述符信息,這樣主機就可以根據這些信息來加載合適的驅動程序,從而知道設備是什么樣的設備,如何進行通信等。
枚舉的過程:
1、 USB主機檢測到USB設備插入之后,就會先對設備復位。USB設備在總線復位后其地址為0,這樣主機就可以通過地址0和那些剛剛插入的設備通信。USB主機往地址為0的設備的端點0發送獲取設備描述符的標准請求(這是一個控制傳輸的建立過程)。設備收到該請求后,會按照主機請求的參數,在數據過程將設備描述符返回給主機。主機在成功獲取到一個數據包的設備描述符並且確認沒有錯誤后,就會返回一個0長度的確認數據包(狀態過程)給設備,從而進入到接下來的設置地址階段。這里需要注意的是,第一次主機只會讀取一個數據包的設備描述符。標准的設備描述符有18字節,有些USB設備的端點0大小不足18字節(但至少具有8字節),在這種情況下,USB主機也是只發送一次數據輸入請求,多余的數據將不會再次請求。因此,如果當設備端點0大小不足18字節時,就需要注意到這個問題。也就是說在第一次獲取設備描述符時,只需要返回一次數據即可,不要再等主機繼續獲取剩余數據(如果還有),因為主機不會這么干的。當主機成功獲取到設備描述符的前8字節之后(USB協議規定端點0最大包長度至少有8字節),它就知道端點0的最大包長度了,因為端點0最大包長度剛好在設備描述符的第8字節處。
2、 主機對設備又一次復位。這是就進入到了設置地址階段。USB主機往地址為0的設備的端點0發出一個設置地址的請求(控制傳輸的建立過程),新的設備地址包含在建立過程的數據包中。具體的地址由USB主機負責管理,主機會分配一個唯一的地址給剛接入的設備。USB設備在收到這個建立過程之后,就直接進入到狀態過程,因為這個控制傳輸沒有數據過程。設備等待主機請求狀態返回(一個輸入令牌包),收到輸入令牌包后,設備就返回0長度的狀態數據包。如果主機確認該狀態包已經正確收到,就會發送應答包ACK給設備,設備在收到這個ACK之后,就要啟用新的設備地址了。這樣設備就分配到了一個唯一的設備地址,以后主機就要通過它來訪問該設備。
3、 主機再次獲取設備描述符。這次跟上次有點不一樣,首先是主機不再使用地址0來訪問設備,而是新的設備地址;另外,這次需要獲取全部的18字節的設備描述符。如果你的端點0最大包長度小於18字節,那就會有多次請求數據輸入(即發送多個IN令牌包)。
4、 主機獲取配置描述符。配置描述符總共為9字節。主機在獲取配置描述符后,根據配置描述符中所描述的配置集合長度,獲取配置集合。獲取配置描述符和獲取設備描述符集合的請求是差不多的,只是指定的長度不一樣。有些主機干脆不單獨獲取配置描述符,而是直接使用最大長度來獲取配置描述符集合,因為設備實際返回的數據可以少於指定的字節數。配置集合包括配置描述符、接口描述、類特殊描述符(如果有)、端點描述符等。接口描述符、類特殊描述符、端點描述符是不能單獨獲取的,必須跟配置描述符以一個集合的方式一並返回。
5、 如果有字符串描述符,還有獲取字符串描述符。另外,像HID設備還有報告描述符等,它們是單獨獲取的。