USB 驱动开发 --- Gadget 驱动框架梳理(一)
本文由 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.hstruct 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驱动程序框架
相关文章:

USB 驱动开发 --- Gadget 驱动框架梳理(一)
本文由 Linux 内核文档翻译与总结而来,个人学习笔记仅供参考。 Gadget 框架 在 USB 协议交互过程中,角色定义: the device driver is the master (or “client driver”) Linux 内核中称为 HCD(Host Controller Driver),负责与 …...

1Hive概览
1Hive概览 1hive简介2hive架构3hive与Hadoop的关系4hive与传统数据库对比5hive的数据存储 1hive简介 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。 其本质是将SQL转换为MapReduce/Spark的任务进…...

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)
【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection) 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集,可以获取数据库中未授权的数据。这种注入技术要…...

IoTDB 常见问题 QA 第三期
关于 IoTDB 的 Q & A IoTDB Q&A 第三期持续更新!我们将定期汇总我们将定期汇总社区讨论频繁的问题,并展开进行详细回答,通过积累常见问题“小百科”,方便大家使用 IoTDB。 Q1:查询最新值 & null 数据相加方…...

RabbitMQ---消息确认和持久化
(一)消息确认 1.概念 生产者发送消息后,到达消费端会有以下情况: 1.消息处理成功 2.消息处理异常 如果RabbitMQ把消息发送给消费者后就把消息删除,那么就可能会导致,消息处理异常想要再获取这条消息的时…...
《鸿蒙Next旅游应用:人工智能赋能个性化与智能导览新体验》
随着鸿蒙Next的推出,旅游应用迎来了全新的发展机遇,借助人工智能技术能为用户带来更出色的个性化推荐和智能导览服务。 鸿蒙Next与人工智能融合优势 鸿蒙Next拥有强大的分布式能力和原生智能体验。其能打破设备界限,实现多设备协同…...
微信小程序获取当前页面路径,登录成功后重定向回原页面
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回&#…...
【9.2】Golang后端开发系列--Gin路由定义与实战使用
文章目录 一、Gin 框架路由的基本定义方式1. 简单路由创建2. 路由参数3. 查询参数 二、商业大项目中的路由定义和服务调用1. 路由模块化2. 路由组和中间件3. 中间件的使用4. 服务层调用5. 错误处理6. 版本控制7. 路由注册 一、Gin 框架路由的基本定义方式 1. 简单路由创建 使…...
【微信小程序】let和const-综合实训
let 和 const 都是用于声明变量的关键字,它们与传统的 var 关键字相比,有很多不同之处。 let 声明块级作用域变量,可再赋值;const 声明块级作用域常量,不可再赋值。 以下是它们的详细介绍: 一、基本概念…...

图匹配算法(涵盖近似图匹配)
【图数据管理与挖掘-第四讲(子)图匹配算法(涵盖近似图匹配) 北京大学2021暑期-邹磊教授】https://www.bilibili.com/video/BV1zh411q7PW?vd_source7c2b5de7032bf3907543a7675013ce3a 图同构: 定义: 给定…...

java线程——Thread
java线程——Thread 基本步骤示例优劣总结 继承Thread类是Java中实现多线程的一种方式。使用时创建一个新的类,该类继承自java.lang.Thread,并重写其run()方法,在方法中定义线程执行的任务逻辑。 基本步骤 1、创建一个子类:定义一…...
MySQL8.0新特性
第十八章_MySQL8.0新特性 1.新特性概述 1. 数据库管理和存储 1.1 数据字典 特性: MySQL 8.0 使用统一的数据字典存储元数据(如表、列、索引等),并将其存储在 InnoDB 表中。 优点 : 提升性能:减少对文件系统的依赖。 提高一致…...

Oracle EBS GL定期盘存WIP日记账无法过账数据修复
系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状 用户反映来源为“定期盘存”和类别为“WIP”的日记账无法过账,标准日记账的界面上的过账按钮灰色不可用。但是,在超级用户职责下,该日记账又可以过账,细心检查发现该业务实体下有二个公司段值15100和…...
【绝对无坑】Mongodb获取集合的字段以及数据类型信息
Mongodb获取集合的字段以及数据类型信息 感觉很LOW的一个数据仓工具seatunel,竟然不能自动读取mongodb的表结构信息,需要手工创建。 然鹅,本人对mongodb也是新手,很多操作也不知所措,作为一个DBA,始终还是…...

【Git版本控制器--1】Git的基本操作--本地仓库
目录 初识git 本地仓库 认识工作区、暂存区、版本库 add操作与commit操作 master文件与commit id 修改文件 版本回退 撤销修改 删除文件 初识git Git 是一个分布式版本控制系统,主要用于跟踪文件的更改,特别是在软件开发中。 为什么要版本…...
C++并发编程之无锁数据结构及其优缺点
在C并发编程中,无锁数据结构(Lock-free Data Structures)是指那些在实现中不使用互斥锁(如std::mutex)来保证线程安全的数据结构。相反,它们利用原子操作和内存模型来确保多线程环境下的正确性和高效性。下…...

