USB接口通信(驱动)的设计及及与实现_第1页
USB接口通信(驱动)的设计及及与实现_第2页
USB接口通信(驱动)的设计及及与实现_第3页
USB接口通信(驱动)的设计及及与实现_第4页
USB接口通信(驱动)的设计及及与实现_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、引言WDM是“Windows驱动程序模型”的简称,即“Windows Driver Model”。实际上它是一系列集成在操作系统之中的常规系统服务集,用于简化硬件驱动程序的编写,并保证它们在Windows 98/Me/2000中的二进制兼容,WDM(Windows Driver Model)模型是从和WinNT4的内核模式设备驱动程序发展而来的。WDM主要的变化是增加了对即插即用、电源管理、Windows Management Interface(WMI)、设备接口的支持。WDM模型的主要目标,是实现能够跨平台使用、更安全、更灵活、编制更简单的Windows设备驱动程序。WDM采用了“基于对象

2、”的技术,建立了一个分层的驱动程序结构。WDM首先在Windows98中实现,在Windows2000中得到了进一步的完善,并在后续开发的Windows操作系统中都将存在,比如Windows Me和Windows XP。微软在通过WDM模型的引入,希望减轻设备驱动程序的开发难度和周期,逐渐规范设备驱动程序的开发,应该说,WDM将成为以后设备驱动程序的主流。USB技术的全称是通用串行总线,是英文Universal Serial Bus的缩写。它是一种应用在PC领域的新型接口技术,虽然已经被广泛应用,但是初始的Windows 2000是支持协议的,如果希望支持协议,需要在微软网站上下载升级包。实际

3、上,对于键盘或者鼠标来说,传输的速度非常小,使用或者是的区别并不大。闪存盘之类的存储设备,则需要重视传输速度。版本主要应用在鼠标,键盘等HID设备上,这就是本驱动程序中引用的头文件版本是的原因。本毕业设计的目的是希望对Windows 2000操作系统体系结构和驱动程序开发以及调试等方面的问题有一个比较深入的了解,对USB协议和USB体系有做一个比较深入的了解。并开发出一个USB键盘驱动。这个USB键盘驱动程序应当可以替代系统原有的键盘驱动程序,并可以正常工作。本论文设计的驱动程序在Windows 2000下运行,开发环境为和DDK2000。1 WDM驱动程序模型概述驱动程序在任何操作系统下都和

4、系统内核有着密切的关系。设备驱动程序是一个包含了许多操作系统可调用例程的容器,这句Walter Oney曾说过的话,抽象的描述了设备驱动程序的本质。 Windows 2000概述图11中概括了Windows 200系统中的组件,Windows 2000操作系统是由不同层次的模块共同组成的。该图着重描述了驱动程序开发者所关心的特征。工作在Windows 2000操作系统平台上的软件要么执行在用户模式中,要么执行在内核模式中。当用户模式程序需要读取设备数据时,就调用Win32 API函数,如ReadFile. Win32子系统模块通过调用平台相关的系统服务接口实现API,而平台相关的系统服务将调用

5、内核模式支持例程。在ReadFile调用中,调用首先到达系统DLL中的一个入口点,NtReadFile函数。然后这个用户模式的NtReadFile函数接着调用系统服务接口,最后由系统服务接口调用内核模式中的服务例程,该例程同样名为NtReadFile。应用程序应用程序Win32子系统设备驱动硬件抽象层硬件IO管理器用户模式内核模式Win32API调用系统服务接口传递IRP给驱动程序派遣函数HAL调用平台相关操作图11 Windows组件模型系统中还有许多与NtReadFile相似的服务例程;它们同样运行在内核模式中,为应用程序请求提供服务,并以某种方式与设备交互。这些服务例程首先检查从用户态传

6、递给它们的参数以保护系统安全或防止用户态程序非法存取数据,然后创建一个称为“I/0请求包(IRP)”的数据结构,并把这个数据结构送到某个驱动程序的入口点。驱动程序完成一个I/0操作后,通过调用一个特殊的内核模式服务例程来完成该IRP。完成操作是处理IRP的最后动作,它使等待的应用程序恢复运行。 Windows 2000中的驱动程序类型虚拟设备虚拟设备驱动程序(VDD)内核模式驱动程序文件系统驱动程序遗留设备驱动程序PnP驱动程序显示驱动程序WDM驱动程序类驱动程序微型(mini)驱动程序图12 Windows 2000中的设备驱动程序种类Windows 2000系统可以使用多种驱动程序,图1-

7、2显示了其中几种。虚拟设备驱动程序(VDD)可以使DOS应用程序访问x86平台上的硬件。VDD通过屏蔽I/O权限掩码来捕获端口存取操作,它基本上是模拟硬件操作,这对于那些直接对裸机硬件编程的应用程序特别有用。尽管这种驱动程序在Windows 98和Windows 2000中共享一个名称并且有相同的功能,但实际上它们的工作方式完全不同。我们用VDD缩写代表这种驱动程序,用VxD缩写代表Windows 98中的虚拟设备驱动程序以示区别。内核模式驱动程序的分类包含许多子类。PnP驱动程序就是一种遵循Windows 2000即插即用协议的内核模式驱动程序。WDM驱动程序是一种PnP驱动程序,它同时还遵

