艾布伦双色球专家专栏:用WDM开发USB驱动程序

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 18:08:04
引言

USB,全称是Universal Serial Bus(通用串行总线),它是一些PC大厂商,如Microsoft、Intel、康柏等为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信的标准,自1995年在Comdex上亮相以来至今已广泛地为各PC厂家所支持。现在生产的PC几乎都配备了USB接口,Microsft的Windows98、NT以及MacOS、Linux、FreeBSD等流行操作系统都增加了对USB的支持。

它有以下主要优点:

·速度快。USB有高速和低速两种方式,主模式为高速模式,速率为12Mbps,另外为了适应一些不需要很大吞吐量和很高实时性的设备,如鼠标等,USB还提供低速方式,速率为1.5Mb/s。
·设备安装和配置容易。安装USB设备不必再打开机箱,加减已安装过的设备完全不用关闭计算机。所有USB设备支持热插拔,系统对其进行自动配置,彻底抛弃了过去的跳线和拨码开关设置。
·易于扩展。通过使用Hub扩展可拨接多达127个外设。标准USB电缆长度为3m(5m低速)。通过Hub或中继器可以使外设距离达到30m。
·能够采用总线供电。USB总线提供最大达5V电压、500mA电流。
·使用灵活。USB共有4种传输模式:控制传输(control)、同步传输(Synchronization)、中断传输(interrupt)、批量传输(bulk),以适应不同设备的需要。


WDM驱动程序的介绍

设备驱动程序就是控制硬件设备的一组函数。在Windows环境下,如果要处理硬件中断,实现DMA操作,就一定要用到设备驱动程序,开发即插即用(PnP)设备(如USB接口设备、PCI接口卡)更是这样。

WDM(Win32 Driver Model)是Microsoft公司力推的全新的驱动程序模式,它的应用平台是Windows 98/Me/2000操作系统,不久的将来,在Windows平台上,WDM将成为主流的驱动模式。

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

WDM不是通过驱动程序名称,而是通过一个128位的全局唯一标识符(GUID)实现驱动程序的识别。在应用程序与WDM驱动程序通信方面,系统为每一个用户请求打包形成一个I/O请求包(IRP)结构,并将其发送到驱动程序,并通过识别IRP中的PDO来区别是发送给哪一个设备的。内核通常通过发送IRP来运行驱动程序的代码。WDM驱动程序完全支持即插即用。

一个WDM驱动程序的功能模块可由以下几个部分组成:
·驱动程序初始化。
·创建和删除设备。
·处理Win32程序打开和关闭句柄的请求。
·处理Win32程序输入/输出请求。
·实现对设备的串行化访问。
·访问硬件。
·取消I/O请求。
·超时I/O请求。
·调用其他驱动程序。
·处理电源管理请求。
·使用Windows管理诊断(WMI)向系统管理员报告。
·处理一个可热插拔的设备被加入或删除的情况。

WDM驱动程序有一个主要的初始化入口点,即一个称为DriverEntry的例程,它有一个标准的函数原型,当WDM驱动程序被装入时,内核调用DriverEntry例程。所有对各种IRP的处理例程都在此入口函数中做出定义。

大多数的WDM设备对象,都是在即插即用管理器调用AddDevice例程入口点被创建的。插入新设备后,当系统找到由安装信息所指示的驱动程序时,这个例程调用在此之后,一系列的即插即用IRP被发送到驱动程序,设备驱动程序可进行相应的功能处理。

开发WDM驱动程序有两种方法,一种利用微软提供的98DDK和2000DDK驱动程序开发包,另外一种是专用驱动程序开发工具,如Compuware Numega公司的DriverStudio,KRF, Tech公司的WinDriver。后者给出驱动程序的框架,并对DDK中操作进行封装,因此减少了开发时间,提高了效率。我们选用了DriverStudio开发工具开发USB驱动程序。


USB 启动的过程

在介绍USB程序设计之前,我们需要先了解它的启动过程。
USB系统主要由主控制器(Host Controller)、USB Hub 和USB外设(Peripherals Node)组成系统拓扑结构,如图1所示。