Ubuntu上,ffmpeg如何使用cuda硬件解码、编码、转码加速
本文使用 Ubuntu 环境。Ubuntu 直接使用 APT 安装的就支持 CUDA 加速。本文使用这样下载的版本进行演示,你自己编译或者其他源的版本可能会不同。 ffmpeg 的一些介绍,以及 macOS 版本的 ffmpeg 硬件加速请见《macOS上如何安装(不需要编译安装…...

rclone,云存储备份和迁移的瑞士军刀,千字常文解析,附下载链接和安装操作步骤...
一、什么是rclone? rclone是一个命令行程序,全称:rsync for cloud storage。是用于将文件和目录同步到云存储提供商的工具。因其支持多种云存储服务的备份,如Google Drive、Amazon S3、Dropbox、Backblaze B2、One Drive、Swift、…...
Ubuntu | 系统软件安装系列指导说明
文章目录 Ubuntu 系统软件安装系列指导说明工具系列1. Docker 与 Docker-Compose部署与安装 环境系列1. Golang部署与安装 数据库系列1. PostgreSQL17.2源码部署与安装 Ubuntu 系统软件安装系列指导说明 工具系列 1. Docker 与 Docker-Compose部署与安装 链接 环境系列 1…...

队列(算法十三)
简介 几乎没有单纯之考察队列的,队列一般只作为一个辅助工具 队列常服务于BFS queue接口 1.N叉树的层序遍历 link: 思路: 队列 层序遍历即可 code /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node()…...

Cursor + Claude 4:微信小程序流量主变现开发实战案例
前言 随着微信小程序生态的日益成熟,越来越多的开发者开始关注如何通过小程序实现流量变现。本文将详细介绍如何使用Cursor编辑器结合Claude 4 AI助手,快速开发一个具备流量主变现功能的微信小程序,并分享实际的开发经验和变现策略。 项目…...
bat批量去掉本文件夹中的文件扩展名
本文本夹内 批量去掉本文件夹中的文件扩展名 假如你有一些文件,你想去掉他们的扩展名 有没有方便的办法呢 今天我们就分享一种办法。 下面,就来看看吧。 首先我们新建一个记事本,把名字改为,批量去掉本文件夹中的文件扩展名.txt 然…...

Keil开发STM32生成hex文件/bin文件
生成hex文件生成bin文件 STM32工程的hex文件和bin文件都可以通过Keil直接配置生成 生成hex文件 工程中点击魔术棒,在 Output 中勾选 Create HEX File 选项,OK保存工程配置 编译工程通过后可以看到编译输出窗口有创建hex文件的提示 默认可以在Output文…...

PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式
PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式 文章目录 PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式1. 查询效果2. 处理方式3. 再次查询 1. 查询效果 2. 处理方式 3. 再次查询...
Dynamics 365 Finance + Power Automate 自动化凭证审核
🚀 Dynamics 365 Finance Power Automate 自动化凭证审核 📑 目录 🚀 Dynamics 365 Finance Power Automate 自动化凭证审核1. 依赖 🔧2. 目标 🎯3. 系统架构 🏗️4. 凭证审批全流程 🛠️4.1 …...
图像处理、图像分析和图像理解的定义、联系与区别
1. 定义 图像处理(Image Processing) 图像处理是低层操作,主要针对像素级的图像数据进行加工,目的是改善图像质量或为后续分析做准备。 典型任务:去噪、增强(如对比度调整)、锐化、边缘检测、图…...

【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析
欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。 目录 引言Redisson基本信息Redisson网站 Redisson应用…...

2025年6月|注意力机制|面向精度与推理速度提升的YOLOv8模型结构优化研究:融合ACmix的自研改进方案
版本: 8.3.143(Ultralytics YOLOv8框架) ACmix模块原理 在目标检测任务中,小目标(如裂缝、瑕疵、零件边缘等)由于其尺寸较小、纹理信息稀疏,通常更容易受到图像中复杂背景或噪声的干扰,从而导致漏检或误检…...

利用qcustomplot绘制曲线图
本文详细介绍了qcustomplot绘制曲线图的流程,一段代码一段代码运行看效果。通过阅读本文,读者可以了解到每一项怎么用代码进行配置,进而实现自己想要的图表效果。(本文只针对曲线图) 1 最简单的图形(入门&…...

HA: Wordy靶场
HA: Wordy 来自 <HA: Wordy ~ VulnHub> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.128,靶场IP192.168.23.130 3,对靶机进行端口服务探…...