玩轉USB HID系列:USB先導知識簡明

先記住幾個重要知識

USB device 不能主動發送信息給USB host

usb與串口有所不同,它是主機端驅動的方式,設備(device)必須在主機(host)詢問後才能返回數據。
device想要定時定量數據到主機就需要主機不斷查詢,只要主機詢問的足夠快,就相當於數據可以實時傳輸了。

端點(End Point)的IN 和OUT是相對誰而言的?

注意!無論是device還是host,IN和OUT是都相對host來說的,IN就是設備發主機收,OUT反之。
也就是說:
device從OUT端點讀取端點數據,向IN端點寫入數據
host從IN端點讀取端點數據,向OUT端點寫入數據

USB 2.0的速度

過去我們稱USB分USB2.0,USB1.1,USB1.0
現在這種說法取消了,都劃爲USB2.0中:
USB2.0 High Speed <–>過去所說的USB2.0
USB2.0 Full Speed <–>也就是USB1.1
USB2.0 Low Speed <–>也就是USB1.0

這裏面也不是隻由HS,FS和LS決定,還由傳輸方式決定
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
(對這個表格有些存疑,待考正)

開始閱讀

導讀:usb(Universal Serial Bus) 串行總線協議是一種常見的計算機協議,幾乎所有的個人電腦都配有 usb 接口,像優盤和手機也多是 usb 接口,還有一些打印機,鼠標和鍵盤等也是使用 usb 接口。usb 協議支持插拔,即插即用非常方便。這篇文章不是詳解 usb 協議,只是對一些 usb 協議的知識點進行簡單概括。在此推薦基本非常不錯的 usb 學習書籍《圈圈教你玩USB》的第二版,如果真的要精通 usb 協議的話,還是去閱讀 usb 協議的規範。

usb 協議從原來的 1.0 發展到現在的 3.x,速度從1.5Mb/s 到480Mb/s再到 10Gb/s ,發生了很大的變化。usb 1.0 顯然已經無法滿足現在的需求,USB 3.0 推廣了也有七八年了,現在新買的電腦上都會有 USB 3.0 接口,但是也沒全面替代 USB 2.0。USB 3.0 顯著的一個特徵就是接口是藍色的(找一個 USB 3.0 的優盤看看),並且裏面除了原來的 4根線 ,又多了幾根(畢竟更快的傳輸速度)。由於手中的 開發板 上配置的 是 USB 2.0的接口,所以還是以 USB 2.0來總結,熟悉了 USB 2.0 再看 USB3.0 也會容易很多。
一、usb 接口類型

在這裏插入圖片描述

從上面圖片來看,usb 的接口類型衆多,像主機端,主要用 USB A-Type 和 USB B-Type (看看電腦端USB接口),設備端常見的 USB C-Type 和 Micro-USB B (看看自己手機是不是其中一種)。根據不同的設備選擇不同的類型接口,如手機上放 USB A-Type 顯然不合適。

USB 2.0 接口包含了四根線,5V電源線、差分數據線D-、差分數據線D+和地線。在 USB OTG中多一根身份識別線。其中差分線D+和D-接15k的下拉電阻到地,當沒有插入設備的時候,D- 和 D+爲低電平。而設備端的D+或者D-接1.5k的上拉電阻到3.3V電源,這樣設備插入的時候,1.5K和15k電阻分壓,得到3V左右的電壓,爲高電平,會被hub檢測到,也就檢測到設備插入。1.5k電阻接在D+還是D-上,由設備的速度來決定。
在這裏插入圖片描述
二、USB 控制器

USB控制器有以下幾種規格:OHCI(Open Host Controller Interface) 、 UHCI(Universal HostController Interface) 、 EHCI(Enhanced Host Controller Interface) 和xHCI(eXtensible Host Controller Interface)。

OHCI:不僅僅是usb用的主控制器接口標準。主要是遵循csr (configuration space register)標準。是其他廠商在設計usb host controller時遵循的標準,如via, nec, ali, 包括nvidia等等。

UHCI: 由intel制定的usb 1.1主控制器(host controller)的硬件實例

EHCI: USB 2.0的主控制器標準接口,兼容 OHCI 和 UHCI。

xHCI:USB 3.0 的控制器標準,兼容 USB 2.0 及其以下的設備。

從上面看出,USB 的兼容性很好,出了新協議仍不忘兼容舊協議。

三、USB 拓撲結構