在应用程序可以与一个USB设备通信之前,主机需要知道设备支持哪些传输类型和终端,主机也必须分配一个地址给设备,主机通过一个被称为枚举的信息交换来完成这些工作 。枚举过程:集线器的一个任务就是检测设备的连接与断开,每个集线器都有一个中断流程来通知主机报告这些事情。在系统启动的时候,主机查询它的根集线器来了解有哪些设备已经连接上了,包括其他集线器和连接到这些集线器的设备。在启动后,主机持续周期性地查询了解是否有设备连接或断开。

图1:USB总线的拓朴结构
图2:软件结构框图

一旦发现一个新设备,主机发送一系列的请求给这个设备的集线器,使这个集线器在主机和这个设备之间建立一个通信渠道。然后主机试图枚举这个设备,枚举是使得主机的设备驱动程序能与这个设备通信的最基本的信息交换 。这个过程由如下动作组成:分配一个地址给设备,从设备读取描述数据,分配和载入一个设备驱动程序以及从接收到的数据中选择一个配置。然后设备就被配置完毕,并且准备好使用它的配置中支持的任何终端来传输数据。

主机的枚举是通过给终端0发送包含标准USB请求的控制传输。所有的USB设备必须支持控制传输、标准USB请求和终端0。对一个成功的枚举来说,设备必须对每一个请求响应并返回请求的信息。

从用户的角度看,枚举应该是不可见和自动的,除了一些情况下如申明发现一个新设备和是否成功配置这个新设备的窗口,有时在第一次使用时,用户需要提供一个有INF文件和设备驱动程序的磁盘。

当枚举结束时,Windows把新的设备加入到控制面板的设备管理器显示中。应依次单击"开始"菜单(Start menu)->设置(Settings)->控制面板(Control Pannel)->设备管理器(Device Manager),在设备管理器可以看到新加的设备。当一个用户断开一个外设的连接时,Windows自动地从这个显示中移掉这个设备。

在一个USB的外设中,外设的程序代码包含了主机将请求的信息,并且程序代码必须能识别和响应这些信息的请求。在Windows不需要编写枚举的程序,因为Windows自动处理枚举过程。Windows将查找一个被称为INF文件的特殊文本文件,这个文件会告诉Windows哪个驱动程序适合这个设备。


USB接口软件结构

USB接口软件结构如图2所示。PC机底层驱动程序包括HUB驱动、总线类驱动和主机控制器驱动,它们负责处理总线枚举、电源管理,以及USB事务的其它方面,这些驱动不需要编程者开发,Windows操作系统提供这类驱动程序。编程者需要开发的程序为:USB控制器固件程序,控制器的接收应用程序,设备功能驱动程序, PC机应用程序。

USB控制器固件程序实现设备的枚举以及端点与主机的通信。控制器的接收应用程序接收主机下载的文件。 设备功能驱动程序为应用程序和底层驱动程序之间提供接口。当一个应用程序启动一个API调用后,Windows把调用传递给设备驱动程序,设备驱动程序把请求传递到底层驱动程序,底层驱动程序对硬件进行相应的操作。PC机应用程序功能是实现主机文件的下载。


USB驱动程序的介绍

USB驱动程序的编写必须采用WDM驱动程序。对于USB设备来说,其驱动程序可分为USB底层驱动程序和USB功能驱动程序。USB底层驱动程序由操作系统提供,它位于USB功能驱动程序的下面,负责与实际的硬件打交道,实现繁琐的底层通信。USB功能驱动程序由设备开发者编写,位于USB底层驱动程序的上面,不与实际的硬件打交道,而是通过向USB底层驱动程序发送包含URB(USB Request Block,USB 请求块)的IRP(I/O Request Packet,I/O请求包),来实现对USB设备信息的发送和接收。采用这种分层驱动程序的设计方法有两个优点:(1)多个USB设备可以通过USB底层驱动程序来协调它们的工作;(2)编写分层驱动程序较之编写单一驱动程序相对简单,且可以节省内存和资源,不易出错。

