LINUX USB 系統(3)

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]

 

 

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