USB 像 I2c 一樣,是主從結構,所有的通信只能由主機發起。下面是 USB 的拓撲結構(圖片來自百度圖片)。
在這裏插入圖片描述

USB控制器下接根集線器(root hub),根集線器下面再接集線器或者設備,集線器下面還可以接集線器,所以很容易看出來USB通過集線器來拓展口的數量,當然不可以無限制的接集線器,USB2.0要求最多爲6層。同事USB的設備地址爲7位,不能超過127個設備(0地址是給剛接入未初始化設備使用)。

四、USB的 device、 congfig、 interface、 endpoint

USB中包含device(設備)、config(配置)、interface(接口)和endpoint(端點)。一個設備下面可以有多個配置,每個配置代表某種功能,同一時刻只有有一個配置生效。

一個配置下可以有多個接口,接口就是端點的集合。而一個接口下面可以有多個端點,USB通信通信的基本形式,主機通信的目標就是端點。
在這裏插入圖片描述

五、USB通信的幾種方式

USB 像 I2C 一樣採用主從的通信方式,所有的通信必須由主機發起。雖然 USB 傳輸數據的也只有兩根線,可通信方式可比I2C複雜的多。想想電腦上用的 USB 設備,像 優盤、攝像頭、鍵盤鼠標等等各種各樣的設備,各有不同的特點,像優盤需要進行大量數據傳輸,並且不能出錯;攝像頭數據量也不小,並且是實時傳輸,可能夠允許錯包(幾個錯包不至於畫面沒法看吧);而鼠標鍵盤數據量很小,但要求及時相應,要不然挪動鼠標的時候一卡一卡的誰受得了?所有 USB 協議要有多種通信方式來滿足不同的需求。

USB 有四種傳輸方式:

批量傳輸:

批量傳輸用在那種需要大量傳輸數據,但對實時性要求不高的情況下。如優盤,拷貝數據的時候需要大量數據傳輸,但對時間上並沒有特別嚴格的要求,通常多幾秒鐘也不是什麼問題,但是不允許有錯誤,一個錯誤包就可能導致整個文件就廢了,顯然是不行的。如果檢測到校驗錯誤的包,會涉及到重傳。

中斷傳輸:

中斷傳輸中的中斷是一個很容易誤解的詞彙,尤其是想到鼠標鍵盤等 USB設備,是不是有數據上報的時候給主機觸發一箇中斷?不是說 USB 所有的傳說操作只能由主機發起嗎?這裏的中斷並不是指硬件上那種中斷機制,而是 USB 主機按照指定的時間不斷的查詢 設備 是否有數據傳輸。具體以多少時間來查詢,根據設備要求而定。

同步傳輸:

看名字也是要保證信息傳輸的同步性,比如攝像頭,需要實時傳輸數據。但同步傳輸也有個特點,雖然要求實時性,但不要求百分之百的包正確,畢竟錯了幾個包並不怎麼影響視頻質量,即使檢測到錯包也不需要重傳。假想一下,攝像頭的數據流實施的在傳輸,突然發現一個錯包,然後去重傳,可後面的數據仍然源源不斷的傳輸,這個時候你重傳了一個包,原本在它後面的數據都已經傳輸過去了,你重傳它有什麼用呢,錯了就錯了吧。

控制傳輸:

前面三種都是要 傳輸數據的,一個 USB 控制器下面掛接那麼多的 設備,究竟怎麼直接傳輸數據呢,總得先尋個址,發幾個包先建立起來鏈接再說吧,這個過程就要到控制傳輸。尤其是一個新設備剛插入USB 集線器中,需要通過控制傳輸來進行設備枚舉。所以控制傳輸就是傳輸控制信息的。

六、USB協議包結構及類型

簡單來說 USB 包的結構如下:其中傳輸方式爲LSB,也就是先傳低位
| 同步域 | 8位標識符PID | … | EOP |
同步域:一是通知設備要開始傳輸了,而是主機和設備時間的時鐘同步

8位標識符PID:標識包的類型,目前USB協議僅使用4位(PID0PID3),另外4位(PID4PID7)是PID0~PID3的取反,用來校驗PID

…: 不同PID類型的包,此處不一樣,像握手包就沒有此部分

EOP:包結束標識

下表是不同PID對應的包類型:
在這裏插入圖片描述
IN、OUT和SETUP令牌包結構:注意IN和OUT是相對主機來說的,IN就是設備發主機收,OUT反之。

同步域 8位標識符PID 7位地址 4位端點號 5位CRC5校驗 EOP

SOF令牌包結構圖:

