您现在的位置: USB开发网 > USB开源项目 > Easy USB 51 Programer Plus
- Easy USB 51 Programer Plus

Windows USB 驱动程序开发基础

------分隔线----------------------------

   厂商自定义USB设备必须由厂商提供Windows驱动程序,很多人也许觉得开发Windows驱动程序非常难,我起初也这样认为,但是如果使用DriverStudio这类辅助工具的话就会变得比较简单,DriverStudio 是一套用来简化微软Windows 平台下设备驱动程序的开发,调试和测试的工具包,利用DriverStudio工程向导,您可以非常方便地生成驱动程序基本框架,只需要添加少许甚至不用添加任何代码就能编写一个自己的驱动程序,DriverStudio已经为您完成了驱动最低层的工作。

  以上内容是在Win7等系统还不是主流操作系统的时候写的,所以现在有必要进行一下补充说明了。首先,厂商自定义USB设备也可以不用厂商自己编写驱动,可以使用LibUSB或WinUSB等驱动,后者是微软提供的一个USB常规驱动程序,LibUSB与WinUSB差不多,只不过LibUSB是跨平台的。有关WinUSB和LibUSB,在后面的内容中将会涉及。第二,DriverStudio在WinXP后已经停止更新了,在WIN7上已经不能用了,所以如果你要还发Winxp、Win2000、Win98等系统上的驱动程序的话,用DriverStudio开是可以用的。第三,后面提到的驱动程序模式,在Win7后都使用WDF了。

  虽然我们可以用DriverStudio来简化我们的驱动程序开发过程,但是传统驱动程序开发基础还是得了解一下的,下面来介绍一下Windows驱动程序的一些基础知识。

1、 Windows驱动程序模型

  Windows驱动程序模型通俗地讲就是有哪些形式,Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver,虚拟设备驱动程序),起源于Windows 3.1 时代,用于Windows 95/98/Me操作系统中;一类是KMD( Kernel Mode Driver,内核模式驱动程序),用于Windows NT下;还有一类就是WDM(Win32 Driver Mode,Win32驱动程序模型),是微软从Windows 98开始,推出的一个新的驱动类型,它是一个跨平台的驱动程序模型,不仅如此WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非Intel平台上运行,毫不夸张地讲,WDM算得上是21世纪的驱动程序框架。

  编写Windows驱动程序最常的方法是用WDM(Windows Driver Model, Windows 驱动程序模型)。WDM采用分层驱动程序模型,对于USB设备来说,可分为USB总线驱动程序(USBD)和USB功能驱动程序。USB总线驱动程序由操作系统提供,它位于USB功能驱动程序的下面,负责与实际的硬件打交道,实现烦琐的底层通信。USB功能驱动程序由设备开发者编写,位于USB总线驱动程序的上面,不与实际的硬件打交道,而是通过向USB总线驱动程序发送URB(USB Request Block,USB请求块)的IRP(I/O Request Packet,I/O请求包),来实现对USB设备信息的发送或接收,而用户应用程序则通过api函数WriteFile、ReadFile、DeviceIoControl等向上层USB驱动请求发送或者操作。

2、开发WDM类型驱动程序的常用方法

  开发WDM驱动程序的方法三种,一种是利用微软提供的DDK驱动程序开发包,第二种是使用Compuware Numega公司的DriverStudio,第三种是使用KRF Tech公司的WinDriver。后两种给出驱动程序的框架,并对DDK中的一些操作进行封装,因此减少了开发时间,提高了效率。开发速度方面,第一种最慢,第三种最快。普及程度方法,第一种和第二种用得比较多。
对于DDK与DriverStudio的优缺点在网上争论了很久,我个人认为这种争论根本没有必要,因为它们之间的关系就好比MFC与SDK之间的关系一样。DriverStudio只是对DDK中的相关函数进行封装,让程序设计者只关注相关功能部分的实现,节省开发时间而已。不管使用什么工具,只要顺手,符合我们的习惯就行。