若应用程序想对设备进行I/O操作,它需调用Windows API函数 ,I/O管理器将此请求构造成一个合适的I/O请求包IRP并把它传递给USB功能驱动程序。USB功能驱动程序接收到这个IRP以后,根据IRP中包含的具体操作代码,构造相应USB请求块并把此URB放到一个新的IRP中,然后把此IRP传递USB底层驱动程序,USB底层驱动程序根据IRP中所含的URB执行响应的操作(如从USB设备读取数据),并把操作结果返还给USB功能驱动程序。USB功能驱动程序接收到此IRP后,将操作结果通过IRP返还给I/O管理器,最后I/O管理器将此IRP操作结果返还给应用程序,至此应用程序对USB设备的一次I/O操作完成。

USB功能驱动程序除负责处理应用程序的I/O请求外,还要处理PnP请求(如设备启动请求IRP_MN_START_DEVICE,设备删除IRP_MN_REMOVE_DEVICE等)。通过对这些PnP请求的处理,USB功能驱动程序可支持设备的热插拔和即插即用功能。


INF文件的介绍

INF文件含有安装一个WDM设备驱动程序需要的所有必要的信息,包括要复制的文件列表、要创建的注册表项、设备的ID和兼容ID等。INF文件是一个文本文件,它由节组成,每一节从节名称开始,后面是节内容。

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


USB功能驱动程序开发

系统中USB驱动程序的开发采用Compuware Numega公司的DriverStudio开发工具。DriverStudio是一个大的开发工具包,它包含VtoolsD、softICE和DriverWorks等开发工具。Driver Wizard是DriverWorks创建WDM框架程序的工具,而DriverWorks又是DriverStudio的工具之一。在DriverWorks安装之前,需要先安装Windows 98 DDK或Windows 2000 DDK。系统中采用Driver Wizard创建一个WDM程序框架。

在Driver Wizard创建驱动程序框架时,开发者需要提供设备的类型,驱动程序支持的功能,从注册表中装载的参数,接口方式,缓冲方式和电源管理方式等内容。通过Driver Wizard生成驱动程序为开发者提供基本的框架 ,针对具体的设备,开发者只需修改较少的代码就可以实现相应的功能。


PC机应用程序的实现

1、应用程序对USB驱动程序的访问

在Windows中,Win32应用程序调用WDM的Win32函数有五个:CreateFile(),ReadFile(),WriteFile(),DeviceIocontrol(),CloseHandle()。

(1)打开一个WDM设备

应用程序打开一个WDM设备驱动程序,用的是CreateFile()函数,它的第一个参数不是一个WDM文件名,而是一个符号链接名。符号链接名的获得需要调用SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,SetupDiGetDeviceInterfaceDetail三个函数。SetupDiGetClassDevs打开指定GUID的设备的"设备信息集",SetupDiEnumDeviceInterfaces取出感兴趣的设备实例的信息,SetupDiGetDeviceInterfaceDetail获得实例的符号链接名。最后调用CreateFile()函数获得设备的句柄,这样它就能够调用Win32函数,这将产生对应于此设备对象的IRP。

(2)关闭一个WDM设备

WDM允许多个应用程序打开同一个设备,它为每个应用程序创建一个设备对象。当其中的一个应用程序调用CloseHandle()函数,驱动程序首先收到"清除"IRP,驱动程序应当在"清除"例程中清除和此设备对象有关的待处理的IRP。然后关闭IRP,关闭设备对象。

(3)ReadFile()、WriteFile()和DeviceIoControl函数的调用

这些调用都产生一个请求,产生IRP请求包传递给驱动程序,实现对设备的读、写和一些特定的操作。

2、PC机应用程序下载数据文件

PC机应用程序通过Win32函数实现将音频文件下载到目标板,为了减少读取下载文件的时间,在内存开辟1M空间。先读1M大小的文件到内存,下载完后再将剩余的文件读入内存。在下载文件过程中,传输的数据可能有错误,为了解决这个问题,采用了重传机制,即若没有收到EP7212确认''$''字符或收到其他的字符,将重传该512个字节块,直到成功为止。程序下载的流程如图3所示。