同步域 8位標識符PID 11位幀號 5位CRC5校驗 EOP

數據包結構圖:

同步域 8位標識符PID 字節0 字節1 字節n 16位CRC16校驗 EOP

握手包結構圖:

|同步域 |8位標識符PID| EOP|

PRE包:當需要傳送低速事務時,主機首先發送一個PRE令牌包(以全速模式發送)。對於全速設備,將會忽略這個令牌包。集線器在接收到這個令牌包之後,打開其連接了低速設備的端口,接着主機就會以低速模式給低速設備發送令牌包和數據包等。

同步域 8位標識符PID EOP

PING包:

同步域 8位標識符PID 7位地址 4位端點號 5位CRC5校驗 EOP

SPLIT包:高速事務分裂令牌包,通知集線器將高速數據包轉化爲全速或者低速數據包發送給其下面的端口。

開始SPLIT包結構:

同步域
8位標識符PID
7位 Hub addr
1位SC
7位Port
1位S
1位E
2位ET
5位CRC5
EOP
完成SPLIT包結構:

同步域
8位標識符PID
7位 Hub addr
1位SC
7位Port
1位S
1位U
2位ET
5位CRC5
EOP
其中 SC爲0代表start-split token

參數port是指設備在 HUB 下的端口號

參數S和E:
在這裏插入圖片描述
在這裏插入圖片描述
(4)ERR:在分裂事務中表示錯誤使用。高速分裂事務的過程比較複雜,而且主要是由集線器完成,所以不詳細說明

不同的傳輸方式也就是上面的包類型的不同組合,協議嗎,就是兩邊按照同一套規則,你一句我一句的完成要傳輸的任務,

固定的交互時序,沒有理解難度。

七、USB設備枚舉過程簡介

USB 支持熱插拔,設備在需要的時候插入,不需要的時候拔出,所以 USB 設備不能事先定義好,然後註冊進去,所以這就要求在插入的時候建立 usb_device。下面簡單總結下設備枚舉過程

1.主機集線器檢測到設備插入: 前面說過, USB 設備的D+ (全速設備,高速設備也會先識別成全速設備)或 D-(低速設備)接1.5k上拉電阻,設備插入的時候會根據 D+ 還是D-是高電平識別出是什麼類型的設備。

2.主機發送Get_Status請求: 集線器用中斷傳輸方式上報集線器上的事件。當主機收到插入設備事件,就給集線器發送一個Get_Status請求更多的消息。

3.主機發送Set_Feature請求: 當主機獲取到插入新設備後,給集線器發送一個Set_Feature請求,請求集線器重啓端口。

4.主機和集線器建立數據鏈路: 主機在此發送Get_Status獲取設備的重啓狀態。當集線器釋放重啓狀態,設備就開始工作,準備好 0 endpoint 準備響應主機通信。

5.獲取最大數據包長度: 前面的4步是主機和hub之間的交互,不涉及 usb 驅動框架的操作,從這一步開始USB驅動框架介入。

主機向 0 號端點發送 Get_Device_Descriptor命令獲取設備描述符,然後讀取設備描述符的bMaxPacketSize0字段,其地址偏移爲7,此時只讀前8字節(有些設備只支持返回8字節)。此時設備的缺省地址爲 0 ,所以一個時刻只能枚舉一個設備。

6.主機給設備分配地址: 第5步交互的時候,還是使用默認0地址,此時就要發送Set_Address分配一個唯一的設備地址。設備收到此請求,返回確認信息,並保存新的地址,然後就不再使用0地址,開始使用新的地址。

7.主機再次發送Get_Device_Descriptor命令: 上次發送Get_Device_Descriptor只是爲了獲取到bMaxPacketSize0字段,這次可是真的要獲取設備描述符了。

8.主機發送Get_Device_Configuration命令: 獲取到設備描述符後,開始獲取配置描述符,USB設備收到此請求要返回全部配置信息。

9.主機發送Get_Device_String命令: 獲取字符描述(如果有的話)。

到此,USB枚舉也就完成了,接下來就是要在 USB 總線上匹配相應驅動,後面的事都是匹配到驅動的動作了,在後面分析驅動的時候再詳解。USB 雖然使用起來方便,可驅動框架卻比較複雜,但大多數工作都由 linux 內核完成,後面將分析代碼中 USB設備時如何枚舉的,以及如何匹配驅動。其實只要設備枚舉出來了,後面不就是 在 總線上 match 驅動嗎!

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