本文由 Linux 内核文档翻译与总结而来,个人学习条记仅供参考。
Gadget 框架
在 USB 协议交互过程中,角色定义:
- the device driver is the master (or “client driver”)
Linux 内核中称为 HCD(Host Controller Driver),负责与 USB 主机控制器硬件(通常是计算机的 USB 控制器)进行交互,管理 USB 数据传输。
- the gadget driver is the slave (or “function driver”)
Linux 内核中称为 UDC(USB Device Controller),管理连接到 USB 设备端的硬件,处理设备端的数据传输、设备枚举和其他 USB 设备相干的操作。
USB Controller Driver(UDC 驱动)
- <linux/usb/gadget.h> 定义的API中,对底层 USB 控制器端点硬件抽象成 endpoint (能够吸收 IN/OUT 数据流),通过回调与 Gadget Driver 交互。
- Controller Driver 采用分时复用的方式进而可以对接任意数目的 Gadget Driver 交互;
Gadget Driver
对 USB Controller 的硬件抽象以支持 USB Function 开辟,形式为各种调用接口。Gadget Driver 工作职责如下:
- 响应 setup 请求, 由 ep0 负责的相干协议的应答也包罗 calss 类别相干功能实现;
- 响应 configuration、String 形貌符;
- (重新)设定 Configuration 和 Interface, 包罗对端点的 使能与配置;
- 报告 活动变乱,例如:绑定到硬件、挂起/恢复、远程唤醒、断连等;
- 管理 全部端点的 IN/OUT 收发;
Linux 社区并不鼓励通过这个方式添加如此多的专有驱动。
Upper Level
在 Gadget driver 之上可以连接到 Linux 内核的其他驱动或框架,通过绑定的形式与 Dadget 驱动完成数据的收发。可参考:
- 用户空间,利用 gadgetfs 或 /dev 下相应节点操作;
- 网络子体系,如:CDC Ethernet Model gadget 驱动;
- 其他:Input 子体系(HID gadgets)、Sound 子体系(Aduio gadget)、文件体系(PTP gadget)等;
Additional Layers
可选的层,如:内核网络模块栈、用户应用、标准 POSIX 体系调用等。
Gadget API
数据结构
gadget driver 利用struct usb_gadget_driver包罗自身信息之外还包罗另外三种数据范例。明确这些数据范例和利用方法就算是把握了API。
- usb_gadget_driver dadget信息;
- //----> linux_5.10/include/linux/usb/gadget.h
- struct usb_gadget_driver {
- ...
- int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *);
复制代码 - usb_gadget,枚举信息;
- struct usb_gadget {
- ...
- struct usb_udc *udc;
复制代码 - usb_ep,端点配置;
- struct usb_ep {
- ...
- const struct usb_ep_ops *ops;
- ...
- struct usb_ep_caps caps;
- ...
- u8 address;
- const struct usb_endpoint_descriptor *desc;
复制代码 - usb_request,数据收发;
- struct usb_request {
- void *buf;
- unsigned length;
复制代码 - linux/usb/ch9.h,Gadget 驱动利用的在USB ch9 中定义的公共的 USB 数据结构,不分 Host 与 Device。
利用中关注:
- 规定利用端点0作为作为各种硬件限定信息的配置与管理,如:发送范例、地址、包巨细、缓存和其他本领集;
- USB message 痴肥(chunky),一个IO请求需要由一个或多个”数据包“组成且边界可被驱动感知;
- USB 协议更像是异步通讯协议(如:HDLC,每帧有 N 个 Byte,多个地址,Host 第一站,Device 其次)超过异步通讯协议(如:TTY,每帧8个 Bit,无奇偶检验位,无停止位);
- USB 数据包是有边界的,如: 一个 USB IN 包数据是 two-byte 一个单位,因此不能将两个单字节直接写入一个单位;
对象与方法
Gadget 设备
核心
- <linux/usb/gadget.h>, 定义了 Gadget 驱动核心对象与方法;
可选
核心 API 已富足支撑 Gadget 驱动开辟,但还另外提供了一些可选工具用以简化常用任务。
- drivers/usb/gadget/usbstring.c;
- drivers/usb/gadget/config.c;
composite 设备
核心 API 已富足开辟 Composite 设备(一个 configuration 中有多个功能)和 多功能设备驱动的开辟,composite 复合框架将简化这些设备驱动的开辟。
框架
composite 设备框架定义了一个设备结构体 struct usb_composite_driver ,其内可关联多个struct usb_configuration 实例。每个 configuration 又包罗多个 struct usb_function 定义。在 function 中定义了用户可感知的设备角色,如:Network Link、mass storage device,也可包罗管理功能,如:Device Firmware Upgrade。
- include/linux/usb/composite.h,数据结构定义;
- drivers/usb/gadget/composite.c,框架实现;
功能
当前只要是利用 DECLARE_USB_FUNCTION_INIT声明的 Gadget 驱动就都是 composite设备,可对应检察源码 drivers/usb/gadget/function/f_xxx.c。
Legacy 设备
源码目录 drivers/usb/gadget/legacy/xxx.c。
活动变乱
Gadget 驱动执行I/O请求时时不用关注硬件细节要求,而当驱动执行 setup/configuration 时就需要关注流程:
- 注册 UDC 驱动(USB Device Controller,作为**设备(Slave)**角色的 USB 控制器驱动);
当前作为设备插入 Host 后会处于 attached 初始化状态( USB ch9 中定义)。此时既无功率斲丧也法被利用(还不支持枚举)。
由于当前数据线上的上拉未使能,所以即使 VBus 正常供电,Host 也无法感知到当前设备的存在(Host 通过设备是否上拉数据线探测设备)。
- 注册 Gadget 驱动;
这些更高层级的 Fuction 驱动将调用 bind() 绑定到具体的 gadget 设备( struct usb_gadget 对象) 。有时这些 Function会在辨认到 VBUS 后使能数据线上拉。
- 硬件驱动开始枚举;
此时设备可以担当 USB power 和 set_address 请求,余下步调由 gadget driver 接管。假如 dadget driver 在枚举前还未加载,忽略厥后步调直接跳转至步调 7,执行 unbind()。
- 实现 Gadget 驱动中 setup()方法;
setup()方法将返回当前设备的:形貌符、硬件接口和本领集等信息。假如硬件允许,乃至可以执行更复杂的设定和配置。
- 实现 set_configuration 请求的应答;
Gadget 驱动需要在setup()方法中实现对主机set_configuration请求的应答(枚举的末了一步),利用全部在 Configuration 中利用的端点 和 默认 settings 中的接口;
- 实现数据收发;
- 实现 Gadget 驱动中 unbind()方法;
当 Gadget 驱动卸载时,同时卸载 UDC 驱动;
注:
- 在设备连接到Hub后会导致Hub的D+或D-电平变化,Hub根据变化的引脚分辨接进来的是全速设备还是低速设备:
- 低速设备内部的D-有1.5K的上拉电阻;
- 全速设备内部的D+有1.5K的上拉电阻;
- 高速设备一开始也是作为全速设备被辨认的,高速模式时,D+的上拉电阻是断开的;
UDC 驱动
UDC(USB Device Controller),即USB从机(设备)控制器,内核文档也称为 Peripheral Controller Drivers。内核中第一个支持的硬件的是 NetChip 2280 控制器(基于PCI 的支持 USB 2.0 调整模式)。其他的控制器基于 gadget 框架开辟,见驱动源码文件: linux_5.10/drivers/usb/gadget/udc/xxx_udc.c。
假造UDC
方便硬件控制器未准备好(缺失或功能异常)时的软件调试,内核实例了一个假造的 UDC 驱动。它像 net2280、pxa25x 和 sa11x0 等硬件控制器一样指代多个端点和速率模式,也能够模仿 控制传输、批量传输 和 中断传输。这也就方便了开辟支持在
Gadget 驱动
除 gadget_Zero驱动(主要用于UDC功能验证)之外,内核另有示例了多个常用的 gadget 驱动。
CDC 类
CDC(Communications Device Class)是太网模型的两个逼迫选项之一,也是电缆调制解调器交互操作性的标准之一。在USB主机看来,利用此代码的gadget 就像是以个太网适配器。
CDC类实现源码文件位于:drivers/usb/gadget/function/f_xxx.c,其下包罗:
- USB CDC serial 类: ACM;
- USB CDC Ethernet 类:ECM、EEM、RNDIS,简单辨析如下:
注:暂且把 微软的 RNDIS 驱动也纳入CDC Ethernet 类,由于 RNDIS 更适合运行在轻量化的 USB 控制器设备中。RNDIS 为设备接入 Windows 体系利用提供了便捷。
MSC 类
MSC(Mass Storage class)指常用的存储设备,如:U盘、CD-ROM等。大容量存储类设备驱动利用一种不同于 MS-Windows 和 MacOS 的交互方式:
- USB 设备端,驱动利用一个具体的文件或块设备作为厥后端存储介质;
- USB 主机端,主机遵循 BBB, CB 或 CBI 版本的 MSC 类规格要求利用 SCSI 命令访问后端不认介质;
MSC 类实现源码文件包罗:
- drivers/usb/gadget/function/f_mass_storage.c,被主机视为 磁盘、CD-ROM 等存储设备访问;
- drivers/usb/gadget/function/f_loopback.c,主要用于应用回环测试;
OTG 功能
USB OTG(USB On-The-GO)指代可以进制双角色切换机制的 USB 控制器:
- 作为 Host时,利用标准 Linux-USB 主机侧驱动栈;
- 作为 Device时,利用 Gadget 框架;
见下图,可以看到:Host Controllere、 Device Controller、OTG Bus Monitor 三个紧张组成
在不同角色下,体系都应只管复用顶层已申请的、硬件无关的顶层控制器驱动(Host, usb_bus;Device, usb_gadget)内存池;包管功能正常的最小修改;包管对非 OTG 产品的影响。可以抽象出以下几个控制特性:
- is_otg,Gadget 驱动检查这个标记以确认是否需要在其 configurations 中添加 OTG 形貌符;
- b_hnp_enable, Gadget 驱动假如需要支持两种新的 OTG 协议:
- HNP, 通过用户接口(如:两个 LED 灯)指示当前设备被 Host 挂起;
- SRP, 可由用户发起(就像远程唤醒),如按下相干按键;
- 白名单,如同主机侧,驱动必须支持 OTG 目的外设名单,用以声明支持的 OTG 控制器,即 OTG 白名单。修改文件 otg_whitelist.h。
需知
- 每个 USB Function 都会在 config_groups 中定义盼望用户配置的内容,可配置参考对应 Function 的实现文件:drivers/usb/gadget/f_*.c
- 主要阅读 USB 规范章节9 和 内核 gadget.rst 文档,以免忽略掉关键信息,如:端点自动配置,否则需要同时参考头文件与示例源码(如 Gadget Zere);
参考
- 内核文档 linux_5.10/Documentation/usb/gadget_configfs.rst
- 11_Gadget驱动程序框架
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |