Android/Linux USB Gadget:三層架構
阿新 • • 發佈:2019-02-20
1.前言
繼Linux Gadget的一點研究後陸續續關注了很久Android USB Gadget,一直想寫點什麼記錄一些認識,可是Linux USB實在是太複雜,讓人有點無從下筆的感覺。它的複雜並不是說不可以被人理解,而且涉及的面很廣。USB Host的驅動關注比較少,就對USB device驅動的認識來說,需從兩大方面去對它進行認識和了解,一方面是USB協議本身,如果連USB端點、裝置描述符、介面、複合裝置等概念都不清楚的話,那是無法理解Linux USB device驅動的;另外方面就是USB Gadget架構。而本文就是基於對USB Gadget架構的一點認識而記錄的。
2.Android USB
3.USB Gadget的三層架構
一般網上關於介紹USB Gadget的資料都是基於Linux2.6.32或在這之前的版本,作者在關注了Linux2.6.37和Linux3.0.4版本的核心,USB Gadget的一些API已經與Linux2.6.32的不同了。但是那些關鍵的資料結構還是一樣滴。 Linux USB Gadget分三層架構: 層次關係從上到下 一層:USB Gadget功能層。BSP/Driver開發者通常是要實現這一層,從而實現一個具體的裝置驅動,如Anddroid在此層實現了adb,mtp,mass_storage等。瀏覽參考關注此層程式碼時,會發現“composite”是此層的關鍵字,此層中關鍵的資料結構是:struct usb_composite_driver。這一層的驅動檔案一般為:driver/usb/gadget/android.c(android實現的)或driver/usb/gadget/serial.c(傳統Linux實現的USB轉串列埠)。 二層:USB裝置層。這一層是Linux核心開發維護者實現的,與我們沒太大關係,不用我們操心,我們只關心其的一些介面就行。瀏覽參考關注此層時,會發現“gadget”是此層的關鍵字,此層的關鍵資料結構是:usb_gadget_driver,usb_composite_dev。這層主要的一個驅動檔案為:driver/usb/gadget/composite.c 三層:USB裝置控制器驅動層。這一層主要是與CPU、CPU USB控制器有關,與硬體緊密相關,這一層也比較頭痛,主要它和USB控制器牽扯在一起,涉及有暫存器、時鐘、DMA等等。但是這一層往往是由晶片廠商去實現。我們一般僅需在板級檔案中處理好所需要的USB介面即可。這層的關鍵字就是“UDC”,主要驅動檔案命名含“udc”關鍵字,一般與CPU或晶片廠商有關,如driver/usb/gadget/xxx_udc.c。4.USB Gadget的三層架構的關係
4.1從Android的gadget功能層去看三層架構的關係
瀏覽driver/usb/gadget/android.c原始碼。 先看init函式,composite_driver是定義在driver/usb/gadget/composite.c中,static int __init init(void) { struct android_dev *dev; int err; android_class = class_create(THIS_MODULE, "android_usb"); if (IS_ERR(android_class)) return PTR_ERR(android_class); dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; dev->functions = supported_functions; INIT_LIST_HEAD(&dev->enabled_functions); INIT_WORK(&dev->work, android_work); mutex_init(&dev->mutex); err = android_create_device(dev); if (err) { class_destroy(android_class); kfree(dev); return err; } _android_dev = dev; /* Override composite driver functions */ composite_driver.setup = android_setup; composite_driver.disconnect = android_disconnect; return usb_composite_probe(&android_usb_driver, android_bind); }
static struct usb_gadget_driver composite_driver = {
.speed = USB_SPEED_HIGH,
.unbind = composite_unbind,
.setup = composite_setup,
.disconnect = composite_disconnect,
.suspend = composite_suspend,
.resume = composite_resume,
.driver = {
.owner = THIS_MODULE,
},
};
可見它是一個全域性的結構體,android.c中重新實現了它的setup和disconnect方法。然後呼叫函式usb_gadget_probe_driver(&android_usb_driver,android_bind);向USB裝置層進行探測和註冊。
【PS:2.6.32核心在init函式後面呼叫usb_composite_register(&android_usb_driver)進行註冊,2.6.37核心以後統一改為usb_gadget_probe_driver。】
usb_gadget_probe_driver(&composite_driver, composite_bind)函式定製在driver/usb/gadget/composite.cextern int usb_composite_probe(struct usb_composite_driver *driver,
int (*bind)(struct usb_composite_dev *cdev))
{
if (!driver || !driver->dev || !bind || composite)
return -EINVAL;
if (!driver->iProduct)
driver->iProduct = driver->name;
if (!driver->name)
driver->name = "composite";
composite_driver.function = (char *) driver->name;
composite_driver.driver.name = driver->name;
composite = driver;
composite_gadget_bind = bind;
return usb_gadget_probe_driver(&composite_driver, composite_bind);
}
函式usb_gadget_probe_driver呼叫usb_gadget_probe_driver相關USB裝置控制器驅動層進行註冊。
【PS:2.6.32核心在init函式後面呼叫usb_gadget_register_driver(&composite_driver)進行註冊,2.6.37核心以後統一改為usb_gadget_probe_driver(&composite_driver, composite_bind);】
usb_gadget_probe_driver()函式是每一個USB裝置控制器驅動要實現的,這個函式與硬體緊密相關。
至此可以看到三層的關係:USB Gadget功能層呼叫USB裝置層的介面,USB裝置層呼叫USB裝置控制器驅動層的介面。