你好,我想修改zero驱动,我的需求是设备通过usb与上位机【tcp zerowindow 原因系统】进行音频数据的传输。

后使用快捷导航没有帐号?
查看: 6010|回复: 5
STM32通过USB向上位机发送数据 上位机无法接收到
在线时间490 小时
威望9087分
芯币12354枚
TA的帖子TA的资源
五彩晶圆(高级), 积分 9087, 距离下一级还需 913 积分
五彩晶圆(高级), 积分 9087, 距离下一级还需 913 积分
我的STM32 是利用ST官方的Mass_Storage修改的端点1是IN& 端点2是OUT& 这两个端点都是批量传输端点
安装驱动后& 我用Bus Hound 5向其发送数据 STM32能顺利接收void EP2_OUT_Callback(void){& PMAToUserBufferCopy(Bulk_Data_Buff, ENDP2_RXADDR, 64);& SetEPRxValid(ENDP2);
& UserToPMABufferCopy(sendBufferr, GetEPTxAddr(ENDP1), 64); & SetEPTxCount(ENDP1, 64);& SetEPTxValid(ENDP1);}但我试图通过& UserToPMABufferCopy(sendBufferr, GetEPTxAddr(ENDP1), 64); & SetEPTxCount(ENDP1, 64);& SetEPTxValid(ENDP1);来向上位机发送数据 但Bus Hound 5中看不到有任何来自STM32的数据所以想问一下这是什么原因 谢谢
一个为理想不懈前进的人,一个永不言败人!
欢迎光临网上店铺!
&&&&&&&&&&
在线时间1346 小时
威望77294分
芯币14182枚
TA的帖子TA的资源
回复 楼主 eeleader 的帖子
目前 看不出来哪里错误了,ENDP1的初始化正确吧!
处处留心皆学问!
在线时间14 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
如果驱动程序与你上面用到的端点是一样的,而且你的初始化是正确 的那么应该是没有问题的!
在线时间41 小时
TA的帖子TA的资源
一粒金砂(中级), 积分 62, 距离下一级还需 138 积分
一粒金砂(中级), 积分 62, 距离下一级还需 138 积分
沾下楼主的光,在这里问一个问题~
我也是使用STM32写的自定义USB HID,但是安装时电脑右下角显示该设备在安装时出现问题,可能无法使用。电脑的设备管理器里面在“USB人体学输入设备”的图标上面显示一感叹号,在此问下是什么原因
在线时间288 小时
威望1955分
芯币4630枚
TA的帖子TA的资源
纯净的硅(高级), 积分 1955, 距离下一级还需 45 积分
纯净的硅(高级), 积分 1955, 距离下一级还需 45 积分
回复 4楼 zhengli880209 的帖子
电脑上应该是需要装个驱动.我还没试过usb.…你可以搜索下usb教程贴
在线时间160 小时
TA的帖子TA的资源
一粒金砂(高级), 积分 315, 距离下一级还需 185 积分
一粒金砂(高级), 积分 315, 距离下一级还需 185 积分
USB HID不需要电脑驱动的。
荣誉会员勋章
曾经的版主且威望大于2000,或对EEWORLD论坛有突出贡献的坛友
Powered by
逛了这许久,何不进去瞧瞧?博客访问: 260869
博文数量: 109
博客积分: 2258
博客等级: 大尉
技术积分: 932
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
来源:Linux社区& 作者:smilestone322本篇文章来源于 Linux公社网站()& 原文链接:
很早以前就想写点东西来总结windows 下usb开发和linux 下usb 驱动开发的异同了,今天主要从相同点和不同点进行讲解吧,对于两个平台下usb驱动开发,usb协议是相同的,咱们先从usb协议开始谈起,然后讲解windows下usb驱动开发的方法,主要介绍3种方法,dw 3.2+DDK;WDM下DDK开发和WDF下KMDF Usb驱动开发。
虽然dw已经被WDF赶下台了,但是我这里还是要讲讲dw开发驱动程序的东西,因为我的第一个驱动程序就是采用dw+ddk 2600开发的,至今我都记得当时开发驱动的情景,那种感觉真的希望神仙来指路啊。在开发第一个usb驱动程序之前我没有做过驱动的经验,甚至都不知道,驱动是干嘛的。但是临危受命,只有往前冲,没有回头路,因为回头就意味着枪毙(被辞职,08年的流行语,被)。没有回头路,那就往前走呗。
没有文档,没有原理图,甚至连数据手册都没有给我,就跟我讲了讲这个项目要做什么工作。当时一片茫然,真希望神仙来指路。拿到项目需求,其实是口头上的,呵呵,没有 一行字的文档。没有办法,一边学习,一边做需求分析,请教做过这些事情的同事和同学。到csdn和国外的论坛发帖狂问。一边搜开发驱动的工具,比如ddk,dw等等,那个时候国内还没有人用WDF模型做驱动开发。
那时的水平真的就是一个字来形容,菜。搜了一大通,感觉还是用dw 吧,感觉还是挺比较容易用,选用了开发工具后,就不分昼夜的学习。有时工作到凌晨2点,雷锋同志说的好,时间就像乳沟,要挤还是有的,呵呵,中午也不休息了,干活,干活,干活。一个星期过去了没有一点进展,2个星期过去了,终于把需求搞明白了,这个时候,对dw+ddk+vc的开发环境也搭起来了,也买了几本书,每一本书都讲到关键的地方没了,呵呵,真气人啊。
神阿,救救我吧!老大每天都过来问一下,有什么进展了吗?唉,我每次都对着他笑笑,还好,老大还对我不错,要我好好的静下心来,理一理思路。当时他也帮我找找资料,但是后面证明都是没用的,呵呵,因为公司没有人做过usb驱动。
3个星期过去了,柳岸花明又一村,我终于可以往硬件发送控制命令了,但是硬件还没有给我回送数据。没办法,用bus hound 一抓包,看到有数据了,我兴奋了一吧。呵呵,终于看到了希望,看到了未来,那时候感谢党,感谢毛主席,心情澎湃了一个小时。
实验证明,希望越大,失望越大,我以为就要做出来了,但是没想到还是万里长征走完第一步,后面的路还很长,我们必须保留……。我后面就去写函数去读端点中的数据,但是一直都读不到,呵呵,调啊 调啊。希望会有的,面包会有的,我一直坚信自己,从来不怀疑自己的能力。
第4个星期的早上,我早早的就去上班了,还是坐在那里,安安静静的写代码,调程序,也不和别人说话,不断地看别人的代码,看dw上的例子,看ddk的例子。当时一个星期比我一个月看的东西还要多,总结一句话,静下心来看源码,源码就会像看故事会那样简单。第4个星期的星期3了。也是上午快吃中饭的时候,终于看到硬件不断的给我传数据了,我还是用bus hound抓包,数据是那么的正确,当时的心情是怎样的激动,我无法形容,现在都过去几年了,都清楚地记得,我当时吼了一声,公司的人都看着我,现在回想起来是那么的幼稚。一个驱动程序,一段不寻常的经历,让我想起一句话:没有压力,没有动力,不经历风雨怎能见彩虹。
以上就是我第一次做usb驱动的一段经历,那时流行采用dw+ddk开发驱动程序,现在开发dw软件的公司都停止开发了,多么可惜的一件事情啊,这么优秀的软件,这么易用的软件,就这样被淘汰了,最终将它的版本定格在3.2。但是国内现在还有一大拨人在使用dw开发驱动程序,我看网上有本书,叫圈圈教你玩usb,就是采用dw开发驱动的,粉丝还挺多的,证明dw还有一定的生命力,还有一定的市场,所以本文还是会讲到怎样采用dw做驱动开发。
虽然现在正规的商用软件都不采用dw了,因为它的版本不更新,出了bug都没有人维护了。但是用dw做研究还是挺不错的。开场白说完了。开始进入正题,本文的主要安排如下:首先介绍usb通信协议,同时介绍一款最简单的usb芯片,68013。然后接着讲解windows下的usb驱动开发。采用3种不同的方法开发usb驱动程序,最后讲解linux下usb驱动开发,当然两个平台开发usb驱动的异同点是贯穿全文的,不然就跑题了。
作为驱动开发人员,不需要你有多高的算法基础,因为驱动里面的算法都是基本的算法,只要你熟悉原理图,熟悉datesheet,然后学习DDK,WDK下自带的例子,就可以轻松上手,对于linux,同样也是这样,还有linux的源码是公开的,你可以编译,安装,就可以在/usr/src看到各种驱动的源码了,学习这些源码,不但可以提高我们的编程水平,而且使得我们写的驱动更有健壮性。下面我讲解的思路也是这样的,先将usb协议,在讲讲cy7c68013芯片,然后讲解dw,ddk,wdk下的例子,只要将这些例子都学会,可以说,你具有写驱动的水平了,至于要成为高手,就必须多总结经验,多积累经验。
1 Usb通信协议
Usb驱动程序是PC中最主要的设备驱动程序,usb总线协议比PCI总线协议复杂,但是对于我们usb驱动开发者来说,并需要对usb通信协议每个东东都搞清楚,比如usb物理层协议,usb传输层协议等等,只要了解即可。
1.1)usb总线协议
USB最多支持127个外设,但是考虑到Hub的情况,连接的外设没有这么多,因为Hub也当成了外设,对于每个PC都有一个或多个Host控制器设备,该Host控制器和一个根Hub作为一个整体,跟Hub下可以连接多个Hub,这样形成级连设置,Host分别有2种驱动,一种是1.0,另一种是2.0,分别对应着USB协议1.0和USB协议2.0。虽然存在Hub,但是对于用户来说,这些都是透明的,就好象USB设备和直接连接到USB Host控制器上一样。当USB设备插入和删除都会发电信号给系统,这样可以枚举USB设备。
USB 的连接模式是Host和Devcie的连接模式,所有的请求必须是Host向Device发出,这就使Host端设计相对复杂,而Device端设计相对简单。在USB的通信中,可以看成是一个分层的协议。分为三个层次,即最底层USB总线接口层、USB设备层、功能通信层,如图1-1所示。
图1 usb逻辑和控制图
对于每个USB设备,都有一个或者多个的接口(Interface),每个Interface都有多个端点(Endpoints),每个端点通过管道(Pipes)和USB Host控制器连接。每个USB设备都会有一个特殊的端点,即Endpoint0,它负责传输设备的描述信息,同时也负责传输PC与设备之间的控制信息,如图1-2所示:
图1-2 USB 管道与端点
现在讲讲usb传输吧,Usb传输一般分为3个部分:令牌传输,数据传输,握手阶段,传输的方式有4种:控制传输,这个是传输控制信息,Bulk传输,这个是批处理传输,中断传输,同步传输。
对于控制传输来说,一般采用端点0进行控制传输,主要用来配置设备、获取设备信息、发送命令或者获取设备的状态报告。总线驱动程序为它保留了10%的带宽,使得控制传输能在1ms内完成。
对于控制端点:
端点所传的数据净负荷的长度必须小于或等于其wMaxPacketSize,当传输的数据大于wMaxPacketSize时,必须分多次进行传送。除最后一次传输外,其它都应达到最大长度。最后一次传输含最后剩下的数据。控制传送的数据阶段结束的标志如下:
·已传了由Setup阶段指定的数据量。
·传了一个数据包,它的长度为0或它的数据区长度小于最大长度。
中断传输:主要用来以一个固定的速度传送少量的数据,对于中断传输,系统会预留带宽。
Bulk传输:用来传送大量的数据,数据传送是可靠的,当总线上的空间不足以发送整个批量包时,会划分成多个包传送。缺点:是当有多个usb设备时,bulk传输,由于系统没有给他预留usb带宽,有可能被其它以中断或同步传输的usb设备抢占带宽,造成bulk传输的设备不能正常使用。
Bulk传输也像控制传输一样,端点所传的数据净负荷的长度必须小于或等于其wMaxPacketSize,当传输的数据大于wMaxPacketSize时,必须分多次进行传送。除最后一次传输外,其它都应达到最大长度。最后一次传输含最后剩下的数据。控制传送的数据阶段结束的标志如下:
·已传了由bulk传输指定的数据量。
·传了一个数据包,它的长度为0或它的数据区长度小于最大长度。
这里要注意了,硬件设计的时候,主要必须能给PC端传送short包,什么意思呢,因为usb bulk传输结束的条件有2个,当数据没有全部传送成功时,我们可以根据short包或zero包来判断这次传输的结束。
同步传输:也叫等时传输,用来传送大量不可靠传输,不保证数据的到达,但能保证恒定的数据流,一般用于摄像机等视频设备的数据采集。
Usb协议中除了上面的讲解的内容,还有usb描述符,usb描述符包括,usb设备描述符,usb配置描述符,usb接口描述符和usb端点描述符。Usb设备描述符长度为18个字节,主要用来枚举设备使用,其中重要的字节是PID/VID,因为它可以用来枚举设备。还有一个字节不得不将,也是面试时,考官容易考试的,SerialNumber字段,各位看官看好了,估计你不知道这个字节的作用了吧。你做usb驱动有过在一个usb口安装usb驱动后,到另外一个口还提示你安装驱动的经验吗,呵呵,这就是SerialNumber了,如何设置,就不说了。各位看官自己研究吧。
Usb配置描述符和usb接口描述符都不重点讲解了,它们的长度都是9个字节,下面在讲讲usb端点描述符,usb端点描符的长度为7个字节,其中重要的字段为端点地址,如果是0x82表示端点是一个端点号为2的IN端点,而0x02表示一个端点号为2的OUT端点。还有bmAttributes的低2位表示端点的类型,如0表示控制端点,而1表示同步端点,2表示bulk端点,3表示中断端点。还有一个就是wMaxpacketsize,不用我说,大家看到这个知道它表示什么意思了,对了,就是表示该端点最大的传输size,如果总的传输大小比这个大,就必须分割成多个块进行传输,每个块的size为wMaxpacketsize,最后剩余的数据放在最后一个块里面输出。剩下的就是bInterval字节的,它只对同步和中断端点有效,对于中断端点,该值得范围为1-255ms,代表2次巡检间的最大时间间隔。对于同步端点,固定为1,表示每隔一个帧周期(1ms)都应该巡检。
1.2)68013 芯片资料
Cypress 68013的芯片数据手册在这里不一一列出了,具体的资料大家给到它的官网上下载,下面是56脚CY7C68013A接口图:
l&&&& 单片集成USB2.0收发器、SIE和增强型8051微处理器。
l&&&& 软件:从内部RAM运行的8051程序来自于:
——通过USB接口下载,或
——从EEPROM下载
——外部储存器设备(仅对128脚配置)
l&&&& 4个可编程的批量/中断/同步端点
——缓冲器可选:双倍、三倍和四倍。
l&&&& 8位或16位外部数据接口。
l&&&& GPIF
——允许直接连接到大部分并行接口;8位或16位。
——通过可编程的波形描述器和配置寄存器来定义波形。
——支持多就绪(RDY)和控制(CTL)输出。
——高达48 MHz的时钟速率。
——每指令周期4个时钟。
——两个UARTS。
——三个定时器/计数器。
——扩展的中断系统。
——两个数据指针。
l&&&& 通过枚举支持总线供电应用。
l&&&& 3.3V操作电压。
l&&&& 灵巧的串行接口引擎。
l&&&& USB中断向量。
l&&&& 对控制传输的设置(SETUP)和数据(DATA)部分使用独立的数据缓冲器。
l&&&& 集成的I2C兼容控制器,运行速率100或400 kHz。
l&&&& 8051的时钟频率为48MHz, 24MHz, 或12MHz。
l&&&& 4个集成的FIFO。
——以更低的系统开销组合FIFO。
——自动转换到/自16位总线。
——支持主或从操作。
——FIFO可以使用外部提供的时钟或异步选通。
——容易与ASIC和DSP芯片接口。
l&&&& 对FIFO和GPIF接口的特殊自动中断向量。
l&&&& 多达40个通用I/O接口。
l&&&& 四种封装可选—128脚TQFP, 100脚TQFP, 56脚QFN和56脚SSOP。
2 驱动基础知识
&& 68013带有自己的驱动的程序的,但是在这里为了讲解usb驱动程序的开发方法,我们还是自己的驱动程序吧,我自己的驱动程序比它自带的驱动程序效果更好,呵呵,传输速度更快,网上有网友说,Ezusb 驱动程序的缺点一大堆,下面讨论驱动程序的编写方法,在本文中,widows环境下我主要想讲解不同的工具的开发方法和技巧。
2.1 windows 驱动开发基础
&&& windows下Pc开发驱动的方法主要有,windriver,driverstudio 3.2+ddk,ddk和WDK这4种,windriver开发驱动最简单,但它开发的驱动不符合微软的wdm模型的思想,在本文中,不对windriver进行讲解,主要讲解driverstudio 3.2(dw 3.2)+ddk,及ddk,和wdk进行驱动开发。
&&&&&& Driverstudio 简单来说,就像api的MFC,它是对ddk的进一步的封装,采用driverstudio的driverworks能够很方便的生成程序框架。而且生成的程序满足wdm模型,因此它以它的易用性影响了一代人。下面首先讲解采用vc6.0+driverstudio 3.2 +ddk搭建驱动开发环境。
1.装系统XP->安装VC 6.0—>安装DDK->driver studio 3.2
2.如果安装的是DDK2600,则需要安装补丁,ntstrsafe和csq,到网上下载文件ntstrsafe.lib+csq.lib.rar,把解压出来的两个库文件拷贝到WinXP_DDK的安装目录下的库目录中(我的是E:\WINDDK\2600\lib\wxp\i386)。
3.对driver studio,VC6.0和ddk进行简单的设置;
& (1)在VC6.0 菜单的DriverStudio菜单下的DDK Build Settings,在弹出的对话框中选择已经安装的DDK目录(我的是E:\WINDDK\2600);
&& (2) VC6.0-->Tools-->Options,点击"Directories"选项卡:)“Show directories for:"下选择Include files,然后检查有没有包含ddk的头文件目录(我的是E:\WINDDK\2600\inc\wxp),如果没有则加上;Show directories for:"下选择Library files,然后检查有没有包含ddk的库文件目录(我的是E:\WINDDK\2600\lib\wxp\i386),如果没有则加上;
&& (3)启动driverstudio,在develop下的DDK Building Settings中确保“DDK Root Directory”下方的内容是ddk的安装目录(我的是E:\WINDDK\2600),然后点击下方的"Luanch Program"正式启动vc6的开发环境。
&& (4) VC6.0进入菜单File-->Open Workspace(打开位于DriverStudio3.2安装目录的\DriverWorks\Source\vdwlibs.dsw)-->进入菜单Build-->batch Build,点击“Select x86"按钮只选中全部的32位库(对于32位的电脑一定不要选中64位的库,否则后面编译会出错)-->点击按钮"Rebuild AlL”开始编译。
(5)编译一个DriverStudio自带的实例,启动VC6.0,点击菜单File-->Open Workspace,打开项目文件:
C:\Program Files\Compuware\DriverStudio\DriverWorks\Examples\wdm\
hellowdm\HelloWdm.dsw,然后编译,如果没有报错,那说明安装和配置成功。
& (6)应用driverstudio的Driver wizard生成驱动程序框架:此后系统会一步一步引导你完成设置,最后自动生产的驱动程序框架。设置好后将生成驱动文件,然后用VC6.0进行编译:进行Build菜单,Rebuild AlL将生成.sys文件,说明驱动模块编译成功!
&&& 讲解完dw3.2的环境搭建后,接着谈谈wdm的驱动到底有哪些内容,本文主要讲解的驱动都是功能驱动,过滤驱动本文不在进行讲解。无论是dw3.2还是ddk或wdk开发驱动都包括以下内容:
1. pnp&& 2.电源管理,3.内存管理等。
&&& 对于dw3.2+ddk或单独采用ddk开发驱动来说,还有派遣函数等内容,而对于wdk来说,就没有派遣函数了,都用队列来处理。
&&& 本文主要针对usb驱动进行讲解,在dw3.2中,与usb驱动相关的几个类如下:
&&&&&&& 1.KUsbLowerDevice :主要用于逻辑设备的编程;
&&&& 2.KusbInterface:主要用于接口设备的编程;
&&&& 3.KusbPipe:主要用于管道的编程;
&&&&&& 对于将dw3.2+ddk怎么开发usb驱动程序,首先采用driverworks的DriverWizard生成usb驱动框架,生成的流程在这里不进行讲解了,网上有10分钟开发一个usb驱动程序等资料。
对于DDK和WDK的最大的不同是DDK采用wdm模型,而WDK采用的是WDF模型,WDM中的Irp在WDF中WDFREQUEST对象表示,WDFREQUEST是对Irp的封装,而wdm中的i/o对象在wdk中不再是一个设备对象,wdk用i/o target表示,i/o target 对象比设备对象(device_object)表示的范围更大,可以表示驱动,和队列对象等。
其次DDK和WDK的不同就是在ddk中,用队列用的比较少,而在wdk中无处不见队列,而wdm的对象都是杂乱的并行队列,而wdf中队列分成了3种,串行队列,并行队列,手动队列。
DDK和WDK的另外一个不同就是电源管理和Pnp了,WDK几乎不要用户在写电源管理和Pnp代码了。
呵呵,总结一句,WDK比DDK的代码更加简洁,少了很多代码。这些不同,我会在后面的举例中,都可以看到。其中ddk的usb讲解,我就采用ddk下面的例子,bulkusb进行讲解,而对于wdk usb讲解,我采用的是wdk下的例子,usbsamp。
Window驱动的开发基础先介绍到这里了,对于最基本的DriverEntry,Adddevice等,我还会在后面的例子中进行讲解。另外WDF又分成2种,第一种是KMDF,第二种是UMDF,KMDF是内核的驱动,UMDF是用户层的驱动。
2.2 应用程序与驱动之间的通信
当应用程序通过USB管道发送或接收数据时,它首先调用Win32 API(如ReadFile,CreateFile,WriteFile,DeviceIoControl)调用使得功能驱动程序收到一个IRP。而驱动程序的工作是把客户的请求(应用软件)引导到正确端点的管道上。它把请求提交到总线驱动程序,总线驱动程序再把请求分解成多个事物(transaction),然后这些事务被送到总线。
应用程序可以调用ReadFile,CreateFile,WriteFile,DeviceIoControl等API通过IRP来和驱动程序进行通信。Windows中,应用程序实现与WDM通信的过程是:应用程序先用CreateFile函数打开设备,然后用DeviceIoControl和WDM通信,包括从WDM中读数据和写数据给WDM。也可以使用ReadFile从WDM中读数据或用WriteFile写数据给WDM,当应用程序退出时,用CloseHandle关闭设备。对应的IRP如下所示:
表1 Win32 API 对应的IRP
Win32函数&IRP主功能代码(IRP_MJ_xxx)&KDevice类成员函数&CreateFile&CREATE&Create&ReadFile&READ&Read&WriteFile&WRITE&Write&DeviceIoControl&DEVICE_CONTROL&DeviceControl&CloseHandle&CLOSE CLENUP&Close CleanUp&
2.3 驱动程序与底层硬件之间的通信
驱动程序(FDO)和硬件之间的通信主要是在功能驱动层,首先构造USB请求包,然后将USB请求包发送到底层驱动总线上,具体的流程如下:
(1)&&&& 当设备插入到PC时,驱动程序调用DriverEntry()例程,主要用于负责驱动程序的初始化,用于初始化驱动程序范围的数据结构和资源。DriverEntry()例程包括主要有以下3个功能。设置AddDevice,Unload,Dispath和其它例程的入口指针;
(2)PC给硬件发送控制命令,即厂商请求。
对于dw3.2来说,发送厂商请求的函数为:BuildVendorRequest,然后构建URB将厂商请求发给硬件;发送Urb的命令为:SubmitUrb函数;
对于ddk来说,发送厂商请求的函数如下:
IoBuildDeviceIoControlRequest,它创建一个I/O控制码的Irp,然后将URB作为Irp的参数,用IoCallDriver发送到底层总线驱动,然后转发到硬件,对硬件设备进行控制;
对于wdk,发送厂商请求分为同步和异步2种方式:
(3)对设备进行读写;
dw3.2对设备进行读的函数如下:
要对usb设备进行进行读(read),首先必须发送控制请求,然后在将该请求以urb发给底层usb总线,然后获取硬件返回的数据。
发送请求有以下几种方式:
1)&&&&& 对于KUsbLowerDevice类来说,发送厂商请求,函数如下:BuildVendorRequest
PURB BuildVendorRequest(
&& PUCHAR TransferBuffer,&&&&&&&&&&&&&& //为驱动程序存放传输数据的内存
&& ULONG TransferBufferLength,&& //传输的字节数
&& UCHAR RequestTypeReservedBits,& //为类别请求字节的保留位
&& UCHAR Request,&&&&&&&&&&&&&&&&&&&&&&&&& //具体的请求数值
&& USHORT Value,&&&&&&&&&&&&&&&&&&&&&&&&&&& //为数值
&& BOOLEAN bIn=FALSE,&&&&&&&&&&&&&&& //False表示主机到设备
&& BOOLEAN bShortOk=FALSE,&&&&&& //传输字节数是否可以少于指定的字节数
&& PURB Link=NULL&&&&&&&&&&&&&&&&&&&&&&& //指为连接下一个传输的URB
&& UCHAR Index=0,&&&&&&&&&&&&&&&&&&&&&&&&& //为索引值
&& USHORT Function=URB_FUNCTION_VENDOR_DEVICE,& //类别请求
&& PURB pUrb=NULL&&&&&&&&&&&&&&&&&&&& //NULL表示分配一个新的URB
然后将URB发送给底层USB总线,提交的函数原型如下:
NTSTATUS SubmitUrb(&& PURB pUrb,&&&&&&&&&&&&& //创建的URB&& PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,& //完成例程&& PVOID CompletionContext=NULL,&&&&&&&&&& //传替给完成例程的参数&& ULONG mSecTimeOut=0&&&&&&&&&&&&&&&&&&&&&&& //同步调用的超时参数);
在dw 3.2下有个usbtherm的例子,里面读取数据的函数,如下:
NTSTATUS UsbThermometer::ReadRamAsynch( UCHAR offset, PIO_COMPLETION_ROUTINE pCompRoutine)
&&&& t << "Entering UsbThermometer::ReadRamAsynch\n";
&&&& KIrp I = KIrp::Allocate( m_Usb.StackRequirement() );
&&&& if ( I.IsNull() )
&&&&&&&& return STATUS_INSUFFICIENT_RESOURCES;
&&&& // allocate a new context structure
&&&& THERMO_READ_COMPLETION_INFO* pCompInfo = new (NonPagedPool) THERMO_READ_COMPLETION_INFO;
&&&& // make sure it succeeded
&&&& if ( pCompInfo == NULL )
&&&&&&&& KIrp::Deallocate(I);
&&&&&&&& return STATUS_INSUFFICIENT_RESOURCES;
&&&& RtlZeroMemory(pCompInfo,sizeof(THERMO_READ_COMPLETION_INFO));
&&&& // initialize the context structure
&&&& pCompInfo->m_pClass =
&&&& pCompInfo->m_OffsetRead =
&&&& // allocate and initialize an URB, and store the pointer in the context structure
&&&& pCompInfo->m_pUrb =
&&&&&&&&&&&&& m_Usb.BuildVendorRequest(
&&&&&&&&&&&&&&&&&& pCompInfo->m_buffer,&&&&&&&&&&&& // transfer buffer
&&&&&&&&&&&&&&&&&& 8,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // transfer buffer size
&&&&&&&&&&&&&&&&&& 0,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // request reserved bits
&&&&&&&&&&&&&&&&& 2,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // request
&&&&&&&&&&&&&&&&&& offset,&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // Value
&&&&&&&&&&&&&&&&&& TRUE,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // In
&&&&&&&&&&&&&&&&&& FALSE,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // Short Ok
&&&&&&&&&&&&&&&&&& NULL,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // link urb
&&&&&&&&&&&&&&&&&& 0,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // index
&&&&&&&&&&&&&&&&&& URB_FUNCTION_VENDOR_ENDPOINT&&&& // function
&&&&&&&&&&&&&&&&&& );
&&&& if ( pCompInfo->m_pUrb == NULL )
&&&&&&&& delete pCompI
&&&&&&&& KIrp::Deallocate(I);
&&&&&&&& return STATUS_INSUFFICIENT_RESOURCES;
&&&& // submit the URB to USBD
&&&& return m_Usb.SubmitUrb(I, pCompInfo->m_pUrb, pCompRoutine, pCompInfo);
对于KusbPipe类来说,构建urb又多了几个函数,其实都差不多,BuildControlTransfer,BuildInterruptTransfer,BuildBulkTransfer,BuildIsochronousTransfer,分别对应的控制传输,中断传输,块传输,同步传输。这些都在usb驱动开发的dw 3.2驱动开发中以例子的形式进行讲解,同时对于usb写,其实是一样的,都是这些函数,只是传输方向变了,改变一个参数就行。
ddk对设备进行读时的函数如下:UsbBuildInterruptOrBulkTransferRequest,然后调用IoCallDriver将URB请求转发给底层总线驱动,在转发给硬件设备。
wdk对设备进行读写时的函数如下(分为同步和异步2种方式):
1)对于usb设备:
同步控制命令(控制传输):
WdfUsbTargetDeviceSendControlTransferSynchronously
函数功能:builds a USB control transfer request and sends it synchronously to an I/O target.
NTSTATUS WdfUsbTargetDeviceSendControlTransferSynchronously(
& [in]&&&&&&&&&& WDFUSBDEVICE UsbDevice,
& [in, optional]&& WDFREQUEST Request,
& [in, optional]&& PWDF_REQUEST_SEND_OPTIONS RequestOptions,
& [in]&&&&&&&&&& PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
& [in, optional]&& PWDF_MEMORY_DESCRIPTOR MemoryDescriptor,
& [out, optional]& PULONG BytesTransferred
举例如下:
WDF_USB_CONTROL_SETUP_PACKET& controlSetupP
WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &controlSetupPacket,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& BmRequestHostToDevice,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& BmRequestToDevice,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& USBFX2LK_REENUMERATE,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& );
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& UsbDevice,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WDF_NO_HANDLE,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& NULL,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &controlSetupPacket,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& NULL,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& NULL
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& );
异步操作(控制传输):
WdfUsbTargetDeviceFormatRequestForControlTransfer
NTSTATUS&&& WdfUsbTargetDeviceFormatRequestForControlTransfer(&&& IN WDFUSBDEVICE& UsbDevice,&&& IN WDFREQUEST& Request,&&& IN PWDF_USB_CONTROL_SETUP_PACKET& SetupPacket,&&& IN OPTIONAL WDFMEMORY& TransferMemory,&&& IN OPTIONAL PWDFMEMORY_OFFSET& TransferOffset&&& );
该函数和同步控制传输函数的区别是只构建控制传输请求,但是不发送控制传输请求,而同步操作WdfUsbTargetDeviceSendControlTransferSynchronously构建完控制传输请求的同时,也发送给I/O target。
2)对于usb管道:
WdfUsbTargetPipeWriteSynchronously函数,函数原型如下:
The WdfUsbTargetPipeWriteSynchronously method builds a write request and sends it synchronously to a specified USB output pipe.
NTSTATUS& WdfUsbTargetPipeWriteSynchronously(&&& IN WDFUSBPIPE& Pipe,&&& IN OPTIONAL WDFREQUEST& Request,&&& IN OPTIONAL PWDF_REQUEST_SEND_OPTIONS& RequestOptions,&&& IN OPTIONAL PWDF_MEMORY_DESCRIPTOR& MemoryDescriptor,&&& OUT OPTIONAL PULONG& BytesWritten&&& );
usb 写数据发送请求的函数为WdfUsbTargetPipeFormatRequestForWrite,然后将WdfRequestSend将请求发送出去。
NTSTATUS WdfUsbTargetPipeFormatRequestForWrite(&&& IN WDFUSBPIPE& Pipe,&&& IN WDFREQUEST& Request,&&& IN OPTIONAL WDFMEMORY& WriteMemory,&&& IN OPTIONAL PWDFMEMORY_OFFSET& WriteOffset&&& );
该函数和同步写函数WdfUsbTargetPipeWriteSynchronously的区别是异步写函数需要调用WdfRequestSend发送请求。WdfRequestSend函数原型如下:
BOOLEAN& WdfRequestSend(&&& IN WDFREQUEST& Request,&&& IN WDFIOTARGET& Target,&&& IN OPTIONAL PWDF_REQUEST_SEND_OPTIONS& RequestOptions&&& );
WdfUsbTargetPipeReadSynchronously函数,函数原型如下:
NTSTATUS WdfUsbTargetPipeReadSynchronously(&&& IN WDFUSBPIPE& Pipe,&&& IN OPTIONAL WDFREQUEST& Request,&&& IN OPTIONAL PWDF_REQUEST_SEND_OPTIONS& RequestOptions,&&& IN OPTIONAL PWDF_MEMORY_DESCRIPTOR& MemoryDescriptor,&&& OUT OPTIONAL PULONG& BytesRead&&& );
WdfUsbTargetPipeFormatRequestForRead函数原型如下:
NTSTATUS& WdfUsbTargetPipeFormatRequestForRead(&&& IN WDFUSBPIPE& Pipe,&&& IN WDFREQUEST& Request,&&& IN OPTIONAL WDFMEMORY& ReadMemory,&&& IN OPTIONAL PWDFMEMORY_OFFSET& ReadOffset&&& );
同步读和异步读的差别和同步写与异步写的区别类似。
待续。。。。。。
本篇文章来源于 Linux公社网站()& 原文链接:
阅读(6260) | 评论(2) | 转发(2) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。

我要回帖

更多关于 zerowindowprobe 的文章

 

随机推荐