8、循电源管理协议,并能在Windows98和Windows 2000间实现源代码级兼容。WDM驱动程序还细分为类驱动程序(classdriver)和微型驱动程序(minidriver),类驱动程序管理属于己定义类的设备,微型驱动程序向类驱动程序提供厂商专有的支持。显示驱动程序是用于显示和打印设备的内核模式驱动程序。文件系统驱动程序在本地硬盘或网络上实现标准PC文件系统模型(包括多层次目录结构和命名文件概念)。遗留设备驱动程序也是一种内核模式驱动程序,它直接控制一个硬件设备而不用其它驱动程序帮助。这种驱动程序主要包括Windows NT早期版本的驱动程序,它们可以不做修改地运行在Windows 2

9、000中。 WDM驱动程序类型WDM(Windows Driver Model)模型是从和WinNT4的内核模式设备驱动程序发展而来的。WDM主要的变化是增加了对即插即用、电源管理、Windows Management Interface(WMI)、设备接口的支持。WDM模型的主要目标,是实现能够跨平台使用、更安全、更灵活、编制更简单的Windows设备驱动程序。WDM采用了“基于对象”的技术,建立了一个分层的驱动程序结构。WDM首先在Windows98中实现,在Windows2000中得到了进一步的完善,并在后续开发的Windows操作系统中都将存在,比如Windows Me和Windows

10、 XP。微软在通过WDM模型的引入,希望减轻设备驱动程序的开发难度和周期,逐渐规范设备驱动程序的开发,应该说,WDM将成为以后设备驱动程序的主流。在WDM模型中,每个硬件设备至少有两个驱动程序:一个功能驱动程序(function driver)和一个总线驱动程序(bus driver)。一个设备还可能有过滤驱动程序(filter driver),用来变更标准设备驱动程序的行为。这些服务于同一个设备的驱动程序组成了一个链表,称为设备栈。详细的描述见图1-3。可选的上层过滤驱动程序可选的上层过滤驱动程序功能驱动程序可选的底层过滤驱动程序可选的总线过滤驱动程序总线驱动程序设备驱动程序总线驱动程序图1

11、-3驱动程序的种类总线驱动程序总线驱动程序为实际的IO总线服务,比如IEEE 1394。在WDM的定义中,一个总线是这样的设备,它用来连接其他的物理的、逻辑的、虚拟的设备。总线包括传统的总线SCSI和PCI,也包括并口、串口、以及i8042端口。微软已经为Windows操作系统提供了总线驱动程序。总线驱动程序已经包含在操作系统里了,用户不必安装。一个总线驱动程序负责以下的工作:枚举总线上的设备;向操作系统报告总线上的动态事件;响应即插即用和电源管理的IO请求;提供总线的多路存取(对于一些总线);管理总线上的设备;功能驱动程序功能驱动程序是物理设备的主要驱动程序,它实现设备的具体功能,一般由设备

12、的生产商来编写。功能驱动程序的主要功能是:提供对设备的操作接口;操作对设备的读写;管理设备的电源策略;过滤驱动程序过滤驱动程序是一个可选项,当一个用户需要改变或新添一些功能到一个设备、一类设备或一种总线时,就可以编写一个过滤驱动程序。在设备栈里,过滤驱动程序安装在一个或几个设备驱动程序的上面或下面。过滤驱动程序拦截对具体设备、类设备、总线的请求,做相应的处理,以改变设备的行为或添加新的功能。但过滤驱动程序只处理那些它所关心的IO请求,对于其他的请求可以交给其他的驱动程序来处理,这样可以非常灵活改变设备的行为,至少用户会这样看。比如:一个USB键盘的上层过滤驱动程序可以强制执行附加的安全检查。一

13、个鼠标的低层过滤驱动程序,通过对鼠标移动的数据做非线性的转换,可以得到一个有加速效果的鼠标轨迹。功能驱动程序的组成功能驱动程序由类驱动程序和微型驱动程序(Minidriver)组成。类驱动程序实现了某一类设备的常用操作,由微软提供,驱动程序的开发者可以只编写非常小的微型驱动程序,去处理具体设备特殊的操作,而对于其他大量的常规操作,可以调用该类的类驱动程序,这也是WDM驱动程序的优点之一。微软提供的类驱动程序处理常用的系统任务,比如,即插即用功能和电源管理。类驱动程序保证了操作系统在处理类似的任务时的一致性,从而提高了系统的稳定性。设备生产商提供微型驱动程序,以实现自己设备的特殊功能,同时调用合

