基于WDM的 USB键盘驱动程序开发*
2012-08-15刘皓
刘 皓
(山西师范大学经济管理学院,山西临汾041000)
计算机发展速度飞快,传统的计算接口已经不能满足当前计算机高速发展的需求,键盘、鼠标、调制解调器、打印机、扫描仪、摄像头、数码相机、MP3随身听、外置硬盘、光驱设备往哪儿接呢?计算机业界迫切需要新的通用型、高速总线接口。
USB是一种应用在计算机领域的新型接口技术,它使得计算机周边设备连接标准化,具有安装方便、高带宽、易于扩展的特点。
本文利用 Visual C++6.0、Driver Works以及 Windows 2000 DDK开发包作为开发工具,采用WDM驱动程序模式,开发USB接口驱动程序,实现了USB键盘驱动程序的开发、安装及测试。
1 WDM驱动程序模型
在WDM驱动程序模型中,每个硬件设备包括两个驱动程序。一个驱动程序是硬件设备驱动程序,也称功能驱动程序,主要为用户提供适合的控制方式。它了解硬件工作的所有细节,负责初始化I/O操作,处理I/O操作完成时所带来的中断事件。通常由两个分离的执行文件组成。一个文件是类驱动程序,它了解如何处理操作系统使用的WDM协议,以及如何管理整个设备的基本特征[3]。另一个文件称为微小驱动程序,它包含类驱动用于管理设备实例的厂商专有特征例程。类驱动程序和微小驱动程序合在一起才成为一个完整的功能驱动程序。
另一个驱动程序称为总线(BUS)驱动程序,负责管理硬件与计算机的连接。
一个完整的驱动程序包含许多例程,当操作系统遇到IRP时,它就调用驱动程序的例程来执行IRP的各种操作。
2 WDM驱动程序的结构
WDM驱动程序实行分层处理,被分成高层驱动程序、中间层驱动程序、底层驱动程序。每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件进行交互,从而完成I/O请求工作。
WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件。总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,并为每个设备创建一个PDO,功能驱动程序(Function Driver)管理FDO所代表的设备,过滤驱动程序(Filter Driver)用于监视和修改IRP流。
3 USB键盘驱动程序的开发
3.1 USB键盘驱动程序的实现和运行
用Driver Wizard3.0创建Usbkbd的WDM框架将自动生成一个工作区和两个工程,Test_Usbkbd files和Usbkbd files。其中Test_Usbkbd files是测试应用程序工程,Usbkbd files是驱动程序工程[3]。
Test_Usbkbd files测试应用程序工程
OpenByIntf.cpp:OpenByIntf.cpp 包含 OpenByInterface 函数,OpenByInterface函数用GUID接口方式与WDM进行通信。
Test_Usbkbd.cpp:是整个测试应用程序的主要文件,在这里添加相关代码,其作用是,打开设备的一个句柄,用于对设备进行读操作,并对DeviceIoControl函数进行调用,DeviceIoControl函数包含了对驱动程序的通信的命令。
Test_Usbkbd.cpp的文件结构
UsbkbdDriverInterface.h:定义设备接口的GUID。
Usbkbdioctl.h:定义驱动程序的控制代码。
Usbkbd.cpp:功能驱动程序,包含设备的初始化,Driver-Entry例程和AddDevice历程。还重载了注册信息参数。
UsbkbdDevice.cpp:设备驱动程序,主要包括一些IRP的操作,如:清除(CleanUp(KIrp I))、关闭(Close(KIrp I))、创建(Create(KIrp I))、PnP 管理(DefaultPnp(KIrp I))、电源管理(DefaultPower(KIrp I))、I/O控制(DeviceControl(KIrp I))、开始设备(OnStartDevice(KIrp I))、停止设备(OnStop-Device(KIrp I))、移除设备(OnRemoveDevice(KIrp I))、对设备进行读操作(Read(KIrp I))、系统控制(SystemControl(KIrp I))、通信控制(USBKBD_IOCTL_800_Handler(KIrp I))等。
在以上文件中添加代码。
function.h预定义相关的例程。
Usbkbd.h描述设备的相关信息,包括初始化时在注册表中的路径,注册表的参数,数据成员在 DriverEntry期间被载入。
Usbkbdioctl.h为设备定义I/O控制命令。
Usbkbd.inf安装文件,在生成工程时自动生成。安装WDM设备驱动程序需要的所有必须的信息,包括要复制的文件列表、创建的注册表项等。
驱动程序通常使用DriverEntry作为驱动程序的默认入口点,当PnP管理器发现一个硬件设备时,首先调用Driver-Entry例程,DriverEntry例程是驱动程序初始化的入口点,它负责创建一个设备对象,定义其它的例程名称,设置例程的入口指针,从注册表中获取信息,初始化驱动程序,并初始化其它在驱动程序范围内的数据结构和资源。在DriverEntry中,主要的工作是在传递的驱动程序对象中存储一系列的回调例程指针。DRIVER_OBJECT结构由操作系统用于存储与驱动程序有关的任何信息。以后使用一个分开的结构存储每个设备的信息。Default Pnp(即插即用)主要是实现一个IRP_MJ_PNP处理程序。在驱动程序中,即插即用的基本处理包括:处理设备的添加和删除;得到分配的资源;处理查询停止和查询删除消息;处理停止设备消息;处理意外删除消息。Dispatch(分发例程)主要用来处理应用程序和驱动程序之间的通信,包括 Great、Close、Cleanup、Read、Write、Control。分发例程是可选的,是为设备的硬件层编程服务的,通过该例程可以达到应用程序控制设备的目的。
WDM驱动程序通常由PnP管理器载入内存,然后调用它之中的AddDevice例程来创建设备。用一个inf安装文件来指明该驱动程序的一些参数[1]。
一般情况下,DriverEntry例程要设置以下几个IRP处理函数:
DriverUnload指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。
DriverExtension→AddDevice指向驱动程序的AddDevice函数。PnP管理器将为每个硬件实例调用一次AddDevice例程。这样将创建一个该设备对象。
DriverStartIo如果驱动程序使用标准的IRP排队方式,应该设置该成员,使其指向驱动程序的StartIo例程。
MajorFunction是一个指针数组,I/O管理器把每个数组元素都初始化成指向一个空函数,这个空函数仅返回失败。驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相对应的指针元素,使它们指向相应的派遣函数。
3.2 功能驱动程序的相关步骤
用IoCreateDevice创建设备对象,并建立一个私有的设备扩展对象。
注册一个或多个设备接口,以便应用程序能够发现设备的存在。另外,还可以给出设备名并创建符号连接。
初始化设备扩展对象和设备对象的Flag成员。
调用IoAttachDeviceToDeviceStack函数,把新设备对象放到堆栈中。
Power例程。WDM驱动程序支持电源管理,电源管理器通过IRP指示驱动程序来改变电源状态,等待并响应系统唤醒事件和查询驱动程序设备,如果设备不支持电源管理,仅有一个默认的Power例程即可。
CreatFile:应用程序要想和设备进行通信,必须先打开设备,因此,应用程序用CreatFile函数来打开设备。
DeviceControl:应用程序可以调用DeviceIoControl函数与WDM驱动程序进行通信。DeviceIoControl函数分为同步调用和异步调用方式,采用同步方式时,应用程序调用DeviceIoControl函数将被阻塞,直到驱动程序完成响应的数据传输时才往下执行,因此这里采用异步调用方式,但是通常采用异步方式完成的驱动程序只允许一个应用程序,为了打开多个应用程序,应用程序调用并修改DeviceControl,使得每次只能有一个IRP处于等待中,这样可以打开多个应用程序[3]。
ReadFile函数:应用程序和驱动程序进行通信的目的就是通过驱动程序对设备进行读、写、或控制等操作。在键盘驱动程序中,通过调用ReadFile函数,来读取键盘数据。
4 驱动程序的安装
用DriverWizard创建WDM框架程序之后,将自动生成一个工作区和两个工程文件。在相关文件添加相关代码后,将光标定位在Usbkbd file上,点击右键,选择“Set as Active Project”设置该工程为当前活动工程。然后点击编译,如果编译没有错的情况下,将会在sys文件夹下生成一些文件,包括一些自由构造和检查构造等文件,还生成一个objfre文件,生成的安装程序的系统文件Usbkbd.sys就包含在该文件里。
要安装上面生成的Usbkbd.sys文件,必须用驱动程序安装文件(inf)来安装。安装Usbkbd.sys文件有三种方法,但是在安装之前都要将sys文件下的Usbkbd.inf复制到“..sysobjferi386”目录下。因为Usbkbd.inf是在生成工作区时生成的,当时并没有sys文件,因此要将Usbkbd.inf复制到Usbkbd.sys所在目录下,Usbkbd.inf文件包含了安装WDM设备驱动程序需要的所有必须的信息,例如要复制的文件列表、创建的注册表项等。
从“控制面板”→“系统”→“硬件”→“添加硬件向导…”开始运行,按照向导一步一步找到Usbkbd.inf文件,完成该USB键盘驱动程序的安装[2]。
驱动程序安装成功后将在设备管理器里可以看到安装的USBKBD设备的详细信息。如果驱动程序安装不上,可以用DriverStudio提供的Monitor跟踪测试。当驱动程序可以正常运行时,显示驱动程序的状态信息,当驱动程序不能运行时显示错误信息。
[1]武安河.Windows 2000/XP WDM设备驱动程序的开发[M].第2版.北京:电子工业出版社 ,2005.
[2]张惠娟,周利华,翟鸿鸣.Windows环境下的设备驱动程序设计[M].西安:西安电子科技大学出版社,2002.
[3][美]Walter Oney.Windows驱动程序编程[M/OL].马少华,译.http://www.driverdevelop.com/2001.