linux usb驱动详解_usb传输中pipe与urb的关系-程序员宅基地

技术标签: LINUX篇  

一、USB驱动层次

usb采用树形拓扑结构,可分为主机侧与设备侧,每一条USB总线上只有一个主机控制器,负责协调主机与设备之间的通讯,设备不能主动的向主机发送任何消息,如下图所示
在这里插入图片描述
如上图所示,从主机侧视角去看,在linux驱动中,usb驱动处于最上层,主要表现为usb主机侧的功能具体实现(比如U盘,鼠标,usb camer等),其下为usb核心层,主要完成usb驱动管理以及协议处理,再下为usb主机控制器,主要提供usb控制器的API,维护整个usb系统,完成设备的热插拔,总线传输控制等,最下为具体的USB硬件实现。
从从机侧看,linux的usb分为3个层次,udc,gadget api与gadget驱动,udc为直接访问硬件,控制usb与主机之间的底层通讯,上下层提供硬件相关的操作接口,gadget api主要完成对udc层的一些封装,适配于上层的gadget 驱动层的需求,最上层为gadget驱动层,主要完成设备的运用表现(网络打印,usb mass storage)等特性,gadget的存在主要是为了gadget将运用于底层的硬件操作进行隔离,是的gadget驱动层不需要关系udc层的具体实现。

二:usb的枚举过程

还是口头叙述吧,懒得画图了,挺麻烦的 ~~ 哈哈哈 ~~~~~~
当主机检测到usb设备插入后,

1、主机发起读设备参数的请求,设备也设备描述配置符的方式回应。

在这里插入图片描述
上庙的设备描述符中,我们主要关心vid,pid,配置数目这三个参数,vid与pid在usb的driver中会进行table的对比,当匹配当table中有相对应的VID与PID参数后,才会执行driver->probe进行参数的相关处理。

2、主机再次发起配置描述请求,从机以配置描述符的协议进行回应、

在这里插入图片描述
这里主要关心接口的个数,在同一个配置下,可能存在很多的接口设备,所有这里的配置根据其下的接口描述符的个数进行修改。

3、主机最后发起接口描述符请求,从机回应接口描述符的配置描述、

在这里插入图片描述
这里主要关心端点数,接口类型,一个接口下可能会有多个端点,不同的断电对应不同的类型(短点0主要用于usb控制,所以我们的功能定制需要从短点1开始,比如端点1用于hid设备的out端口,端点2用于hid的in端口,端点3用于mass storage的out 端点,断点4用于mass storage的in端点,。。。),

4、最后到具体断点描述符,从机会将当前设备的端点描述符返回给主机、

在这里插入图片描述
自此,usb的枚举以及完成,主机会将usb的信息存储到driver->private数据接口,获取到的数据都存储到struct usb_interface中,在probe函数中将相关的信息提出出来,进行usb的core相关即可完成usb的枚举过程。

三、usb主机侧驱动

usb主控制器有三种规格,OHCI(open host controller interface),UHCI(universal host controller interface)和EHCI(enhanced host controller interface)。
嵌入式中常用的是OHCI,在主机侧,用hub_hcd来描述主机相关的相关信息,
在这里插入图片描述
usb_hcd主要描述了主机控制器的相关信息,同时usb_driver为控制usb主机的钩子函数(回调函数)。
在这里插入图片描述

四、usb从机侧驱动

usb从机可大概分为如下几个设备类、
1、音频设备类
2、通讯设备类
3、HID设备类
4、mass storage类
5、集线器设备类
usb的从机侧使用usb_Driver来描述一个从机usb设备驱动,数据结构如下、
在这里插入图片描述
在编写usb从机侧驱动时候,主要完成probe与diconnect函数,
probe函数的被调用如上枚举所言,只要当枚举到的VID与PID与我们驱动中的id_table成员中的相同,才会被执行,usb设备拔出后disconnect函数在设备被拔出时才会被执行。

五、urb

urb(usb request block)为usb输出传输的载体,用于描述usb传输数据包的基本信息,结构体如下、
在这里插入图片描述
transfer_flags表示当前usb的状态,只有当该状态处于idle时,数据才能被submit到usb的ENDPOINT的queue中。