14、适的类驱动程序完成其他的通用工作。将大量的标准操作的代码通过各种类驱动程序来实现,并集成在操作系统中,这样的方式可以有效的减少具体设备的微型驱动程序的大小,也就减小了程序出错的可能。如果某一类设备存在着工业标准,微软就会提供一个该类设备的WDM类驱动程序。这个类驱动程序实现了该类设备所有必须的任务,但不实现任何具体设备所特有的东西。比如,微软提供的HID(人工输入设备)类驱动程序的实现,是根据USB HID 类规范的规定,但并不实现任何一种具体设备的特殊功能,比如,USB键盘、鼠标、游戏控制等等。本文所设计的驱动程序就是一个功能驱动程序,它是将USB驱动程序与微型驱动程序(Minidriver

15、)结合起来,驱动USB键盘的一个驱动程序.微软支持的WDM总线和类驱动程序图1-4 微软支持的WDM总线和类驱动程序对于图1-4,本文只描述其中的人工输入设备(HID)和USB部分。因为这是在USB键盘驱动程序设计中所涉及到的两个方面。USB总线驱动程序枚举和控制低速的USB总线。USB客户驱动程序使用各种IOCTL通过USB类驱动程序访问它们的设备。人工输入设备(HID)类驱动程序管理多种总线(如USB)间的数据与指令语法翻译。大多数时候,本类驱动控制由用户交互接口传来的数据,如键盘,鼠标和游戏杆等。 驱动程序的分层结构FiDOFiDOFDOFiDOPDO上层过滤驱动程序功能驱动程序低层过滤

16、驱动程序总线驱动程序IRP图15 WDM中设备对象和驱动程序的层次结构WDM模型使用了如图15的层次结构。图中左边是一个设备对象堆栈。设备对象是系统为帮助软件管理硬件而创建的数据结构。一个物理硬件可以有多个这样的数据结构。处于堆栈最底层的设备对象称为物理设备对象(physical device object),或简称为PDO。在设备对象堆栈的中间某处有一个对象称为功能设备对象(functional device object),或简称FDO。在FDO的上面和下面还会有一些过滤器设备对象(filter device object)。位于FDO上面的过滤器设备对象称为上层过滤器,位于FDO下面(但

17、仍在PDO之上)的过滤器设备对象称为下层过滤器。操作系统中的即插即用管理器(PnP Manager)根据设备驱动程序的指令来建立这个数据对象堆栈。前面我们已经知道,总线驱动程序的作用之一是枚举总线上的设备,当总线驱动程序检测到一个设备时,PnP管理器就马上建立一个PDO。当建立好PDO之后,PnP管理器通过查找注册表来找到其他的过滤驱动程序和功能驱动程序。设备的安装程序负责建立这些注册表里的表项,驱动程序的安装,是根据INF文件中的指令进行的。注册表中的表项指明了各种驱动程序在数据对象堆栈中的位置,于是PnP管理器开始装载最低层的过滤驱动程序,并调用该驱动程序的AddDevice函数。该函数在

18、数据对象堆栈中建立一个FiDO,同时也将前面建立的PDO和这个FiDO联系在一起。PnP管理器反复的实现该过程,装载其他位置靠上的低层过滤驱动程序、功能驱动程序、上层过滤驱动程序,直到该堆栈完成。应用程序对设备的存取通过提交IO请求包(IRP)来进行。在操作系统中,对设备的存取过程是这样的:操作系统中的IO管理器接受IO请求(通常是由用户态的应用程序发出的),建立相应的IRP来描述它,将IRP发送给合适的驱动程序,然后跟踪执行过程,当操作完成后,将返回的状态通知请求的发起者。操作系统中的IO管理器、即插即用管理器、电源管理器都使用IRP来与内核模式驱动程序、WDM驱动程序进行通信,并且,各驱动

19、程序之间的通信也是依靠IRP。在WDM驱动程序中,IRP首先从最上层进入,如图15里右手边的箭头,然后,依次往下传送。在每一层,驱动程序自行决定对IRP的处理。有时,一个驱动程序除了把继续IRP向下传递外,并不做任何事情。有时,一个驱动程序会完全接管IRP,不再把它向下传递了。当然,一个驱动程序也可以处理IRP后,再把它继续向下传递。这取决于驱动程序的功能和IRP的含义。从这里,可以知道微软在WDM模型中使用分层的驱动程序结构的原因了,通过分层的方法,在处理对设备的IO请求时,利用添加合适的驱动程序层的方法,从而非常灵活的改变设备的行为,以实现不同设备的功能。 IO请求包(IRP)操作系统使用

20、I/0请求包(IRP)数据结构与内核模式驱动程序通信。这个数据结构很重要,需要了解它的创建、发送、处理,以及最后的销毁。可以说,IO请求包(IRP)才是WDM驱动程序结构的最重点,只有真正了解处理IRP的过程,才算是真正懂得了设备驱动的原理。结构图16 I/O请求包数据结构MdlAddress(PMDL)域指向一个内存描述符表(MDL),该表描述了一个与该请求关联的用户模式缓冲区。如果顶级设备对象的Flags域为DO_DIRECT_IO,则I/O管理器为IRP_MJ_READ或IRP_MJ_WRITE请求创建这个MDL。如果一个IRP_MJ_DEVICE_CONTROL请求的控制代码指定MET

21、HOD_IN_DIRECT或METHOD_OUT_DIRECT操作方式,则I/O管理器为该请求使用的输出缓冲区创建一个MDL。MDL本身用于描述用户模式虚拟缓冲区,但它同时也含有该缓冲区锁定内存页的物理地址。为了访问用户模式缓冲区,驱动程序必须做一点额外工作。Flags(ULONG)域包含一些对驱动程序只读的标志。但这些标志与WDM驱动程序无关。AssociatedIrp(union)域是一个三指针联合。其中,与WDM驱动程序相关的指针是。 SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中。对于IRP_MJ_READ和IRP_MJ_WRITE操作,如果顶级设备

