Linux USB-Gadget 驅動框架

2021-02-15 Linux與嵌入式系統

1. 簡介

USB gadget是什麼?Linux-USB Gadget 驅動框架(以下簡稱 Gadget)實現了USB 協議定義的設備端的軟體功能。相對於 Linux USB 主機端(Host) 驅動而言, Gadget 驅動出現較晚,它出現在2.4.23 以後。 

Gadget 框架提出了一套標準 API, 在底層, USB 設備控制器(USB Device Controller, UDC)驅動則實現這一套 API, 不同的 UDC (通常是 SOC 的一部分) 需要不同的驅動, 甚至基於同樣的 UDC 的不同板子也需要進行代碼修改。這一層我們可以稱之為平臺相關層。 

  基於 API, Gadget 驅動實現了一套硬體無關的功能,這基本上可以對應到 USB 協議裡 的各種 USB Class, 也有比如 USB Gadget Generic Serial 驅動,沒有對應的 Class。當然,Gadget 驅動還是受限於底層提供的功能的。比如 某些 Class 需要 USB Isochronous  端點,這時我們就不能支持該 Class。   普通的 Gadget 驅動只實現一個功能(比如u 盤,usb 網卡)。複合設備可以支持多個功能,後面將仔細研究一下複合設備的實現。像智慧型手機, PDA這樣的設備,硬體支持較豐富的端點、DMA Buffer, 給軟體提了支持複合功能的基礎。 

 有兩點值得注意,第一是 usb gaget 驅動框架不象 usb 主機端有 usb core 的概念,usb 主機可能支持成百類型的外設,把通用功能抽象出來很有意義。Usb device 端則通常沒有這個需求,一些通用功能抽象在一些 Helper 函數裡就可以了。第二是 usb 2.0 裡提出了 OTG 的概念,可以在同一接口上支持 host 以及 device 功能。   

 

2. 控制器驅動 

常見的 usb device 有 U 盤, usb 滑鼠、鍵盤,usb 藍牙模塊,usb 讀卡器,等等。這些設備比較簡單,通常不會運行Linux。運行Linux Gadget 的通常是一些集成 CPU 以及很多外設接口的 SOC (System-on-Chip), 其中 CPU 通常為 32 bit 的 CPU, 並且 udc 也是該 SOC 的一部分( 順帶還有 DMA 通道,FIFO)。 

Linux 標準內核裡支持各主流 SOC 的 udc 驅動,make menuconfig 一下可以看到具體列表,其中值得一提的是 dummy_hcd, 它是一個軟體模擬的 udc, 在開發新的 gadget 驅動時很有幫助。 

 控制器驅動處理很少的 USB 控制請求(主要由硬體負責的部分)。其它所有的控制請求,比如返回描述符,設置當前配置,由 Gadget Driver 完成。控制器驅動一個主要責任就是負責管理各個端點的 I/O 隊列,在 Gadget Driver 的 buffer 和硬體buffer 之間傳輸數據(通常是通過 DMA)。 

我們前面提過,上層 Gadget 驅動能夠實現什麼功能要依賴底層提供的硬體條件。比如一個複合設備需要至少 5 個端點,這些硬體特性通過一組 gadget_is_*()函數實現。   

 

3. Gadget 驅動 

 基於底層提供的資源, Gadget 驅動可以運行在各種硬體平臺上。重要的驅動有: 

     Gadget Zero, 類似於 dummy hcd, 該驅動用於測試 udc 驅動。它會幫助您通過 USB-IF 測試。   

    Ethernet over USB, 該驅動模擬乙太網網口,它支持多種運行方式: 

     CDC Ethernet: usb 規範規定的 Communications Device Class 「Ethernet Model」 protocol。   

    CDC Subset: 對硬體要求最低的一種方式,主要是 Linux 主機支持該方式。

     RNDIS: 微軟公司對 CDC Ethernet 的變種實現。 

      File-backed Storage Gadget最常見的 U 盤功能實現。   

     Serial Gadget 實現,包括: Generic Serial 實現(只需要Bulk-in/Bulk-out端點+ep0)和CDC ACM 規範實現。 

      Gadget Filesystem, 將 Gadget API 接口暴露給應用層,以便在應用層實現user mode driver。   