5.1 urb的处理流程

5.1.1、分配urb

使用struct urb *usb_alloc_urb(int iso_pockets,int men_flags)来动态的分配一个urb资源。
iso_pockets表示分配的urb个数,为0则表示分配的urb是非实时性的,
usb_free_urb(struct urb *urb) 表示将分配的资源进行释放。

5.1.2、初始化urb

使用void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,void *transfer_buf,int buffer_length,usb_complete complete,void *context,int interval)来初始化中断urb,
urb表示需要初始化的urb的指针,dev表示需要发送这个urb的usb设备,pipe表示urb需要发送到的usb指定的端口(一般情况下使用usb_sndintpipe()或者usb_rcvintpipe()创建),transfer_buf是指向发送数据或者接受数据的缓冲区,buffer_len表示数据长度,complete表示传输完成之后需要执行的处理回调函数,xontext字面上是上下文(咱不理解),interval表示这个urb被调度的间隔。

5.1.3、提交urb

使用int usb_submit_urb(struct urb *urb,int mem_flag)将urb的数据提交到usb的core层,注意,在complete没有没调用之前,不要再次submit urb

建议:关于usb的相关,内核中已经提供了一个很好的usb框架文件在drivers/usb/usb-skeleton.c

举个栗子:见下一篇 usb emulate camera device。

**~~~~~~~~~~~~~~~~~~~~~废话太多了,再见 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/madannasf/article/details/102658630

智能推荐

大数据管理神器:Ambari自定义stack和服务二次开发详细教程_如何重写 ambari abstracttimelinemetricssink-程序员宅基地