22、指定DO_BUFFERED_IO标志,则I/O管理器就创建这个数据缓冲区。对于IRP_MJ_DEVICE_CONTROL操作,如果I/O控制功能代码指出需要缓冲区(见第九章),则I/O管理器就创建这个数据缓冲区。I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,这也是创建IRP过程的一部分。这些数据可以是与WriteFile调用有关的数据,或者是DeviceIoControl调用中所谓的输入数据。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。对于指定了METHOD_BUFFERED的I/O控制操作,驱动程序把所谓的输出数

23、据放到这个缓冲区,然后I/O管理器再把数据复制到用户模式的输出缓冲区。IoStatus(IO_STATUS_BLOCK)是一个仅包含两个域的结构,驱动程序在最终完成请求时设置这个结构。域将收到一个NTSTATUS代码,而的类型为ULONG_PTR,它将收到一个信息值,该信息值的确切含义要取决于具体的IRP类型和请求完成的状态。Information域的一个公认用法是用于保存数据传输操作,如IRP_MJ_READ,的流量总计。某些PnP请求把这个域作为指向另外一个结构的指针,这个结构通常包含查询请求的结果。RequestorMode将等于一个枚举常量UserMode或KernelMode,指定原

24、始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。PendingReturned(BOOLEAN)如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。完成例程通过参考该域来避免自己与派遣例程间的潜在竞争。Cancel(BOOLEAN)如果为TRUE,则表明IoCancelIrp已被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIrp函数。取消IRP是一个相对复杂的主题,我将在本章的最后详细描述它。CancelIrql(KIRQL)是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的。当你在取消

25、例程中释放自旋锁时应参考这个域。CancelRoutine(PDRIVER_CANCEL)是驱动程序取消例程的地址。你应该使用IoSetCancelRoutine函数设置这个域而不是直接修改该域。UserBuffer(PVOID) 对于METHOD_NEITHER方式的IRP_MJ_DEVICE_CONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请求缓冲区的用户模式虚拟地址,但指定了DO_BUFFERED_IO或DO_DIRECT_IO标志的驱动程序,其读写例程通常不需要访问这个域。当处理一个METHOD_NEITHER控制操作时,驱动程序能用这个地址创建自己的MDL

26、。是Tail联合中的一种结构,它含有几个对WDM驱动程序有潜在用途的成员。由于篇幅有限,这里不再讨论。处理的“标准模型”(1)创建IRPIRP开始于某个实体调用I/O管理器函数创建它。在上图中,我使用术语“I/O管理器”来描述这个实体,尽管系统中确实有一个单独的系统部件用于创建IRP。事实上,更精确地说,应该是某个实体创建了IRP,并不是操作系统的某个例程创建了IRP。例如,你的驱动程序有时会创建IRP,而此时出现在图中第一个方框中的实体就应该是你的驱动程序。可以使用下面任何一种函数创建IRP: IoBuildAsynchronousFsdRequest 创建异步IRP(不需要等待其完成)。该

27、函数和下一个函数仅适用于创建某些类型的IRP。 IoBuildSynchronousFsdRequest 创建同步IRP(需要等待其完成)。 IoBuildDeviceIoControlRequest 创建一个同步IRP_MJ_DEVICE_CONTROL或IRP_MJ_INTERNAL_DEVICE_CONTROL请求。 IoAllocateIrp 创建上面三个函数不支持的其它种类的IRP。 前两个函数中的Fsd表明这些函数专用于文件系统驱动程序(FSD)。虽然FSD是这两个函数的主要使用者,但其它驱动程序也可以调用这些函数。DDK还公开了一个IoMakeAssociatedIrp函数,该函

28、数用于创建某些IRP的从属IRP。WDM驱动程序不应该使用这个函数。(2)发往派遣例程创建完IRP后,你可以调用IoGetNextIrpStackLocation函数获得该IRP第一个堆栈单元的指针。然后初始化这个堆栈单元。在初始化过程的最后,你需要填充MajorFunction代码。堆栈单元初始化完成后,就可以调用IoCallDriver函数把IRP发送到设备驱动程序:PDEVICE_OBJECT DeviceObject; ET作为开发工具,但是后来又转向的原因。构造环境当创建新的Makefile项目时,Visual Studio缺省提供两个build配置“Win32 Debug”和“Wi

29、n32 Release”,build命令行中的设置,根据程序所在驱动器位置的不同而需要改变。build命令行运行批处理文件,使用DDKROOT环境变量,如果在Visual Studio中请求一个完整的重新构造,把选项-nmake /a添加到这个命令行。设置输出文件名,使得在build菜单中显示正确的名字。代码清单21 Win32自由配置设置build命令行 MakeDrvr %DDKroot% e:lcsDriver checked全部重新构造选项 -nmake /a输出文件名 浏览信息文件名 objchki386如果在以上配置中,checked改为free,那么在浏览信息文件名中,应改为ob

