Gadget驱动程序框架

news2025/1/9 20:32:06

Gadget驱动程序框架


文章目录

  • Gadget驱动程序框架
  • 参考资料:
    • 一、 怎样理解Gadget框架
    • 二、从硬件软件角度理解Gadget框架
      • 2.1 底层硬件操作_UDC驱动
      • 2.2 上层软件操作
    • 三、 从构造描述符的角度理解Gadget框架
  • 致谢


参考资料:

  • Linux下USB gadget设备详解
  • Linux usb gadget框架概述
  • USB设备驱动程序-USB Gadget Driver(二)
  • usb gadge驱动设计之我是zero
  • Linux-USB驱动笔记(四)–USB整体框架
  • USB gadget设备驱动解析
  • 调试软件:USB view 、bushound 、及一些硬件USB信号分析仪
  • 可以用wireshark+usbmon捕捉usb协议数据包。

一、 怎样理解Gadget框架

USB协议是主从结构:

在这里插入图片描述

我们编写USB设备驱动程序时,主要是:

  • 读取设备的各类描述符,比如endpoint描述符,得到端点号
  • 使用底层USB Host Controller驱动程序提供的API函数,从endpoint上读写数据

那么要基于Gadget驱动框架模拟一个USB设备时,endpoint的数据传输能力是底层的USB Device Controller驱动提供的,我们要做的就是:

  • 提供各类设备描述符
  • 使用底层USB Device Controller驱动程序提供的API函数,从endpoint得到数据、反馈数据

Gadget的含义是"小器件",在Linux的USB系统中,它表示"usb device"。Gadget驱动程序,就是用来模拟USB Device。对于真实的USB Device,它有两大要素:

  • 怎么表示自己?
    • 每个USB Device都有1个设备描述符
    • 都1个或多个配置描述符
    • 每个配置描述符里面有1个或多个接口描述符
    • 每个接口描述符里面有0个多个端点描述符
  • 怎么进行数据传输?
    • 通过端点进行传输
    • 有端点的操作函数
      在这里插入图片描述

在学习过程中,记住这几个要点非常有帮助:

  • 各类描述符的构造
  • USB Host获得Gadget各类描述符的过程
  • 数据传输的流程

二、从硬件软件角度理解Gadget框架

USB传输的核心是endpoint,使用endpoint可以收发数据。在endpoint之上,就可以模拟USB串口、USB触碰屏、USB摄像头。基于这个角度,Gadget框架可以分为两层:

  • 底层endpoint操作
  • 上层模拟各类USB设备
    在这里插入图片描述

2.1 底层硬件操作_UDC驱动

对于底层endpoint的代码,需要从UDC驱动开始分析:

  • IMX6ULL的代码:Linux-4.9.88\drivers\usb\chipidea\ci_hdrc_imx.c

    ci_hdrc_imx_probe
        ci_hdrc_add_device
        	pdev = platform_device_alloc("ci_hdrc", id);
    
    
    // Linux-4.9.88\drivers\usb\chipidea\core.c
    static struct platform_driver ci_hdrc_driver = {
    	.probe	= ci_hdrc_probe,
    	.remove	= ci_hdrc_remove,
    	.driver	= {
    		.name	= "ci_hdrc",
    		.pm	= &ci_pm_ops,
    	},
    };
    
    ci_hdrc_probe
        	ret = ci_hdrc_gadget_init(ci);
    		    	udc_start    		
    

在这里插入图片描述

2.2 上层软件操作

模拟各类USB设备时,软件怎么分层?以访问设备、获取描述符为例:

  • Host要分配地址、把地址发送给设备:不管要模拟什么设备,Gadget都必须接收地址,这部分由usb_gadget(硬件相关的驱动程序)实现
  • Host要读取各类描述符,这些描述符是由上层的驱动程序提供的
  • 怎么把上层的描述符通过底层的usb_gadget传回给Host?还需要一个中间层。Host获取描述符时,方法是固定、通用的,这些方法可以由内核统一提供,这就是:usb_gadget_driver。

所以,从获取描述符的角度看看,上层软件至少分为2层:

  • usb_gadget_driver:实现一些通用的USB访问方法,比如Host访问描述符时,由usb_gadget_driver提供
  • 在这上面提供各类描述符,实际上,描述符的提供还可以分为两层:
    • 设备描述符、配置描述符:由程序员决定,由usb_composite_driver提供
    • 接口描述符、endpoint描述符:由内核事先实现的、常用的function driver提供

软件层次可以进一步细化,如下图:

在这里插入图片描述这涉及2个结构体:

  • usb_composite_dev:它里面汇集有各类描述符、有一个usb_funciton链表(实现数据传输)

    struct usb_composite_dev {
    	struct usb_gadget		*gadget;
    	struct usb_request		*req;
    	struct usb_request		*os_desc_req;
    
    	struct usb_configuration	*config;
    
    	/* OS String is a custom (yet popular) extension to the USB standard. */
    	u8				qw_sign[OS_STRING_QW_SIGN_LEN];
    	u8				b_vendor_code;
    	struct usb_configuration	*os_desc_config;
    	unsigned int			use_os_string:1;
    
    	/* private: */
    	/* internals */
    	unsigned int			suspended:1;
    	struct usb_device_descriptor	desc;
    	struct list_head		configs;
    	struct list_head		gstrings;
    	struct usb_composite_driver	*driver;
    	u8				next_string_id;
    	char				*def_manufacturer;
    
    	/* the gadget driver won't enable the data pullup
    	 * while the deactivation count is nonzero.
    	 */
    	unsigned			deactivations;
    
    	/* the composite driver won't complete the control transfer's
    	 * data/status stages till delayed_status is zero.
    	 */
    	int				delayed_status;
    
    	/* protects deactivations and delayed_status counts*/
    	spinlock_t			lock;
    
    	/* public: */
    	unsigned int			setup_pending:1;
    	unsigned int			os_desc_pending:1;
    };
    
  • usb_udc:UDC的本意是"usb device controller",usb_udc结构体里面有usb_gadget(表示UDC本身)、usb_gadget_driver()

    struct usb_udc {
    	struct usb_gadget_driver	*driver;
    	struct usb_gadget		*gadget;
    	struct device			dev;
    	struct list_head		list;
    	bool				vbus;
    };
    

三、 从构造描述符的角度理解Gadget框架

假设你要模拟一个USB设备,

  • 这个USB设备含有厂家信息:它记录在设备描述符里,所以设备描述符应该由你提供
  • 这个芯片可能有多种配置,这也是由你决定,所以配置描述符应该由你提供
  • 某个配置下多个接口,接口就是功能,Linux内核里事先提供了很多功能的驱动程序,所以:接口描述符是内核提供的
  • 某个接口下需要什么端点,也是内核里各类功能的驱动程序提供的

以zero.c为例:

  • 配置1:loopback,Host写数据给它,就可以读出原样的数据
  • 配置2:sourcesink,Host写数据给它(它只是记录下数据),Host还可以读数据(读到的都是0)

从下到上涉及这些文件:

在这里插入图片描述

阅读源码时,入口函数是usb_composite_probe(&zero_driver)

在这里插入图片描述

函数调用过程中主要的函数如下,重点关注"xxx_bind"函数,可以认为bind就是初始化的意思:

  • usb_composite_probe
  • composite_bind
  • zero_bind
  • sourcesink_bind/loopback_bind

在这里插入图片描述

深入解读描述符的构造过程,可以得到下面的图:

  • 构造出一个usb_composite_dev结构体
  • 它把各层串联起来,里面构造有设备描述符、配置描述符、接口描述符、端点描述符
    在这里插入图片描述

致谢

以上笔记源自韦东山老师的视频课程,感谢韦老师,韦老师是嵌入式培训界一股清流,为嵌入式linux开发点起的星星之火,也愿韦老师桃李满园。聚是一团火,散是满天星!

在这样一个速食的时代,坚持做自己,慢下来,潜心琢磨,心怀敬畏,领悟知识,才能向下扎到根,向上捅破天,背着世界往前行!
仅此向嵌入行业里的每一个认真做技术的从业者致敬!


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

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

相关文章

Linux常用命令——quotaon命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) quotaon 激活Linux内核中指定文件系统的磁盘配额功能 补充说明 quotaon命令用于激活Linux内核中指定文件系统的磁盘配额功能。执行quotaon指令可开启用户和群组的才磅秒年空间限制,各分区的文件系统…

STM32——I2C外设总线

文章目录一、I2C外设简介二、I2C框图三、I2C基本结构四、主机发送五、主机接收六、I2C的中断请求七、软件/硬件波形对比八、硬件I2C读写MPU6050电路设计关键代码状态监控函数一、I2C外设简介 STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条…

Go语言jwt无感刷新以及解决SSO单点登录限制

前言 为什么使用JWT? Jwt提供了生成token以及token验证的方法,而token是一种不用存储在服务端,只需要由用户携带即可实现认证的一种方式。在介绍JWT之前,我们也应该先了解cookie和session。 Cookie和Session 为每一位用户设定…

PLSQL Developer 代码助手卡顿优化

支持付费优化 原因分析 代码助手卡顿来源于(不考虑网络和软件版本等影响) A.从已连接的数据库的数据字典中,读取该表的列信息B.将读取到的列信息返回到plsql编辑器,并进行字符处理,然后显示如何优化B 这个勾勾是维…

【GPLT 二阶题目集】L2-034 口罩发放

为了抗击来势汹汹的 COVID19 新型冠状病毒,全国各地均启动了各项措施控制疫情发展,其中一个重要的环节是口罩的发放。 某市出于给市民发放口罩的需要,推出了一款小程序让市民填写信息,方便工作的开展。小程序收集了各种信息&#…

redis的配置文件