MIDI: 暴露ALSA接口,提供 recording 以及 playback 功能。

 

4. t軟體結構

USB Gadget軟體結構總共分為三層:

a.UDC(USB Device Controller)層

這一層是與硬體相關層。以S3C2410為例,其作為一個linux設備在這一層是作為platform設備而註冊到linux設備模型中的。S3C2410是集成的USB設備控制器,所以就是採用platform驅動的形式來註冊的。如果系統是外接的USB設備控制器,那麼則會採用相應總線的註冊形式,比如PCI等。

b.USB設備層

USB設備層,雖然名字上與設備相關。但是屬於硬體無關層。這一層的功能是隔離Gadget功能驅動與硬體相關層。使得功能驅動直接與USB設備層交互不用考慮硬體的相關細節。還有USB設備層提供了USB設備的一些基本數據結構,不同的Gadget功能驅動可以共同調用。如果沒有這一層,則每一個功能驅動都需要實現自己的USB設備,導致了代碼重用率很高。這一層向下與UDC層進行交互,向上與Gadget功能驅動層進行交互。在UDC層已經介紹了USB設備層向下與UDC層交互方式主要是通過調用usb_gadget_register_driver(struct usb_gadget_driver *driver),這個函數是UDC層提供的。而這個函數傳遞的參數就是一個usb_gadget_driver的結構體。

c.Gadget功能驅動層

Gadget 功能驅動層是USB Gadget軟體結構的最上層。主要是實現USB設備的功能,這一層通常與linux內核的其他層有密切的聯繫。模擬網卡或者串口的gadget就與文件系統層與塊IO層有著聯繫。

下面的圖很好的說明了整個USB-Gadget軟體架構:

 