30、jfre i386。makefile文件时必不可少的,它是一个标准文件,激活DDK inc目录中的标准构造文件。不要试图来编辑这个文件,为了把它添加到我们的工程中去,在SOURCES文件的SOURCES宏中,写入了它。代码清单22 Makefile文件内容# DO NOT EDIT THIS FILE! Edit .sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the

31、 driver components of the Windows NT DDK#!INCLUDE $(NTMAKEENV)目录与普通的生成程序不同,在Windows2000中,build分开保存自由构造版本和检查构造版本文件。如果TARGETPATH(目标路径)是OBJ,自由构造x86目标文件和最终的驱动程序进入OBJFREi386目录中,检查构造目标文件和驱动程序进入OBJCHKi386目录中,在本论文的驱动程序中,使用的是后者。在要求Visual Studio构造驱动程序时,批处理文件运行,它总是至少传递四个参数:DDK基目录,源驱动器,源目录和构造类型(“free”或“checked”

32、)。任何其他的参数直接传递给build。MakeDrvr先对传递的参数进行一些基本的检查,然后调用DDK setenv命令为build目录正确设置环境变量,改变目录为源驱动器和目录,最后调用build。-b选项保证显示完全的错误文本,-w选项保证在屏幕输出上出现警告,可以在Visual Studio的build Output窗口中发现它们。MakeDrvr命令文件的屏幕输出出现在Visual Studio Output窗口中。代码清单23 MakeDrvr文件echo offif %1= goto usageif %3= goto usageif not exist %1bin goto us

33、agecall %1binsetenv %1 %4%2cd %3build -b -w %5 %6 %7 %8 %9goto exit:usageecho usage MakeDrvr DDK_dir Driver_Drive Driver_Dir free/checked build_optionsecho eg MakeDrvr %DDKROOT% C: %WDMBOOK% free -cef:exit的使用驱动程序没有任何保护,因为它是内核的一部分,要特别仔细地完全测试驱动程序,否则会丢失数据。驱动程序出错的方式有以下几种。崩溃内核转储驱动程序不启动挂起资源遗漏时间依赖性DebugPri

34、nt软件用来允许我们使用格式化的打印语句跟踪驱动程序的执行。详细的信息来自于。首先我安装了DebugPrint驱动程序,安装方法于安装驱动程序类似。它的用户态监视程序监视测试驱动程序的打印跟踪事件。在程序中使用DebugPrint的方法如下:首先我们要把和这两个标准文件复制到驱动程序项目中,然后在驱动程序的主头文件中包括。修改SOURCES文件,使得被构造。驱动程序中调用DebugPrint函数,只能在DISPATCH_LEVEL或更低的IRQL调用这些函数,这意味着可以在DriverEntry例程,主IRP分发例程和StartIo及延迟过程调用(DPC)例程中调用DebugPrint函数,但

35、不能在中断处理例程中调用。DebugPrintInit例程必须在PASSIVE_LEVEL IRQL调用。DebugPrint调用在驱动程序的执行中只引起很小的延迟,DebugPrint调用的主要工作在以低实时优先级在后台运行的系统线程中发生。在本论文的驱动程序代码中一个典型的例子如下:代码清单24 DebugPrint调用实例NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject , IN PUNICODE_STRING RegistryPath)#if DBG DebugPrintInit(Lcs_Kbd checked );#elseDeb

36、ugPrintInit(Lcs_Kbd free );.3 使用USB USB类概述图31 主要的USB类图31列出了主要的USB设备类,由图中我们可以看出人工输入设备类(HID类)与USB类是有关系的,在下一章中,可以看出HID类和USB类的关系远不止如此。事实上,HID协议本来就是USB协议的一个子部分,最初的时候HID是因USB而生,但是现在它的作用不止如此。当然HID设备是不一定在USB上运行的,但是因为一些特定的关系,它们能够很好的适合于USB设备模型。访问USB键盘的实现 的IOCTL使用Windows USB驱动程序接口(USBDI),可以编写访问USB键盘的驱动程序,并读取原始

37、键盘输入数据。并可以对键盘进行控制,使得键盘上的LED灯发光或是熄灭。Windows 2000使用的是USBDI 版,因为这个驱动程序中并没有用到WMI(Windows Management Instrumentation)数据,所以受版本的影响不大。表31中是USB驱动程序接口的内部IOCTL。表31 USB驱动程序接口的内部IOCTLIOCTL_INTERNAL_USB_SUBMIT_URB 发出URB停止等待结果IOCTL_INTERNAL_USB_RESET_PORT 复位并重新启用一个端口IOCTL_INTERNAL_USB_GET_PORT_STATUS 得到状态位: USBD_P

38、ORT_ENABLED USBD_PORT_CONNECTEDIOCTL_INTERNAL_USB_ENABLE_PORT 重新启用一个被禁止的端口IOCTL_INTERNAL_USB_GET_HUB_COUNT 集线器驱动程序内部使用IOCTL_INTERNAL_USB_CYCLE_PORT模拟设备拔出和再次插入IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO集线器驱动程序内部使用IOCTL_INTERNAL_USB_GET_HUB_NAME 得到集线器驱动程序的设备名IOCTL_INTERNAL_USB_GET_BUS_INFO 获得USB总线信息IOCTL_INTER

