1、 OTG 控制器
OTG 的基本概念
首先,提出一個問題, OTG 和 EHCI/OHCI/UHCI 是同一類概念嗎?
那我們先看一看 OTG 能做些什麼。
在 OTG 中,我們一般不把設備叫做主設備或從設備,而稱作 A-DEVICE 和 B-DEVICE 。一般而言, A-DEVICE 作主, B-DEVICE 作從,但也不能這樣綁定, A-DEVICE 也可以作從,這時 A-DEVICE 仍要爲總線提供電力。
OTG 設備使用插頭中的 ID 引腳來區分 A/B Device , ID 接地被稱作爲 A-Device, 爲連接時候的 USB Host , A-Device 始終爲總線提供電力。 ID 懸空被稱作爲 B-Device, 爲連接時候的 USB Device( 作從 ) ,設備的 USB Host/USB Device 角色可以通過 HNP 切換。
OTG Device :使用 Micro AB 插座,可以在運行時切換 Host/Device 。
僅外設 B-Device :僅僅能作爲外設的 B-Device (分爲插頭一體和插頭線纜分離的)。
可見, OTG 主要是負責控制器狀態的切換,這種切換要根據接入的設備來判斷。 OTG 主要使用在嵌入式設備中,說到嵌入式不能不提降低功耗了,所以僅有 ID 線的檢測還是不夠的。
OTG 中的三大協議
SRP ( Session Request Protocol ):
B-Device 使用。通過數據線上的脈衝,請求 A-Device 打開 VBUS 並且開始-個 Session 。 Session 爲從 VBUS 打開到關閉這一段時間。
支持: A-Device 允許迴應 SRP , B-Device (包括僅能作爲外設的 B-Device ),允許發起 SRP 。一個能夠支持 HNP 的 B- Device 應該能夠發起 SRP 。當 A 插頭插入時關閉 VBus 的 Host 必須支持迴應 SRP , VBus 總是打開的 Host 不必響應 SRP 。
ADP ( Attach Detection Protocol ):
提供設備檢測是否有對端設備插入。
HNP ( Host Negotiation Protocol ):
OTG 設備通過 HNP 來切換 Host/Device 角色。
OTG 不同連接方式的不同過程
OTG Device /Embedded Host 與 僅作爲外設的 B-device (帶 A 插頭型)
Host 端檢測到 A 插頭插入,停止 ADP ,打開 VBus ,因爲 B-Device 的 A 插頭與設備作爲一體,此時 B-Device 必定與 A 插頭連接, Host 檢測到外設連接,開始枚舉。
OTG Device/Embedded Host 與 僅作爲外設的 B-device ( A 插頭爲線纜連接)
Host 段檢測到 A 插頭插入,停止 ADP ,打開 VBus ,如果 B-Device 是線纜連接完畢在將 A 插頭插入則整個連接過程與上面無異,因爲此 時 B-Device 可能還沒有插入插頭,則設備連接超時, VBus 再次關閉,等待下一次 ADP 的改變(線纜連接完畢),再次打開 VBus ,此時開始正常總 線枚舉。
OTG Device 與 OTG Device
Host 端檢測到插頭插入,則打開 VBus ,如果沒有外設檢測到,則關閉 VBus ,打開 ADP Probing , Device 端檢測到插頭插入,則打開 SRP ,如果線纜沒有插入,則 SRP 超時, Device 端開始進行 ADP Probing ,當線纜連接完畢, Device 端偵測到 ADP 變化,發送 SRP 請求 Host 打開 VBus , Host 迴應 SRP 並且打開 VBus ,完成設備 連接。
從上面的過程可以看出, ADP 和 SRP 的目的都是爲了節能,平時 VBus 上的供電是並沒有打開的,而且在空閒一段時間後 VBus 也會自動關閉。在 VBus 不供電的情 況下就需要靠 ADP 和 SRP 來檢測外設並打開 VBus 的供電。如果 VBus 上一直有電流供應, ADP 和 SRP 就無用武之地了。可見,在嵌入式的世界裏,確實要精打細算, ADP 和 SRP 是何等的複雜,這麼複雜的設計僅是爲了省幾毫安的電流。
回來我們前面的問題, OTG 和 EHCI/UHCI/OHCI 是同一類的概念嗎?
OTG 的作用只是負責切換主從狀態的切換,同時,在功耗方面也有要求, OTG 要求 vbus 不能像 PC 那樣永遠供電,所以這樣就需要有一套設備發現機制,這就是 SRP 和 ADP 了。 OTG 也允許同進充許同類設備進行數據傳輸( A TO A ) , 這就是 HNP 發揮作用的時候了。
當 OTG 己經發現設備, VBUS 供電開啓,系統處於 HOST 或 DEVICE 狀態,這時 OTG 的使命就完成了,接下來的工作就交給主控制器( EHCI/OHCI/UHIC )或從控制器了。
所以 OTG 的主要是在設備接入的那一刻起作用,此後 USB 還是要按傳統的 HOST/DEVICE 的方式來通訊。當然,有些 OTG 控制器會集成一些 HOST 控制器的功能,這些控制器並不符合任何一種標準,一旦遇到這種 OTG 控制器,驅動開發人員就要倒黴了。 USB 系統中最複雜的就是主控制器了,如果與主控制器與 USB 標準有出入,就無法重用大量成熟的控制代碼,驅動開發人員就需要重新去研究整個 USB 協義,這無疑是一份耗時耗力不討好的活。
Linux 下的 OTG 架構
內核 定義了一個 struct otg_transceiver 的結構體,這個結構體描述的 OTG 需要支持的接口
struct otg_transceiver { struct device *dev; const char *label;
u8 default_a; enum usb_otg_state state; // 記錄 OTG 控制器的狀態,在實際的處理中這個比較重要。
struct usb_bus *host; struct usb_gadget *gadget;
/* to pass extra port status to the root hub */ u16 port_status; u16 port_change;
/* bind/unbind the host controller */ int (*set_host)(struct otg_transceiver *otg, struct usb_bus *host);// 這個接口用來啓用或禁用主控制器,是關鍵的接口
/* bind/unbind the peripheral controller */ int (*set_peripheral)(struct otg_transceiver *otg, struct usb_gadget *gadget);
/* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct otg_transceiver *otg, unsigned mA);// 一般用來設置 vbus 上的供電
/* for non-OTG B devices: set transceiver into suspend mode */ int (*set_suspend)(struct otg_transceiver *otg, int suspend); // 下面是 OTG 的三大高級功能的接口。 /* for B devices only: start session with A-Host */ int (*start_srp)(struct otg_transceiver *otg);
/* start or continue HNP role switch */ int (*start_hnp)(struct otg_transceiver *otg);
/* b device disconnect during hnp */ int (*disconnect)(struct otg_transceiver *otg);
/* b device connect */ int (*connect)(struct otg_transceiver *otg, struct usb_device *udev);
/* host suspend the bus during hnp */ int (*host_suspend)(struct otg_transceiver *otg);
/* hand interrupt related to usb otg */ int (*otg_interrupt)(struct otg_transceiver *otg);// 中斷處理接口 }; |
上表的結構體很清晰的描述了 OTG 的功能,只要實現幾個重要的接口,就能把你的 OTG 控制器和 linux 系統聯接起來。
系統中作了如下定義:
struct otg_transceiver *xceiv;
這個定義就是一個 OTG 控制器的對像,然後使用 otg_set_transceiver 來實現這兩者之間的聯接。
注:轉載請註明出處 [email protected]