USB 驱动开发 --- Gadget 驱动框架梳理(一)

news2025/1/15 5:01:30

本文由 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 时就需要关注流程:

  1. 注册 UDC 驱动(USB Device Controller,作为**设备(Slave)**角色的 USB 控制器驱动);

    当前作为设备插入 Host 后会处于 attached 初始化状态( USB ch9 中定义)。此时既无功率消耗也法被使用(还不支持枚举)。

    因为当前数据线上的上拉未使能,所以即使 VBus 正常供电,Host 也无法感知到当前设备的存在(Host 通过设备是否上拉数据线探测设备)。

  2. 注册 Gadget 驱动;

    这些更高层级的 Fuction 驱动将调用 bind() 绑定到具体的 gadget 设备( struct usb_gadget 对象) 。有时这些 Function会在识别到 VBUS 后使能数据线上拉。

  3. 硬件驱动开始枚举;

    此时设备可以接受 USB powerset_address 请求,余下步骤由 gadget driver 接管。如果 dadget driver 在枚举前还未加载,忽略其后步骤直接跳转至步骤 7,执行 unbind()

  4. 实现 Gadget 驱动中 setup()方法;

    setup()方法将返回当前设备的:描述符、硬件接口和能力集等信息。如果硬件允许,甚至可以执行更复杂的设定和配置。

  5. 实现 set_configuration 请求的应答;

    Gadget 驱动需要在setup()方法中实现对主机set_configuration请求的应答(枚举的最后一步),使用所有在 Configuration 中使用的端点 和 默认 settings 中的接口;

  6. 实现数据收发;

  7. 实现 Gadget 驱动中 unbind()方法;

    当 Gadget 驱动卸载时,同时卸载 UDC 驱动;

注:

  1. 在设备连接到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

需知

  1. 每个 USB Function 都会在 config_groups 中定义期望用户配置的内容,可配置参考对应 Function 的实现文件:drivers/usb/gadget/f_*.c
  2. 主要阅读 USB 规范章节9 和 内核 gadget.rst 文档,以免忽略掉关键信息,如:端点自动配置,否则需要同时参考头文件与示例源码(如 Gadget Zere);

参考

  • 内核文档 linux_5.10/Documentation/usb/gadget_configfs.rst
  • 11_Gadget驱动程序框架

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276811.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字符串算法篇——字里乾坤,算法织梦,解构字符串的艺术(下)

文章目录 前言第一章&#xff1a;最长公共前缀1.1 题目链接&#xff1a;https://leetcode.cn/problems/longest-common-prefix/description/1.2 题目分析&#xff1a;1.3 思路讲解&#xff1a;1.4 代码实现&#xff1a; 第二章&#xff1a;最长回文子串2.1 题目链接&#xff1a…

计算机网络 笔记 数据链路层3(局域网,广域网,网桥,交换机)

局域网: LAN:在某一区域内由多台计算机互联成的计算机组&#xff0c;使用广播信道 特点&#xff1a; 覆盖范围有限&#xff1a;通常局限在几千米范围内&#xff0c;比如一栋办公楼、一个校园或一个工厂等相对较小的地理区域。 数据传输速率高&#xff1a;一般能达到 10Mbps…

istio-proxy oom问题排查步骤

1. 查看cluster数量 cluster数量太多会导致istio-proxy占用比较大的内存&#xff0c;此时需检查是否dr资源的host设置有配置为* 2. 查看链路数据采样率 若采样率设置过高&#xff0c;在压测时需要很大的内存来维护链路数据。可以调低采样率或增大istio-proxy内存。 检查iop中…

fast-crud select下拉框 实现多选功能及下拉框数据动态获取(通过接口获取)

教程 fast-crud select示例配置需求:需求比较复杂 1. 下拉框选项需要通过后端接口获取 2. 实现多选功能 由于这个前端框架使用逻辑比较复杂我也是第一次使用,所以只记录核心问题 环境:vue3,typescript,fast-crud ,elementPlus 效果 代码 // crud.tsx文件(/.ts也行 js应…

Apache JMeter 压力测试使用说明

文章目录 一、 安装步骤步骤一 下载相关的包步骤二 安装 Jmeter步骤三 设置 Jmeter 工具语言类型为中文 二、使用工具2.1 创建测试任务步骤一 创建线程组步骤二 创建 HTTP 请求 2.2 配置 HTTP 默认参数添加 HTTP消息头管理器HTTP请求默认值 2.3 添加 查看结果监听器2.4 查看结果…

计算机网络 (40)域名系统DNS

前言 计算机网络域名系统DNS&#xff08;Domain Name System&#xff09;是互联网的基础技术之一&#xff0c;它负责将人类可读的域名转换为计算机用来通信的数字IP地址。 一、基本概念 DNS的主要目的是将域名解析或翻译为IP地址&#xff0c;使得用户可以通过简单易记的域名来访…

本地服务器Docker搭建个人云音乐平台Splayer并实现远程访问告别烦人广告

前言 大家好&#xff01;今天我要给大家分享的是如何在Ubuntu上用Docker快速搭建高颜值无广告的某抑云音乐播放器Splayer的详细流程&#xff0c;并且结合cpolar内网穿透工具实现远程访问。如果你是音乐爱好者&#xff0c;经常需要在外办公或旅行&#xff0c;这个教程绝对能让你…

黑马linux入门笔记(01)初始Linux Linux基础命令 用户和权限 实用操作

