1. 程式人生 > >龍芯軟件開發(32)-- USB協議深入分析

龍芯軟件開發(32)-- USB協議深入分析

喚醒 end 操作系統 取字符 軟件 發送 ice sta request

現在非常流行USB設備,時時刻刻都在我們身邊,比如使用U盤,使用MP3,使用手機,都需要與PC的USB通訊。通過USB的接口,使用我們的生活非常方便了,想什麽時候聽歌,就可以插入MP3到PC機那裏,然後再從PC上下載MP3。這個過程在用戶看來是非常的簡單,不需要安裝驅動程序,不需要斷掉PC機的電源。真正體現“科技以人為本”的思想。使用這麽方便的U盤或者MP3,那麽我們又需要去問個為什麽了,為什麽會這麽方便呢?往往方便的背後,就意味著需要工程師做大量的工作,才會讓大家使用USB這麽方便。下面就來詳細地分析USB的協議。 USB通訊是非常復雜的,剛剛協議定義就厚厚的一本,要完全地去看完,並且理解它,是很費時間的事情。希望本文可以提供給你一個非常好的指導,讓你深入地理解USB的協議。USB的協議是主從協議,在所有通訊裏,只有一個主控器,其它都是從設備。最多能接127個從設備,因為協議裏只保留了7bit作為設備地址。所有的USB數據交流都是由主控器發起,其它從設備進行響應。現在就以WINDOWS上的USB通訊來學習一下USB的通訊協議,後面所有提到的數據,都是WINDOWS上的USB驅動程序發下來的數據。 為了把所有通訊數據都顯示出來,我找到了一個USB的ARM開發板,通過這個開發板,就可以把主控器所有數據打印出來,並作相應的分析。同時,使用這個開發板,也可以用來調試龍芯的主控器驅動程序的調試。 當USB的開發板加電時,就會先初始化USB的連接,但沒有插入PC的連接線,這時開發板就會從串口輸出下面的字符: USB Suspend USB Resume 從上面看到,從設備的USB一直不斷地掛起和喚醒,直到插入PC的連接線。當插入連接線到PC時,就會收到主控器發來的信息。下面的數據,就是開發板與USB主控器交流的數據。 1.
收到主控器的獲取設備描述符配置包。 Setup m=0,n=0,val=37 80 06 00 01 00 00 40 00 這是主控器發來第一個配置包數據。由於主控器不知道USB設備設備描述符有多長,所以包的最後裏的長度是0x0040,也就是64個字節長度。 REQUEST_STANDARD=0x6 USB_DEVICE_DESCRIPTOR_TYPE(0) 根據USB的協議,分析上面的數據,就知道它是獲取設備描述符。為了實現即插即用,就需要對插入來的設備進行獲取描述信息,才知道這個USB的設備是什麽樣的設備,是U盤,還是HID的鍵盤。因此,USB設備就返回下面的數據給主控器: USB_DataInStage,cnt=18,EP0Data.Count=18 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01
這條數據,就是USB的設備描述符,描述了這個設備使用什麽USB的協議版本,這裏是1.1的版本,還有廠家標識、產品標識,以及廠家、產品和序列號等字符串的偏移地址。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 USB_EVT_OUT 通過設備描述符,就可以讓主控器知道這個設備是使用什麽版本的USB協議,是高速的設備,還是低速的設備,是誰產生的,是什麽產品,然後操作系統就可以通過這些信息去找到相應的驅動程序,如果操作系統沒有找到相應的驅動程序,就會提示用戶插入光盤,或者其它方來安裝相應的驅動程序。 2.
收到主控器的設置設備地址配置包。 Setup m=0,n=0,val=37 00 05 01 00 00 00 00 00 這條數據,根據USB的協議,就可以知道它是設置USB設備的地址配置包。它的作用,就是分配USB設備的地址,由於USB總線上可以有127個設備,那麽每個設備都需要分配一個唯一的地址才通訊,這跟網卡的MAC地址的作用是一樣的。其實,就像分配門牌號,讓大家看到那個門牌就知道什麽房了。 從下面的數據分析來看,是分配地址為1. REQUEST_STANDARD=0x5 USB_DeviceAddress=129 USB_EVT_IN,USB_SetAddress(1) 3. 收到主控器的獲取設備描述符配置包。 Setup m=0,n=0,val=37 80 06 00 01 00 00 12 00 再次收到獲取設備描述符的配置包,由於第一次不知道設備描述符有多大,因而總是發送一個最大數據的包,就是64個字節大,現在知道描述符的大小為0x0012個大小了,就把它發送下來了。所以USB設備再次回應設備描述符就可以了。 REQUEST_STANDARD=0x6 USB_DEVICE_DESCRIPTOR_TYPE(1) USB_DataInStage,cnt=18,EP0Data.Count=18 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 在這裏再次回應設備描述符。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 4. 收到配置描述符包 Setup m=0,n=0,val=45 80 06 00 02 00 00 09 00 根據USB協議可以知道,這是一個配置描述符的包,也就是讓USB設備發送本設備有多少個配置方式給主控器。由於USB的設備是多種多樣,滿足不同的用戶需要的。比如鼠標和鍵盤,就是不同的設備了。還有MP3播放器,還有各種數碼相機等等,都是不一樣的設備了。就可以通過下面的方式來說明這個配置有多少種方式,主要是通訊的方式。 REQUEST_STANDARD=0x6 USB_CONFIGURATION_DESCRIPTOR_TYPE(2)(Offset=0x0) USB_DataInStage,cnt=9,EP0Data.Count=9 09 02 22 00 01 01 00 01 32 這裏就是USB設備返回配置描述符給主控器的,它主要說明了這個設備有多少個配置,比如定義端點的類型,端點的傳送方式,還有這個設備使用USB總線的電源多少。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 5. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 00 03 00 00 FF 00 這裏收到獲取字符串描述符。由於在設備描述符裏已經說明字符串描述符在那裏,主要是偏移地址,比如04就是廠家的描述符。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(3)(Offset=0x0) USB_DataInStage,cnt=4,EP0Data.Count=4 04 03 09 04 這裏返回偏移地址為0的字符串描述,其實那裏是保存字符串描述符的語言描述標識,這裏英語的標識,0X0409。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 6. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 4A 03 09 04 FF 00 這時收到獲取字符串描述符,根據偏移地址,就知道它是想返回0x4A的字符串,也就是字符串描述符裏的偏移地址。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(4)(Offset=0x4A) USB_DataInStage,cnt=36,EP0Data.Count=36 24 03 43 00 41 00 49 00 32 00 30 00 30 00 37 00 30 00 33 00 32 00 35 00 20 00 31 00 2E 00 30 00 2E 00 30 00 USB設備返回0x4A的字符串給PC。這裏是我放置的字符串: CAI20070325 1.0.0 它作為產品的序列號。由於采用UNICODE編碼,所有高位字節全是0。由於USB協議是使用小端格式來發送數據,所以都低位在前,高位在後。這樣在PC那裏就可以看到USB設備的產品序列號了。又前進了一步。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 7. 收到第二個配置描述符包 Setup m=0,n=0,val=45 80 06 00 02 00 00 FF 00 這裏收到是第二個配置描述符包,與第一個的區別是返回長度不同。 第一個配置包返回的長度是9個字節,而這裏的長度是255。 REQUEST_STANDARD=0x6 USB_CONFIGURATION_DESCRIPTOR_TYPE(5)(Offset=0x0) USB_DataInStage,cnt=34,EP0Data.Count=34 09 02 22 00 01 01 00 01 32 09 04 00 00 01 03 00 00 6E 09 21 00 01 00 01 22 24 00 07 05 81 03 40 00 20 在這裏返回全部配置描述給PC,讓PC知道USB設備所有的配置。在這裏包括設備配置,接口配置,端點配置,還有設備特別配置信息。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 8. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 00 03 00 00 FF 00 收到PC的字符串描述符,後面設備就返回。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(6)(Offset=0x0) USB_DataInStage,cnt=4,EP0Data.Count=4 04 03 09 04 返回設備描述符的語言定義。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 9. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 2C 03 09 04 FF 00 收到PC需要產品字符串。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(7)(Offset=0x2C) USB_DataInStage,cnt=30,EP0Data.Count=30 1E 03 42 00 69 00 67 00 53 00 6C 00 6F 00 70 00 65 00 33 00 44 00 20 00 48 00 49 00 44 00 這裏USB設備返回產品字符串給PC了。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 10. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 00 03 00 00 FF 00 這裏收到字符串描述符。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(8)(Offset=0x0) USB_DataInStage,cnt=4,EP0Data.Count=4 04 03 09 04 返回語言標識。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 11. 收到字符串描述符包 Setup m=0,n=0,val=45 80 06 2C 03 09 04 FF 00 收到PC需要產品字符串。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(9)(Offset=0x2C) USB_DataInStage,cnt=30,EP0Data.Count=30 1E 03 42 00 69 00 67 00 53 00 6C 00 6F 00 70 00 65 00 33 00 44 00 20 00 48 00 49 00 44 00 這裏USB設備返回產品字符串給PC了。 USB_EVT_IN,USB_DataInStage USB_DataInStage,cnt=0,EP0Data.Count=0 12. 收到字符串描述符包 USB_EVT_OUT Setup m=0,n=0,val=37 80 06 00 03 00 00 FF 00 這裏收到字符串描述符。 REQUEST_STANDARD=0x6 USB_STRING_DESCRIPTOR_TYPE(10)(Offset=0x0) USB_DataInStage,cnt=4,EP0Data.Count=4

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

龍芯軟件開發(32)-- USB協議深入分析