【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 功能。
OTG 是一个比较复杂的规范。
【控制器驱动】
常见的 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_*()函数实现。
【Gadget框架结构】
kernel/drivers/usb/gadget,这个目录是android下usbgadget的主要目录。
Gadget功能组织单元:主要文件android.c,usb gadget功能的统领文件,负责组织usb 复合设备的功能,与上层应用提供交互的接口,面向市场需求的产品规划部门。
复合设备逻辑处理单元(复合设备管理单元):主要文件:composite.c,这个文件类似于一个项目管理组,负责各个单元的接口对接,资源整理。针对拥有多个usb功能的复合设备,这部分负责将支持的各个功能组织到一起,协助各个功能与UDC控制器单元建立联系。
具体功能单元:以U盘为例,f_mass_storge.c文件,用来完成具体的功能。这个部分是一个功能性很强的部分,将与UDC控制器单元直接对话,完成数据的传输。
UDC控制器单元:只做一件事情,收发usb数据,将数据透明的传递出去。
通过configfs用户空间对android gadget设备的配置在init.usb.rc文件中。
【Gadget 驱动 类型】