相關焦點

  • 一文搞懂 USB 設備端驅動框架
    USB 設備驅動 2.1 gadget 驅動框架拆解1我們將USB 設備端驅動拆解一下,其驅動框架如下:usb 驅動框架之所以複雜,除了需要研究各種複雜的協議,還融合了各種驅動,對於初學者來說,理解起來有點困難。事實上,光是legacy這裡也包含其他驅動,比如webcam裡有大名鼎鼎的 v4l2 驅動框架。所以當我學習USB驅動框架的時候,一定要抓大放小,【把握主要脈絡,忽略細節】。
  • Linux USB總線驅動框架分析
    1.2 USB接入識別大致過程當識別出有USB設備插入後,linux內的USB總線驅動程序發出命令至該設備,與設備對話,並詢問設備信息(描述符),設備收到請求後,回復設備描述符給總線驅動程序。且總線驅動程序會為該設備分配一個地址,如上地址為2,當後期訪問某個USB設備時,均會通過這個地址編號,當新接入的USB設備被第一次訪問時,以地址0來訪問。
  • USB驅動框架(二)
    前面簡單聊了一下USB驅動的整體框架《USB驅動框架(一)》,接下來看一下主機控制器驅動框架。//include/linux/usb/hcd.hstruct usb_hcd { struct usb_bus self; /* hcd是一個總線 */ struct kref kref; /* 引用計數
  • USB設備控制器(UDC)驅動分析
    內核版本:4.20.12驅動路徑:/drivers/usb/chipidea/core.c                /drivers/usb/chipidea/udc.cUSB IP核:ChipideaChipidea的UDC驅動和主機控制器驅動都是放在core.c中,裡面根據不同的配置來選擇初始化角色(主機,外設,OTG等)。
  • Linux 下使用USB 網絡
    g_ether.ko在配置菜單位置如下Symbol: USB_ETH_RNDIS [=n] ││ Prompt: RNDIS support ││ Defined at drivers/usb/gadget/Kconfig:609 ││ Depends on: <choice> && USB_ETH │
  • Linux USB滑鼠驅動程序詳解
    一個 USB 總線引出兩個重要的鍊表,一個為 USB 設備鍊表,一個為 USB 驅動鍊表。設備鍊表包含各種系統中的 USB 設備以及這些設備的所有接口,驅動鍊表包含 USB 設備驅動程序(usb device driver)和 USB 驅動程序(usb driver)。
  • 帶你遨遊USB世界
    結構體在include\linux\usb\ch9.h中定義和具體含義:設備描述符結構體/* USB_DT_DEVICE: Device descriptor */struct usb_device_descriptor {__u8 bLength; //該描述符結構體大小(18位元組)__u8 bDescriptorType
  • adb使用技巧和usb通信原理探索
    (usb_vendors.c)    usb_init(usb_linux.c)]new thread----device_poll_thread(usb_linux.c)find_usb_device(usb_linux.c)kick_disconnected_devices(usb_linux.c)從usb_vendors.c文件中
  • 安卓adb使用技巧和usb通信原理探索
    (usb_vendors.c)    usb_init(usb_linux.c)]new thread----device_poll_thread(usb_linux.c)find_usb_device(usb_linux.c)kick_disconnected_devices(usb_linux.c)從usb_vendors.c文件中
  • uart驅動框架分析(二)uart_add_one_port
    作者:lizuobin (也是百問網論壇兼職答疑助手)原文:https://blog.csdn.net/lizuobin2/article/details/51801183 (所用開發板:mini2440, jz2440類似,代碼很多,需要你建個si工程跟著代碼分析)在前面的一篇文章中:   tty初探 — uart驅動框架分析
  • Linux 上如何禁用 USB 存儲
    編譯自 | http://linuxtechlab.com/disable-usb-storage-linux/  作者 | Shusain
  • 「圖文」深入了解Linux USB驅動工作的整個流程
    (USB 核心將其傳遞給USB設備驅動,並由USB設備驅動負責後續的控制。ep_dev; /* For sysfs info */    unsigned char*extra;/* Extra descriptors */    int extralen;    int enabled;};當調用USB設備驅動調用usb_submit_urb提交urb請求時,將調用int usb_hcd_link_urb_to_ep(struct
  • Linux 2.6.35 自帶的USB轉UART晶片CH341T的驅動有問題
    老wu看到有CH341T的驅動支持,很開森。直接選中然後開始make。然後就開森不起來了,從Debug Console列印的引導記錄來看,USB 已經加載了,但是看布袋 ttyUSB 的加載,ls /dev/ttyUSB* 也沒任何結果。
  • USB主機控制器驅動分析
    前面我們介紹了USB的基礎知識和USB驅動框架
  • 解密:Linux與Android的關係
    這就與Linux的一些特性有關了,比如:  1、強大的內存管理和進程管理方案  2、基於權限的安全模式  3、支持共享庫  4、經過認證的驅動模型  5、Linux本身就是開源項目  看到這個標題大家可能會有些迷惑,前面不是一直說Android是基於Linux內核的嗎,怎麼現在又不是Linux了?
  • 嵌入式Linux USB驅動開發之教你一步步編寫USB驅動程序
    usb_complete_t complete_fn,  7.                  void *context,  8.                  int interval);  9.
  • Linux 終端初始化 console_init 及 tty 驅動框架
    linux4.14/kernel/printk/printk.clinux4.14/drivers/tty/n_tty.c__con_initcall_start 和 __con_initcall_end 定義在:linux4.14/include/asm-generic/vmlinux.lds.h
  • Linux下的驅動設備分離思想
    總的來說就是當我們向系統註冊一個驅動時,總線就會在設備文件中查找,看看有沒有與之匹配的設備,如果有的話就將兩者聯繫起來。同樣的,當向系統中註冊一個設備的時候,總線就會在驅動文件中查找看有沒有與之匹配的驅動,有的話也聯繫起來。因此,最終Linux下的驅動、設備、總線框架也就呼之欲出了。
  • linux 驅動程序的數據封裝
    0.引言基於 ARM 內核的 SoC 在引入設備樹技術之後,通過設備樹文件來描述不同的設備並匹配不同的驅動代碼,使得一個 kernel 鏡像文件可以支持多種設備。這種代碼可重用的思想不僅體現在設備樹文件中,在驅動代碼中同樣也有所體現。其中之一就是驅動代碼中設備描述表-of_device_id。