3、 USB驱动程序的结构

  WDM体系结构实行分层处理,即设备驱动被分成了若干层,典型地分成:高层驱动程序、中间层驱动程序、底层驱动程序。每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件发生作用,从而完成I/O请求工作。在这样的架构下,上面的驱动层就不需要对每个操作系统都要开发一遍了。

  WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件,一个PDO对应一个真实硬件。一个硬件只允许有一个PDO,但却可以拥有多个FDO,而在驱动程序中我们不是直接操作硬件而是操作相应的PDO与FDO。

  USB驱动程序采用分层结构,位于上层的是USB设备驱动程序(或叫功能驱动程序Function Driver、用户驱动程序),负责创建FDO。总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,创建PDO代表发现的设备。

  与传统PC总线(如PCI总线)设备的驱动程序相比,USB功能驱动程序从不直接与硬件对话。相反,它仅靠创建URB(USB请求块)并将URB提交到总线驱动程序就可完成硬件操作。在应用程序与WDM驱动程序通信方面,系统为每一个用户请求打包形成一个I/O请求包(IRP)结构,将其发送至驱动程序,并通过识别IRP中PDO来区别是发送给哪一个设备的。

  NT驱动程序和一般的DOS/Windows C语言程序不一样,它没有main()或者WinMain()函数入口。和DLL类似地,它向操作系统显露一个名称为DriverEntry()的函数,在启动驱动程序的时候,操作系统将调用这个入口。DriverEntry除了做一些必要的设备初始化工作外,还初始化一些Dispatch例程入口。我们知道,应用和设备驱动程序打交道主要是通过CreateFile、 ReadFile、WriteFile 和DeviceIoControl等Win32 API来进行的。这些API其实都对应着驱动程序的一些Dispatch例程。而驱动程序除了DriverEntry以外,主要就是由这些Dispatch例程组成的。例如调用Win32 API CreateFile的时候,操作系统最终转化为对驱动程序IRP_MJ_CREATE功能代码所对应的 Dispatch例程的调用,如果驱动程序没有提供该例程, CreateFile调用就会失败。

以下是设备驱动程序常用功能代码含义及与应用程序API函数对应关系

NT中一些常用的功能代码和Win32 API的对象关系表

功能代码

说明

IRP_MJ_CREATE

打开设备CreateFile

IRP_MJ_CLEANUP

在关闭设备时,取消挂起的I/O请求CloseHandle

IRP_MJ_CLOSE

关闭设备CloseHandle

IRP_MJ_READ

从设备获得数据ReadFile

IRP_MJ_WRITE

向设备发送数据WriteFile

IRP_MJ_DEVICE_CONTROL

对用户模式或内核模式客户程序可用的控制操作DeviceIoControl

IRP_MJ_INTERNAL_DEVICE_CONTROL

只对内核模式客户程序可用的控制操作

IRP_MJ_QUERY_INFORMATION

得到文件的长度GetFileLength

IRP_MJ_SET_INFORMATION

设置文件的长度SetFileLength

IRP_MJ_FLUSH_BUFFERS

写输出缓冲区或丢弃输入缓冲区FlushFileBuffers、FlushConsoleInputBuffer、PurgeComm

IRP_MJ_SHUTDOWN

系统关闭InitialSystemShutdown

  DDK有很多驱动程序的例子,其中有一个bulkusb的例子,仔细看过之后,其实把它修改一下就可以变成自己设备的驱动,这也正是Microsoft推荐驱动设计者开发设备驱动程序的方法(不过有了DriverStudio和WinDriver这类辅助开发工具后,就可以直接利用这类工具来快速生成驱动程序框架)。DDK确实过于博大精深,我想,能够达到自己的设备驱动可以正常工作这个目的就可以了,没有必要搞清楚驱动程序设计中的每一个细节。 如果使用DriverStudio工具进行开发,DriverStudio不仅提供相当数量的实例,还可以利用它的DriverWizard向导生成驱动程序框架,此框架已经完成大部分设备枚举工作,方便设计人员将精力集中在功能的实现上面。

4、 与设备驱动程序相关的文件

  WDM类型的设备驱动程序扩展名为SYS,同时还应该包括一个INF类型的文件。INF文件含有安装一个WDM设备驱动程序需要的所有必要的信息,包括要复制的文件列表、要创建的注册表项、设备的旧和兼容ID、设备类别、设备名称、厂商信息等。INF文件是一个文本文件,它由节组成,每一节从节名称开始,后面是节内容。

  当发现新的设备时(系统启动时,在安装热插拔设备时,或者从控制面板安装新设备时),就调用Windows的“添加新设备向导”,执行这个向导扫描所有可用的INF文件,试图找到合适的驱动程序。Windows首先选择硬件ID匹配的设备的INF文件,否则它选择其兼容ID与设备ID最佳匹配的INF文件,若仍未找到则会提示用户手动选择驱动程序INF文件。然后根据INF文件的指令安装驱动程序,驱动程序可执行文件(即sys文件)被复制到正确的位置,通常是indows\System32\Drivers目录,然后创建各种注册表项,驱动程序被装入内存,并执行它的DirverEntry例程,对新的设备调用AddDevice例程,给设备分配I/O、DMA、中断等资源,启动设备,然后正常的I/O操作就可以继续进行,使用后的INF文件复制到Windows INF子目录,当有发现有新设备安装时,安装向导也会首先搜索这个目录查找对新设备对应的inf文件。

  利用DriverStudio提供的DriverWizard向导生成驱动程序框后会自动生成这个INF文件,所以您也可以不必过多关心INF文件的细节。

------分隔线----------------------------
联系我们
  • Q Q: 1148374829 点击这里给我发消息
  • 旺旺:jhoneqhsieh 点击这里给我发消息
  • 电话:(0)15923141204
  • 淘宝网店