文章浏览阅读7.2k次,点赞28次,收藏57次。背景Ambari是一个强大的大数据集群管理平台。在实际使用中,我们使用的大数据组件不会局限于官网提供的那些。如何在Ambari中集成进去其他组件呢?一、Ambari基本架构Ambari Server 会读取 Stack 和 Service 的配置文件。当用 Ambari 创建服务的时候,Ambari Server 传送 Stack 和 Service 的配置文件以及 Service 生命周期的控制脚本到 Ambari Agent。Agent 拿到配置文件后,会下载安装公共源里软件包(R._如何重写 ambari abstracttimelinemetricssink

JavaScript基础教程之学习过程中遇到的问题:字符串拼接_javascript 字符串拼接异常-程序员宅基地

文章浏览阅读402次。Write By Monkeyfly以下内容均为原创,如需转载请注明出处。该博客写于:2018年01月04日 11:46:52前提:今天在复习for循环的过程中,碰到这样一个问题——就是这个可恶的字符串的拼接问题,一直都看不懂,不知道到底是怎么实现的。中途看过好几次,每次都思考半天,最后还是没有看懂。话不多说,直接上代码:原始的p标签长这样:<p st..._javascript 字符串拼接异常

字符数组、字节数组实例化_byte[]实例化-程序员宅基地

文章浏览阅读2.3k次,点赞3次,收藏2次。import java.math.*;import java.util.*;public class Main { public static void main(String[] args) { // TODO Auto-generated method stub char[] C = {'0','1','2','3','4'}; String A = new Str..._byte[]实例化

GRADLE_USER_HOME用法指南-程序员宅基地

文章浏览阅读2.6k次。GRADLE_USER_HOME用法指南_gradle_user_home

请你努力成为一名优秀的软件工程师,拒绝做优秀的码农!_希望成为一名优秀的软件工程师?还是成为一名优秀的程序员?-程序员宅基地

文章浏览阅读2.7k次,点赞3次,收藏4次。最近,很多网友问我,怎么才能成为优秀的软件工程师,而不是优秀的码农?这个问题应该是最近这几年程序员的诉求了,估计每个程序员的理想都是做一个高大上的工程师,而不是只会Ctrl+C和Ctrl+V的码农。从我们踏入这个行业开始,我相信大多数人都是差不多的,都是学习编程基础,学习算法基础,学习各个大牛的骚操作,学习优秀框架或者项目中的各种写法等等。这个时候我们都是码农,是一个处于入门状态的程序员。当..._希望成为一名优秀的软件工程师?还是成为一名优秀的程序员?

军事仿真新纪元——全数据实时驱动视景仿真_万象视景-程序员宅基地

文章浏览阅读4.4k次,点赞2次,收藏28次。目前,世界各主要军事大国的军事装备信息化的步伐明显加快。而在信息复杂多样且多变的现代战争背景下,不仅军用仿真技术作为未来战争至关重要的一环节,信息更成为了胜负的决定因素,战场信息融合技术至关重要。只有依靠完备的信息融合有效感知战场态势,才能及时准确地判断战场动态、威胁估计以及作战效能等关键信息,最大程度支撑有效决策。_万象视景

随便推点

[EndNote]关于导入CAJ文献_endnote为啥导入不了caj-程序员宅基地

文章浏览阅读2.9w次,点赞25次,收藏55次。[EndNote]关于导入CAJ文献 EndNote在导入一些PDF格式的文献时,有时会发生不能自动填充信息的情况。这种情况产生的原因是EndNote在这篇PDF格式文献当中,不能查询到DOI。 对于中国知网上面的学位论文,先不必说EndNote导入中文文献时对文献信息的识别能力不足,单就学位论文的CAJ格式,就能给导入工作带来一些头疼的问题。注意:以下过程是在校_endnote为啥导入不了caj

微信小程序开发 开启_小程序别人把我加入开发者模式-程序员宅基地

文章浏览阅读1.5w次,点赞16次,收藏120次。小程序是运行在微信环境中,而网页是运行在浏览器环境中。由于运行环境不同,所以小程序中,无法调用DOM和BOM的API。但是,小程序中可以调用微信环境提供的各种API,例如地理定位,扫码,支付。网页的开发模式:浏览器+代码编辑器。而小程序有自己的一套标准开发模式:登录网址https://mp.weixin.qq.com/,注册一个个人的账号,填写好相关的信息,我们的账号就注册好了。获取小程序的APPID。在上边的网址完成注册以后,我们在页面中可以找到我们的小程序的APPID展示在如图所示的位置。微信_小程序别人把我加入开发者模式

Zynq+zcu106学习随笔2-VCU硬件逻辑搭建_vcu 参考时钟-程序员宅基地

文章浏览阅读5.4k次,点赞2次,收藏10次。 内容主要来自官方手册pg252-vcu。 vcu的逻辑电路还是还是很好理解,以下只记录觉得重要的部分。 1.添加Zynq UltraScale+ VCU IP以及Zynq UltraScale+ MPSoC到block design。 2.选择PL1 clock频率为333MHz,使能中断以及4个PS-PL从接口AXI HP。 3.剩下的连接如下图值得注意的是pll..._vcu 参考时钟

Unity3D与Android互相调用踩坑总结_com/unity3d/player/unityplayer-程序员宅基地

文章浏览阅读1.2w次,点赞4次,收藏13次。1.引入unity的 classes.jar包 本人安装unity-5.6.1版本,目录为D:\Program Files\unity-561\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar 若直接将classes.jar导入AndroidSt..._com/unity3d/player/unityplayer

VC--CAnimateCtrl 动画控件的学习_mfcanimation control-程序员宅基地

文章浏览阅读5.3k次。动画控件  Windows 95支持一种动画控件(Animate control),动画控件可以播放AVI格式的动画片(AVI Clip),动画片可以来自一个AVI文件,也可以来自资源中。合理地使用动画控件,可以使程序的界面更加形象生动。11.5.1 动画控件的使用MFC的CAnimateCtrl类封装了动画控件,该类的Create成员函数负责创建动画控件,其声明为:BOO_mfcanimation control

起死回生——在 Linux 中使用 supervisor 管理后台进程_unix:///usr/local/supervisor/tmp/supervisor.sock r-程序员宅基地

文章浏览阅读1.1k次。在 Linux 中运行后台进程运行有很多方法,例如 nohup,screen 等。但如果想要可靠地在后台运行一个服务程序,就需要把它做成 daemon,最好还能监控进程状态,在意外结束时能自动重启。supervisor 就是用 Python 开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。一、安装以 CentOS 为例。先安装 easy-installyum install python-setuptools然后用 easy-i_unix:///usr/local/supervisor/tmp/supervisor.sock refused connection