当前位置: 首页 > news >正文

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

  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驱动程序框架

相关文章:

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

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

1Hive概览

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

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)

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

IoTDB 常见问题 QA 第三期

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

RabbitMQ---消息确认和持久化

&#xff08;一&#xff09;消息确认 1.概念 生产者发送消息后&#xff0c;到达消费端会有以下情况&#xff1a; 1.消息处理成功 2.消息处理异常 如果RabbitMQ把消息发送给消费者后就把消息删除&#xff0c;那么就可能会导致&#xff0c;消息处理异常想要再获取这条消息的时…...

《鸿蒙Next旅游应用:人工智能赋能个性化与智能导览新体验》

随着鸿蒙Next的推出&#xff0c;旅游应用迎来了全新的发展机遇&#xff0c;借助人工智能技术能为用户带来更出色的个性化推荐和智能导览服务。 鸿蒙Next与人工智能融合优势 鸿蒙Next拥有强大的分布式能力和原生智能体验。其能打破设备界限&#xff0c;实现多设备协同&#xf…...

微信小程序获取当前页面路径,登录成功后重定向回原页面

&#x1f935; 作者&#xff1a;coderYYY &#x1f9d1; 个人简介&#xff1a;前端程序媛&#xff0c;目前主攻web前端&#xff0c;后端辅助&#xff0c;其他技术知识也会偶尔分享&#x1f340;欢迎和我一起交流&#xff01;&#x1f680;&#xff08;评论和私信一般会回&#…...

【9.2】Golang后端开发系列--Gin路由定义与实战使用

文章目录 一、Gin 框架路由的基本定义方式1. 简单路由创建2. 路由参数3. 查询参数 二、商业大项目中的路由定义和服务调用1. 路由模块化2. 路由组和中间件3. 中间件的使用4. 服务层调用5. 错误处理6. 版本控制7. 路由注册 一、Gin 框架路由的基本定义方式 1. 简单路由创建 使…...

【微信小程序】let和const-综合实训

let 和 const 都是用于声明变量的关键字&#xff0c;它们与传统的 var 关键字相比&#xff0c;有很多不同之处。 let 声明块级作用域变量&#xff0c;可再赋值&#xff1b;const 声明块级作用域常量&#xff0c;不可再赋值。 以下是它们的详细介绍&#xff1a; 一、基本概念…...

图匹配算法(涵盖近似图匹配)

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

java线程——Thread

java线程——Thread 基本步骤示例优劣总结 继承Thread类是Java中实现多线程的一种方式。使用时创建一个新的类&#xff0c;该类继承自java.lang.Thread&#xff0c;并重写其run()方法&#xff0c;在方法中定义线程执行的任务逻辑。 基本步骤 1、创建一个子类&#xff1a;定义一…...

MySQL8.0新特性

第十八章_MySQL8.0新特性 1.新特性概述 1. 数据库管理和存储 1.1 数据字典 特性: MySQL 8.0 使用统一的数据字典存储元数据&#xff08;如表、列、索引等&#xff09;&#xff0c;并将其存储在 InnoDB 表中。 优点 : 提升性能&#xff1a;减少对文件系统的依赖。 提高一致…...

Oracle EBS GL定期盘存WIP日记账无法过账数据修复

系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状 用户反映来源为“定期盘存”和类别为“WIP”的日记账无法过账,标准日记账的界面上的过账按钮灰色不可用。但是,在超级用户职责下,该日记账又可以过账,细心检查发现该业务实体下有二个公司段值15100和…...

【绝对无坑】Mongodb获取集合的字段以及数据类型信息

Mongodb获取集合的字段以及数据类型信息 感觉很LOW的一个数据仓工具seatunel&#xff0c;竟然不能自动读取mongodb的表结构信息&#xff0c;需要手工创建。 然鹅&#xff0c;本人对mongodb也是新手&#xff0c;很多操作也不知所措&#xff0c;作为一个DBA&#xff0c;始终还是…...

【Git版本控制器--1】Git的基本操作--本地仓库

目录 初识git 本地仓库 认识工作区、暂存区、版本库 add操作与commit操作 master文件与commit id 修改文件 版本回退 撤销修改 删除文件 初识git Git 是一个分布式版本控制系统&#xff0c;主要用于跟踪文件的更改&#xff0c;特别是在软件开发中。 为什么要版本…...

C++并发编程之无锁数据结构及其优缺点

在C并发编程中&#xff0c;无锁数据结构&#xff08;Lock-free Data Structures&#xff09;是指那些在实现中不使用互斥锁&#xff08;如std::mutex&#xff09;来保证线程安全的数据结构。相反&#xff0c;它们利用原子操作和内存模型来确保多线程环境下的正确性和高效性。下…...

Ubuntu上,ffmpeg如何使用cuda硬件解码、编码、转码加速

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

rclone,云存储备份和迁移的瑞士军刀,千字常文解析,附下载链接和安装操作步骤...

一、什么是rclone&#xff1f; rclone是一个命令行程序&#xff0c;全称&#xff1a;rsync for cloud storage。是用于将文件和目录同步到云存储提供商的工具。因其支持多种云存储服务的备份&#xff0c;如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…...

队列(算法十三)

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

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...