39、NAL_USB_GET_CONTROLLER_NAME 得到主机控制器设备名最重要的内部IOCTL是IOCTL_INTERNAL_USB_SUBMIT_URB,它发出USB请求块(URB)由USB类驱动程序处理。有30多个不同的URB功能代码。USB客户使用URB做它们大多数的工作。URB结构是一个联合,含有16个不同的_URB_*结构。使用USBDI访问USB键盘 对一个USB键盘来说,它有这么几种操作,复位设备,配置设备,和读写设备。在使用USB设备之前,第一件事就是要复位它,来确保它可用。然后主机负责配置设备。配置设备的过程与物理特性相关。在USB键盘的配置中,我们所要做的是获得设备的配

40、置描述符,然后找出接口,设备接口的每个管道的最大传输数据包为8,创建配置设备的URB请求发送给USBDI。 具体的配置过程在第五章中描述,在这里主要涉及的是,如何使用USBDI。USB设备驱动程序从不直接与硬件对话。它仅靠创建URB(USB请求块)并把URB提交到总线驱动程序就可完成硬件操作。系统当中的文件,是接受URB的实体。向USBD的调用被转化为带有主功能代码为IRP_MJ_INTERNAL_DEVICE_CONTROL的IRP。然后USBD再调度总线时间,发出URB中指定的操作。(1)为了创建一个URB,首先应该为URB分配内存,然后调用初始化例程把URB结构中的各个域填入请求要求的内

41、容(2)创建完URB后,你需要创建并发送一个内部I/O控制(IOCTL)请求到USBD驱动程序,USBD驱动程序位于驱动程序层次结构的低端。在大多数情况下,你需要等待设备回应。(3)当提交一个URB到USB总线驱动程序时,最终将收到一个描述该操作结果的NTSTATUS代码。当USBD完成一个URB时,它就把URB的域设置为某个USBD_STATUS值。DDK中的URB_STATUS宏可以简化这个值的存取。这就是调用USBDI的完整过程。 USB键盘的一个特点这个问题本来可以在后面inf文件的部分予以说明,但是因为设计到USB,所以在这里描述。下面是标准安装文件中的一部分,它的意思是,这个设备驱

42、动程序所对应的设备属于USB类,ClassGUID给出的是设备的标识符。Class=USBClassGUID=36FC9E60-C465-11CF-40000替代Windows 2000中的键盘驱动,用这样的配置文件是不可能的,Windows 2000有对USB键盘的内置支持,在这两个操作系统中,它们装入人工输入设备(HID)类驱动程序,然后标准键盘驱动程序通过HID客户驱动程序得到键输入。有两种方法可以使生成的.sys文件得以安装到系统中,第一种来自于一本描述Windows 2000 wdm驱动程序设计的书,在参考书目中列出了它的具体信息。这个方法是将用生成的.sys文件(本设计中是)替换H

43、ID USB小驱动程序。Windows使用处理HID USB设备,这种替换是可以的,但是却使用户不能使用USB键盘进行常规的输入。另外一种方法是将标准安装文件改为:Class=KeyboardClassGUID=4D36E96B-E325-11CE-BFC1-08002BE103184 HID小驱动程序实现 人工输入设备模型(HID),是与用户输入设备交互的标准方法,HID设备使用各种描述符定义它的功能。报告描述符详细说明它可以产生的输入报告呵可以接收的输出报告。HID规范是用于控制计算机的大多数人工输入设备的抽象模型,例如,一个输入设备可以是普通的老式键盘,汽车模拟方向盘或计算机的软开关按钮

44、。HID规范一开始是为USB设备写的,紧密遵循USB描述符,这就是为什么上面说HID设备可以很好的遵循USB的原因,但是HID用于其它类型的设备是非常常见的。HID设备大多数时候为计算机提供输入数据,但是,也可以输出到HID设备(如打开键盘上的LED灯)。以可以控制设备的特性,如用于现实设备的字体或者LED颜色,但是这些不在本设计的范围之内了。在Windows中,系统HID类驱动程序提供输入设备的一个抽象视图。HID设备自身可以是USB设备,IEEE 1394设备,甚至只要为普通的PC兼容的设备编写一个合适的HID小驱动程序与总线或设备接口,它也可以成为HID设备。图41 驱动程序结构图图41

45、说明了在Windows中,HID设备是如何被使用的。首先从输入说起,HID提供输入设备的一个抽象模型,这样客户程序不关心输入来自什么地方。HID把一个设备描述为代表该设备的各种控制。本论文所涉及到的是键盘,对于一个键盘,它通常是有单个位控制,代表每个修饰键的状态,并且有一个扫描代码字节控制数据,代表目前按下的其他键。系统HID类驱动程序做大多数的工作,它把它的硬件交互委托给HID小驱动程序,Windows包括一个用于USB总线上的设备的HID小驱动程序,有合适的HID接口类常量和HID描述符的新USB设备不需要新的小驱动程序。系统USB HID小驱动程序调用系统USB驱动程序,可选的通过所有低