目录 介绍 1. 单位的设置方式 2. 可以包含其他文件内容 3. 网络配置相关 4. 通用 5. 安全 6. 限制 redis的配置文件名为redis.conf,一般会安装在/etc目录下。 如果找不到该文件可以使用find命令查找。 find . -name redis.conf 介绍 1. 单位的设置方式 只支持字…

client-go监听apiserver,监听http2逻辑分析

前言 最近做项目,需要写一个controller(k8s的插件),需要从k8s的apiserver取数据,就用了自带的client-go,但是client-go是怎么从apiserver获取数据的一直没有研究过,只是看网上,看官…

Hudi系列10:Flink流式插入

文章目录流式插入概述一. Hudi流式插入案例1(datagen)1.1 准备工作1.2 源端准备1.3 目标端表准备1.4 ETL准备1.5 数据验证1.6 通过SPARK SQL查看数据二. Hudi流式插入案例2(Kafka)2.1 准备工作2.2 源端准备2.2.1 创建kafka的topic (hudi_flink)2.2.2 Flink SQL Client消费kafka…

卷积神经网络中的权值共享和局部连接

卷积神经网络中的权值共享和局部连接卷积神经网络的两大特点权值共享全连接卷积神经网络的两大特点 权值共享,就是输入一张图,用一个filter去扫这张图,filter里面的数就叫权重,这张图每个位置都是被同样的filter扫的,…

Flink官方例子解析:WordCount

1. 简介 今天介绍的是官方子项目flink-examples-streaming里面的WordCount例子。 WordCount ,中文:单词统计,是大数据计算常用的例子。 2. WordCount需要实现的功能 监听指定目录下的文件,读取文件的文本内容;如果未…

Python继承机制及其使用

Python 类的封装、继承、多态 3 大特性,前面章节已经详细介绍了 Python 类的封装,本节继续讲解 Python 类的继承机制。继承机制经常用于创建和现有类功能类似的新类,又或是新类只需要在现有类基础上添加一些成员(属性和方法&#…

RASP技术进阶系列(三):重大漏洞自动化热修复

在上篇文章《RASP技术进阶系列(二):东西向Web流量智能检测防御》中提到,在企业日常安全运营以及HW场景下,应用漏洞攻击应急响应和恶意流量溯源分析是安全团队的重点工作。在恶意流量溯源方面,指向攻击来源的…

趁着你对象吃泡面的功夫,我修复了误删除的文件

文章目录前言一. linux下文件删除原理1.1 文件删除原理的简单介绍1.2 测试inode号是否容易被覆盖?二. 实验测试过程2.1 实验环境:2.2 新增一块硬盘测试2.3 对磁盘分区2.3.1 分区(使用fdisk分区)2.3.2 格式化,创建目录挂…

网络化多智能体系统的共识与合作

在所有参与者之间提供快速协议和团队合作的算法通过自组织网络系统实现有效的任务执行。By Reza Olfati-Saber, Member IEEE, J. Alex Fax, and Richard M. Murray, Fellow IEEE小于 翻译摘要:本文提供了一个理论框架,用于分析多智能体网络系统的共识算法…

Linux文件与目录的查看:ls

前言 ls作为我们在Linux系统中最常用的命令,因为我们常常需要去知道文件或是目录的相关信息,但我们Linux的文件所记录的信息实在是太多了,ls也没有需要全部都列出来,所以,当我们执行ls命令时,默认显示的只…

【数据结构】基础:二叉搜索树

【数据结构】基础:二叉搜索树 摘要:本文为二叉树的进阶,主要介绍其概念与基本实现(递归与非递归),再介绍其应用,主要介绍内容为KV模型。最后为简单的性能分析。 文章目录【数据结构】基础&#…

【数据结构】1.1 数据结构的研究内容

文章目录数据结构的研究内容数据结构研究的内容小结数据结构的研究内容 早期,计算机主要用于数值计算: 首先,分析问题、提取操作对象,然后,找出操作对象之间的关系,用数学语言加以描述,建立相应数学方程。…

Java日志门面技术 SLF4J

文章目录背景SLF4J概述切换日志框架实际应用配合自身简单日志实现(slf4j-simple)配置logback日志实现配置Log4J日志实现(需适配器)配置JUL日志实现(需适配器)添加slf4j-nop依赖(日志开关)桥接旧的日志实现框架背景 随着系统开发的进行,可能会更新不同的日志框架&am…

TF数据流图图与TensorBoard

2.1 TF数据流图 学习目标 目标 说明TensorFlow的数据流图结构应用 无内容预览 2.1.1 案例:TensorFlow实现一个加法运算 1 代码2 TensorFlow结构分析2.1.2 数据流图介绍 2.1.1 案例:TensorFlow实现一个加法运算 2.1.1.1 代码 def tensorflow_demo():&…

CMMI对企业有什么价值,如何高效落地?

1、获得权威认证 CMMI是全球性软件与系统工程行业的唯一权威认证,是对企业软件研发与能力服务的认可。 CMMI企业价值 CoCode项目管理全面支持CMMI3-5级高效落地​ 2、降本增效,提高企业能力。 CMMI对软件开发过程进行规范化梳理,保证软…