B站 黑马程序员 的视频 BV1n84y1i7td 黑马程序员新版Linux零基础快速入门到精通&#xff0c;全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等 增强自控力 冥想慢呼吸绿色锻炼充分休息减少决策次数优先做重要的事情(早晨)融入强自控群控…

小程序组件 —— 31 事件系统 - 事件绑定和事件对象

小程序中绑定事件和网页开发中绑定事件几乎一致&#xff0c;只不过在小程序不能通过 on 的方式绑定事件&#xff0c;也没有 click 等事件&#xff0c;小程序中绑定事件使用 bind 方法&#xff0c;click 事件也需要使用 tap 事件来进行代替&#xff0c;绑定事件的方式有两种&…

UE5 使用内置组件进行网格切割

UE引擎非常强大&#xff0c;直接内置了网格切割功能并封装为蓝图节点&#xff0c;这项功能在UE4中就存在&#xff0c;并且无需使用Chaos等模块。那么就来学习下如何使用内置组件实现网格切割。 1.配置测试用StaticMesh 对于被切割的模型&#xff0c;需要配置一些参数。以UE5…

ue5 1.平A,两段连击蒙太奇。鼠标点一下,就放2段动画。2,动画混合即融合,边跑边挥剑,3,动画通知,动画到某一帧,把控制权交给蓝图。就执行蓝图节点

新建文件夹 创建一个蒙太奇MA_Melee 找到c_slow 调节一下速度 把D_slow拖上去 中间加一个片段 哎呀呀&#xff0c;写错了&#xff0c;我想写2 把这个标记拖过来&#xff0c;点击默认default 弄第二个片段 就会自己变成这个样子 把2这个标记拖到中间 鼠标左键&a…

《机器学习》之K-means聚类

目录 一、简介 二、K-means聚类实现步骤 1、初始化数据点、确定K值 2、通过距离分配数据点 3、更新簇中心 4、 迭代更新 三、聚类效果评价方式 1、轮廓系数的定义 2、整体轮廓系数 3、使用场景 4、优点 5、缺点 6、代码实现方法 四、K-means聚类代码实现 1、API接…

Wireshark抓包教程(2024最新版个人笔记)

改内容是个人的学习笔记 Wireshark抓包教程&#xff08;2024最新版&#xff09;_哔哩哔哩_bilibili 该课程笔记1-16 wireshark基础 什么是抓包工具&#xff1a;用来抓取数据包的一个软件 wireshark的功能&#xff1a;用来网络故障排查&#xff1b;用来学习网络技术 wireshark下…

Web开发(一)HTML5

Web开发&#xff08;一&#xff09;HTML5 写在前面 参考黑马程序员前端Web教程做的笔记&#xff0c;主要是想后面自己搭建网页玩。 这部分是前端HTML5CSS3移动web视频教程的HTML5部分。主要涉及到HTML的基础语法。 HTML基础 标签定义 HTML定义 HTML(HyperText Markup Lan…

RabbitMQ 的工作模式

目录 工作模式 Simple&#xff08;简单模式&#xff09; Work Queue&#xff08;工作队列&#xff09; Publish/Subscribe&#xff08;发布/订阅&#xff09; Exchange&#xff08;交换机&#xff09; Routing&#xff08;路由模式&#xff09; Topics&#xff08;通配…

备战蓝桥杯:树的存储与遍历(dfs和bfs)

树的概念 树的逻辑结构是树形结构&#xff0c;和我们之前的线性结构又不太一样了&#xff0c;是一种一对多的关系 树的结点分为根节点&#xff0c;叶子结点&#xff08;没有分支的结点&#xff09; 以及分支结点 从上往下看&#xff0c;每个结点都有0个或多个后继 从下往上…

超大规模分类(三):KNN softmax

传统的分类损失计算输入数据和每个类别中心的距离&#xff0c;来优化模型的训练。KNN softmax通过选择和输入数据最相关的top-K个类别&#xff0c;仅计算输入数据和top-K个类别中心的距离&#xff0c;以减小计算量。 KNN softmax首次诞生于达摩院机器智能技术实验室发表的SIGKD…

ubuntu官方软件包网站 字体设置

在https://ubuntu.pkgs.org/22.04/ubuntu-universe-amd64/xl2tpd_1.3.16-1_amd64.deb.html搜索找到需要的软件后&#xff0c;点击&#xff0c;下滑&#xff0c; 即可在Links和Download找到相关链接&#xff0c;下载即可&#xff0c; 但是找不到ros的安装包&#xff0c; 字体设…

项目实战——使用python脚本完成指定OTA或者其他功能的自动化断电上电测试

前言 在嵌入式设备的OTA场景测试和其他断电上电测试过程中&#xff0c;有的场景发生在夜晚或者随时可能发生&#xff0c;这个时候不可能24h人工盯着&#xff0c;需要自动化抓取串口日志处罚断电上电操作。 下面的python脚本可以实现自动抓取串口指定关键词&#xff0c;然后触发…

电脑分辨率调到为多少最佳?电脑分辨率最佳设置

电脑分辨率是指电脑屏幕上显示的像素点的数量&#xff0c;通常用水平和垂直方向的像素点数来表示&#xff0c;例如19201080。像素点越多&#xff0c;显示的内容就越清晰&#xff0c;但也会占用更多的系统资源和电力。那么多电脑分辨率多少最佳&#xff1f;以及电脑分辨率如何调…