46、层USB过滤驱动程序,然后系统USB驱动程序访问设备。所以现在可以得出我将要在详细设计里描述的键盘驱动程序的大致结构,HID客户只访问HID类驱动程序,HID小驱动程序调用USB驱动程序接口(USBDI),这样得以实现一个完整的键盘驱动程序。 HID概述HID小驱动程序需要返回特定的数据结构给HID类驱动程序,告诉它设备的功能。对于许多新设备来说,它们由设备自身提供。关键的数据结构是:HID描述符设备属性报告描述符身体部位描述符字符串描述符在本论文中,只介绍跟本驱动程序最为相关的HID描述符和报告描述符。 HID模型描述符HID描述符提供关于设备的第一个信息,它主要确认这是一个HID设备,并提

47、供其报告描述符的长度和所有身体部位描述符。表中给出了HID_DESCRIPTOR结构以及典型的值。DescriptorList域通常只有一个元素,详细说明报告描述符和它的长度。但是,它也可以指定身体部位描述符,提供关于激活设备上的控制的人类身体部位的信息。图42 HID描述符结构本论文所设计的驱动程序使用倒的HID描述符,基本上和上表中是一样的。它们的值在最右边的一栏。bLength标识HID描述符的长度为9,bDescriptorType表明描述符的类型是HID_HID_DESCRIPTOR_TYPE,后面跟着的0 x21,是它的宏。bcdHID是HID规范版本,它的值是0 x0100,国家

48、代码为bCountry,值是0,未指定的意思就是任何国家都可以使用。bNumDescriptors所代表的值,是指在系统中用到了除本描述符之外的几个描述符,在本论文设计的驱动程序中,用到了另外一个报告描述符,结构如下:struct _HID_DESCRIPTOR_DESC_LISTUCHAR bDescriptorType; .DriverEntry的第一个参数是一个指针,指向一个刚被初始化的驱动程序对象,该对象就代表你的驱动程序。WDM驱动程序的DriverEntry例程应完成对这个对象的初始化并返回。DriverEntry的第二个参数是设备服务键的键名。这个串不是长期存在的(函数返回后可能

49、消失),如果以后想使用该串就必须先把它复制到安全的地方。对于WDM驱动程序的DriverEntry例程,其主要工作是把各种函数指针填入驱动程序对象。这些指针为操作系统指明了驱动程序容器中各种子例程的位置。它们包括下面这些指针成员(驱动程序对象中): DriverUnload 指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。 DriverExtension-AddDevice 指向驱动程序的AddDevice函数。PnP管理器将为每个硬件实例调用一次Add

50、Device例程。DriverStartIo 如果驱动程序使用标准的IRP排队方式,应该设置该成员,使其指向驱动程序的StartIo例程。 MajorFunction 是一个指针数组,I/O管理器把每个数组元素都初始化成指向一个哑派遣函数,这个哑派遣函数仅返回失败。驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相对应的指针元素,使它们指向相应的派遣函数。 例程与实现通常,一个驱动程序可以被多个设备利用。WDM驱动程序有一个特殊的AddDevice函数,PnP管理器为每个设备实例调用该函数。该函数的原型如下:NTSTATUS AddDevice(PDRIVER_OBJ

51、ECT DriverObject, PDEVICE_OBJECT pdo)DriverObject参数指向一个驱动程序对象,就是你在DriverEntry例程中初始化的那个驱动程序对象。pdo参数指向设备堆栈底部的物理设备对象。对于功能驱动程序,其AddDevice函数的基本职责是创建一个设备对象并把它连接到以pdo为底的设备堆栈中。相关步骤如下: (1)调用IoCreateDevice创建设备对象,并建立一个私有的设备扩展对象。 (2)寄存一个或多个设备接口,以便应用程序能知道设备的存在。另外,还可以给出设备名并创建符号连接。 (3)初始化设备扩展和设备对象的Flag成员。 (4)调用IoA

52、ttachDeviceToDeviceStack函数把新设备对象放到堆栈上。例程与实现Dispatch例程由I/O管理器定义如下:NTSTATUS(*PDRIVER_DISPATCH) (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);通常,大多数驱动程序必须处理一些或者所有以下请求:LRP_MJ_PNP表明一个包括PnP设备识别的请求,硬件配置,或者资源分配的请求。这类请求显然从PnP管理器或者从一个与较高层驱动程序密切相关的设备发送到一个设备驱动程序。IRP_MJ_POWER表明一个属于设备或者系统的电源状态请求。这类请求通过电源管理器或者一个密切连

53、接的较高层驱动程序发送到设备驱动程序。IRP_MJ_CREATE表明用户模式保护子系统,可能代表应用或者特定子系统驱动程序,已请求一个与目标设备对象有关的文件对象的控制,或者一个较高层的驱动程序把其设备对象连接或者附加到目标设备对象。IRP_MJ_CLEANUP表明,为代表目标设备对象的文件对象的处理被关闭,因此任何在清除IRP的驱动程序I/O栈位置中找到的,在给定文件对象目标设备的当前队列中的IRP,应该被取消。IRP_MJ_CLOSE表明代表目标设备对象的文件对象句柄或指向目标设备对象的指针已经被关闭,还表明没有未完成的、对文件对象指针的引用。IRP_MJ_READ表明I/O请求从下层物理

54、设备向系统传输数据。IRP_MJ_WRITE表明I/O请求从系统向下层物理设备传输数据。IRP_MJ_DEVlCE_CONTROL表明一个带有系统定义的,指定一个被发送给设备驱动程序的具体设备操作的特定设备类型I/O控制码的请求。IRP_MJ_INTERNAL_DEVICE_CONTROL表明一个传给设备驱动程序的请求,大多数情况下是来自一个紧密连接的较高层驱动程序,通常带有一个私有的、驱动程序特定的及特定设备类型的或特定设备的I/O控制码,该控制码请求一项特定设备类型的或特定设备的操作。仅仅某些种类的驱动程序要去处理系统定义的内部设备I/O控制请求,包括SCSI驱动程序,键盘或鼠标设备驱动程

55、序,及与系统支持的驱动程序进行互操作的并行驱动程序。任何驱动程序都必须在驱动程序对象中设置的Dispatch例程入口点根据下层物理设备的类型和功能的不同而不同。在本论文所涉及的驱动中,用到了LRP_MJ_PNP例程,它实现了USB键盘的即插即用功能。例程与实现StartIo例程由I/O管理器定义如下:VOID( *PDRIVER_STARTIO) ( IN PDRIVER_OBJECT DeviceObject, IN PIRP Irp );StartIo例程运行在位于IRQLDISPATCH_LEVEL上的任意线程环境中。运行在IRQLDISPATCH_LEVEL上限制了这组StartIo例

56、程可以调用的支持例程。因此我们需要在一个系统线程中调用StartIo例程,关于系统线程,因为在本毕业设计中用到的地方较少,会用很少的篇幅来讨论它。Windows NT/Windows 2000在多任务及多线程环境中支持异步I/O,I/O请求可以比驱动程序处理完成更快地到达,特别是在一个多处理器的机器中。因此,任何具体设备在忙与处理另一个IRP时,必须让超出限度的IRP在驱动程序上排队。因此,最低层驱动程序必需以下之一:StartIo例程,I/O管理器用一个IRP调用它来启动一个该驱动程序的设备上的I/O操作它自己的IRP排队机制,它用来控制比驱动程序的处理速度更快地到达的IRP仅有一个最低层设

57、备驱动程序能在其Dispatch例程中满足和完成所有可能的IRP,而不需要StartIo例程和/或驱动程序管理的IRP队列.较高层驱动程序几乎从来没有StartIo例程。大多数中间层驱动程序也没有内部队列;一个中间层驱动程序通常从其Dispatch例程传送带有效参数的IRP,并且为任何其IoCompletion例程中的IRP做必要的处理后操作。大多数设备驱动程序有StartIo例程,因为大多数PC外设同时仅能处理一个设备I/O操作。对于有一个StartIo例程的驱动程序,I/O管理器提供IoStartPacket和IoStartNextPacket来管理驱动程序中的IRP队列。例程与实现I/O

58、管理器对IoCompletion例程的定义如下:NTSTATUS *PIO_COMPLETION_ROUTINE( IN PDEVICE_OBJEXT DeviceObject, IN PIRP Irp, IN PVOID Context );高层驱动程序完成各种操作的IRP需要多少个IoCompletion例程,就可以建立多少个IoCompletion例程。IoCompletion例程是运行在等于或低于DISPATCH_LEVEL的IRQL上和专用线程环境中的。驱动程序无法预先知道IoCompletion例程将在哪一级IRQL上被调用。本论文涉及到的程序中,处理IRP_MN_START_DE

59、VICE例程的时候,用到了完成例程。例程与实现任何在系统运行时可以被替换或卸载并重载的驱动程序都必须有Unload例程。I/O管理器对Unload例程的定义如下:VOID(*PDRIVER_UNLOAD)( IN PDRIVER_OBJECT DriverObject );DriverObject参数是传递给驱动程序的DriverEntry例程的指针。视频、键盘或鼠标设备和能保存系统当前页文件的海量存储设备的驱动程序没有Unload例程,因为这些类型的设备必须在当前系统运行时始终可用。位于这些设备驱动程序之上的高层驱动程序也没有Unload例程。Unload例程负责在驱动程序自身被卸载之前释放

60、驱动程序使用的所有系统对象和资源。像DriverEntry例程一样,Unload例程运行在PASSIVE_LEVEL上并在系统线程的环境中被调用。在本论文涉及到的程序中,DriverEntry例程没有分配资源,因此Unload例程并没有用到,但是了解它,也是很有意义的。 实现即插即用即插即用即插即用不是一个简单的问题,它的具体实现有许多方面。为了有一个总体上的概念,我将介绍一个即插即用的系统应该能满足的以下两个目标:(1)当新的设备加入系统时,处理这些新设备。可以在软件中配置的设备必须被告知使用哪些资源和地址。(2)通过提供标准驱动程序,使驱动程序更容易访问复杂的设备。对于通用串行总线这样的相

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论