2024年1月10日发(作者:)

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用摘要w.mdows2000/)(PⅣISTA已经成为PC的主流操作系统,要想实现在Windows操作系统下对硬件设备的操作,必须通过在WDM模型下设计的驱动程序这个软接口。随着USB2.0的发展,运用USB这种具有热插拔,高速率等优点的接口设备已开始流行。Windows驱动程序模型WDM(WindowsDriverModel)是一种全新的设备驱动程序模式,可以运行于windows98/2000/)(P等多种操作系统平台。WDM采用模块化、分层次类型的驱动程序结构。作为一种符合WDM的驱动程序,USB驱动程序分为USB总线驱动程序和USB功能驱动程序两个层次。USB总线驱动程序负责控制实际的硬件,实现与底层的通信。USB功能驱动程序由设备开发者编写,位于USB总线驱动程序的上层,通过向USB总线驱动程序发送USB请求包,来实现对USB设备信息的发送或接收。本文以运用EZ—USB芯片的卫星视频接收设备为例,论述了如何运用DDK工具包,开发USB设备WDM驱动程序。重点介绍了USB驱动程序中“DriverEntry”、添加设备例程、即插即用处理例程、读写操作例程等几个重要例程的设计实现,以及应用程序如何访问设备。并介绍了编译、安装及测试USB设备驱动程序的过程。为适应不同版本的晰ndows操作系统(如WindowsVISTA),将接收卡驱动程序在各类Windows操作系统下出现的一些新问题,进行了处理。本文首先介绍了驱动程序开发的历史、WDM基本概念及Windows驱动程序的种类,并对USB技术和开发驱动工具做了简单介绍。第二章讨论了WDM的层次结构模型,驱动程序的加载流程以及几个重要的数据结构。第三章分析了WDM的数据读写方式及中断的处理方式。第四章对WDM的一般处理流程进行了介绍。第五章详细介绍了卫星视频信号接收卡设备的驱动程序开发及对程序中的重要代码进行了列举与讲解,并对某些错误及其处理进行了列举。第六章对本文的一个总结。关键词:Windows,USB,WDM,驱动程序,例程

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用AbstractWindows2000/XP/VISTAhasbecomethemainstreamofPCoperatingsystem.InordercontrolthehardwareunderthetoWindowsoperatingsystem,softInterfaceofdesigningunderofUSB2.0.USBequipmenthasstartedtoWDMmodelmustbeadopted.WiththedevelopmentpopbecauseoftheadvantagesofUSBsuchashot-swappableandhi曲-speed.Windowsrunondrivermodel.WDMiSanentirelynewmodelofdevicedrivers。itCanbesuchastheoperationsystemaWindows98/2000/)(P.WDMtakesthemodular,layereddriverstructure.AspartofWindowsDriverModel。USBdriverdevicedriversiSdepartedtotwolayered.oneiSUSBBusdeviceandtheotheriSUSBFunctiondevicedriver.TheUSBBusdevicedrivertakeschargeofcontrolandcommunicateswithhardware,USBFunctiondevicedriveriSdesignedbyclient。itliestheuplayerofUSBBusdevicedrivelitsendsandreceivesinformationfromUSBdevicebysendURBtoUSBBusdevicedriver.ThispapertakesatellitevideoreceivingequipmentEZ.USBchipasuseanexample.describeshowtouseDDKKittodevelopWDMDriverofUSBdevices.MostlYintroducessomeimportantroutinesuchas“DriverEntry'’routine.adddeviceroutine,plugandplayprocessroutine,readaccessorwriteroutine.Andapplicationprogramshowtodevice.Andintroducescompile.installanddebugprocessofUSBdriverdevices.TomeetthedifferentversionsoftheWindowsoperatingsystem(suchasproblemsthatdriverofreceivingcardrunningunderdeferentdealtwith.WindowsVISTA),somenewWindowsoperatingsystemwasAtfirst,thepaperintroducesthehistoryofdevicedrivesdevelopment,basicconceptofWDMandtypesofWindowsdevicedrivers.andintroducestheUSBtechnology,driverdevelopmenttools.Chapter2discussesthelayeredarchitecturemodelofWDMandlpadflowofdevicedriversandsomeimportantdatastructure.Chapter3analyzesdataaccessmethodandinterruptsprocessofWDM.Chapter4introducesthegenerMprocessesofWDM.Chapter5detaileddescribesthedevelopmentofsatellitevideoandsomeimportantproceduralcodecited.Chapter6givesKeyaonsignalreceivingcardUSBdevicedriverserrorsthelistareexplained.someandtheirtreatmentareconclusion.words:Windows.USB。WDM,Drivers,Routine

学位论文独创性声明本人郑重声明:l、坚持以“求实、创新”的科学精神从事研究工作。2、本论文是我个人在导师指导下进行的研究工作和取得的研究成果。3、本论文中除引文外,所有实验、数据和有关材料均是真实的。4、本论文中除引文和致谢的内容外,不包含其他人或其它机构已经发表或撰写过的研究成果。5、其他同志对本研究所做的贡献均已在论文中作了声明并表示了谢意。作者签名:日期:j耋211£:占:2』学位论文使用授权声明本人完全了解南京信息工程大学有关保留、使用学位论文的规定,学校有权保留学位论文并向国家主管部门或其指定机构送交论文的电子版和纸质版:有权将学位论文用于非赢利目的的少量复制并允许论文进入学校图书馆被查阅;有权将学位论文的内容编入有关数据库进行检索:有权将学位论文的标题和摘要汇编出版。保密的学位论文在解密后适用本规定。、互作者签名:!鎏

关于学位论文使用授权的说明本人完全了解南京信息工程大学有关保留、使用学位论文的规定,即:学校有权保留送交论文的复印件,允许论文被查阅和借阅;学校可以公布论文的全部或部分内容,可以采用影印、缩印或其他复制手段保存论文。(保密的论文在解密后应遵循此规定)作者签名:日期:导师签名:日期:

南京信息工程大学硕士学位论文基于Windows的USB接121WDM驱动研究和应用第一章绪论在Windows操作系统中,驱动程序能让设备看起来像是一个文件,可以打开设备的一个句柄,然后应用程序可以在设备句柄最后关闭之前向驱动程序发出读写请求。设备驱动程序是操作系统的一个信任部分,提供连接到计算机的硬件的软件接El,用户不必考虑如何控制硬件,便可让应用程序以一种规范的方式访问硬件,而不必考虑如何控制硬件。驱动程序作为一个软件,在装入后成为操作系统内核的一部分。它使一个或多个设备可用于用户态程序,每个设备代表一个物理的或逻辑的硬件。一个完整的Windows驱动程序要完成以下工作:初始化;创建和删除设备;处理Win32打开和关闭文件旬柄的请求:处理Win32输入/输出请求;串行化对设备的访问;访问硬件;调用其他驱动程序;取消I/0请求;超时I/0请求;处理一个可热拔插的设备被加入或删除的情况:处理电源管理请求;使用WindowsManagementInstrumentation(Windows管理诊断,WMI)和NT事件向系统管理员报告。,1.1Windows设备驱动程序发展历史微软已经发布了很多版本的Windows操作系统,从开始的Windows3.0到Windows2000和WindowsXP,以及到最近发布的全新操作系统W'mdowsVista。一些底层的技术一直在各个Windows平台下共享,而其它的一些技术随版本的不同有了很大的变化。由于设备驱动程序是与操作系统最低层的功能发生交互,因此,如果要实现跨平台的兼容,首先必须在不同平台的底层结构上做到兼容。Window3.0的基本结构一直延续到W'mdows9X家族,虽然后来的操作系统在驱动程序的开发和管理上有了非常大的改变,但底层的基本结构没有变化。在Windows3.x、Windows95和Windows98下使用的是虚拟设备驱动(VirtualDeviceDriver),也称为VxD。虚拟设备驱动程序,原来的设计目标是为了支持在Windows平台下的设备,它作为动态连接库(DLL)链接到操作系统里,工作在保护模式下(Rin90)。VxD解决了那些常规应用程序不能完成的工作,比如直接硬件的读写,也可以说,使用VxD是扩展操作系统内核的一种方法。VxD最初的编写采用的是Intel汇编语言,后来随着VtoolsD的使用,使用C和C++也开始流行起来。WindowsNT的设计体现更现代和模块化的内部体系,它的目标是更好的灵活性和更加的健壮。NT采用了一种特有的内核模式驱动程序体系,一般也采用C语言来编写。当NT下的驱动程序需要直接控制机器时,它会向硬件抽象层(HAL)发出请求。硬件抽象层建立在驱动程序和实际的硬件之间,为驱动程序隐藏了硬件的不同,这样就可以编制出跨处理器(比如Pentium和Alpha)、源代码兼容的设备驱动程序。因为WindowsNT可以工作在单处理器和多处理器环境中,驱动程序必须十分小心的保护关键的数据结构。WindowsNT提供了一种分层的体系结构,每一个NT设备驱动

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用程序有一个底层和一个上层接口。底层的驱动程序直接控制硬件。在底层和上层驱动程序之间的是中间层驱动程序。WindowsNT也定义了一种类驱动程序体系,并且支持某些设备类。WindowsNT的这种驱动程序体系,在Windows98和Mndows2000ⅨP/VISTA中得到了继承和扩展,形成了现在的WDM体系。认识到跨平台兼容能力的价值后,微软开始尝试统一设备体系,给未来的驱动程序开发提供一个简单的平台。微软的做法,不是重新开发一套新的体系,而是在更合理的WindowsNT体系的基础上,进行必要的完善,从而形成一个新的设备驱动程序体系,称为WindowsDriverModel(Windows驱动程序模型,wDM)这个名字。Windows98最先支持WDM,随后推出的操作系统中也都支持WDM,包括Windows2000系列,WindowsMe和WindowsXP,VISl’A。1.2WDM驱动程序简介编写硬件设备驱动程序一直是一种具有很强挑战性的复杂工作,即便是编写过具有相当难度的Win32程序的开发人员,在编写设备驱动程序时也必须去应对种种不适。编写设备驱动程序很像在执行一项艰巨的任务:没有窗口、没有消息需要处理,很难对源代码进行调试设置,几乎所有支持库都无法调用;更加糟糕的是由于设备驱动程序属于操作系统的信任部分,于是很容易伤害系统,对此开发人员却往往缺乏一种保护手段去防止进程、线程以及Windows系统故障。WDM(Windowsdrivermodel)是微软为开发人员提供的一种编写运行在Windows平台下新硬件驱动程序的有效方法,这就是Windows驱动程序模型。WDM提供了设备类(deviceclasses),由此形成的源代码可以运行在各类Windows平台:winⅥsta/XP/2000/Me/98。WDM是一种便携式的编程技术,它使开发人员写出的驱动程序可以跨平台运行,支持编写微软所有支持的WDM总线驱动程序,在WDM中总线的概念是一种附加在其它设备(包括物理设备、逻辑设备、虚拟设备)上的设备协议。例如WindowsXP内置的WDM技术支持的总线类型包括:PO(PeripheralComponentInterconnect)、动态式即插即用串行I/O总线(如USB和IEEEl394),scsi(SmallComputerSystemInterface)、NDIS(NetworkDriverInterfaceSpecification)以及远程式NDlS(RNDIS)。新版WDM中的RNDIS属于新内容:如简化了对网络设备硬件的开发,减弱了网络设备对驱动程序的依赖性,使最终用户对网络设备的设置安装更简便。WDM新版中对设备的支持主要包括:USB设备类,例如其中的HID(HumanInterfaceDevice);数码相机/扫描仪;通过IEEEl394标准的视频捕捉设备;音频:控制调制解调器的WinModem。在WDM类代码中提供的port/miniport驱动范文,支持第三方厂商为其特殊设备编写的“迷你型”驱动minidriver。现将WDM的特点总结如下:-2.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用1.支持即插即用(pap)和电源管理即插即用是指外部设备可以在系统运行时添加或者删除,操作系统可以在任何时候分配设备需要的硬件资源。WDM驱动程序支持即插即用,因而可以动态配置设备。电源管理是指设备对系统电源的使用情况是动态变化的。WDM驱动程序支持设备的电源管理,使得设备对系统电源的使用情况同设备所处的工作状态相关。操作系统通过发送IRP请求,通知外部设备进行资源配置和电源管理,这些IRP主函数的代码分别为IRPMJPNP和IRP—MJ—POWER。针对每个主函数代码还有详细的次函数代码,表明系统对设备进行的详细操作和请求。WDM设备驱动程序中有响应这些IRP请求的分发例程。2.支持WMIWMI是WindowsManagementInstrumentation的缩写,是一种向系统管理员报告管理信息的协议,这个协议能测量和管理消耗在本地或者是网络中客户机上的资源信息。WDM驱动程序必须支持WMI,一般这种请求是通过IRPMJSYSTEMCONTROL请求传递给PDO(物理设备对象)的,支持WMI的驱动程序具有这样特点:可以测试应用程序性能、配置数据和其它信息;可以允许应用程序改变驱动程序中的设置,使得驱动程序执行特定功能;可以通知应用程序,驱动程序检测到哪些事件或者警告信息。3.支持类驱动程序/微驱动程序分层结构WDM驱动程序采用分层结构,可和其它驱动程序相联系,接收建立在其他驱动程序上的服务,也可向其它驱动程序发送IRP请求。WDM驱动程序模型支持类驱动程序/微驱动程序。类驱动程序是针对一个特定类设备的驱动程序,处理针对这一类设备的IRP请求。类设备驱动程序向上为这一类设备提供了基于IRP的接口,向下对一个或者多个微驱动程序定义了接口。而微驱动程序主要任务是为特定驱动程序提供服务。4.提供系统总线驱动程序WDM环境提供了系统总线驱动程序,通过系统总线驱动程序,设备驱动程序实现对物理设备的底层控制和资源配置。驱动程序依靠PDO(物理设备对象)存取系统总线驱动程序,一个FDO(功能设备对象)通过向PDO发送IRP,实现和总线驱动程序的通信。1.3分类Windows驱动程序Windows操作系统中包含很多种驱动程序,可以将这些驱动程序分为用户模式驱动程序和内核模式驱动程序两大类。图1。1中列出了其中的一部分。用户模式驱动程序包含了Win32多媒体驱动程序,支持MS—DOS应用程序的虚拟设备驱动程序(VirtualDeviceDriver.VDD)和其他保护子系统的驱动程序。VDD是用户模式部件,它可以使DOS应用程序访问x86平台上的硬件,VDD通过屏蔽I/O权限掩码来捕获端口访问操作,它基本上是模拟硬件操作。.3.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用圈1.1Windows驱动程序种类内核模式驱动程序使用系统级代码编写,且运行在内核模式下,因为内核模式允许直接访问硬件,这些驱动程序被用来直接控制硬件。内核模式驱动程序包含了许多子类:1.PIlP驱动程序就是一种遵循W'mdows即插即用协议的内核模式驱动程序。2.WDM驱动程序是一种PIlP驱动程序,它同时还遵循电源管理协议,并能在Windows98和Windows2000间实现源代码级兼容。WDM驱动程序还细分为类驱动程序(classdriver)和迷你驱动程序(minidriver),类驱动程序管理属于已定义类的设备,迷你驱动程序向类驱动程序提供厂商专有的支持。3.小端口驱动程序(miniportdriver),包括视频小端口驱动程序,SCSI小端口驱动程序和NDIS小端口驱动程序。4.文件系统驱动程序(FSD)在本地硬盘或网络上实现标准Pc文件系统模型,包括多层次目录结构和命名文件概念。1.4USB设备驱动程序简介USB设备驱动程序是基于WDM结构之上的。WDM的分层驱动程序结构在USB设备上体现在驱动程序分为USB总线驱动程序和USB功能驱动程序两个层次。USB总线驱动程序一般由win98或更高的操作系统提供,它位于USB功能驱动程序的下面,负责与实际的硬件打交道,实现烦琐的底层通信。USB功能驱动程序(也称为用户自定义驱动)由设备开发者编写,位于USB总线驱动程序的上层,不与实际的硬件打交道,而是通过向.4.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用USB总线驱动程序发送包含URB(USB设备信息的发送或接收。RequestBlock请求块)的IRP请求包,来实现对USB1.5USB技术的特点(1)操作简便,即插即用。因为USB接口支持热插拔,用户在使用外接设备时,不需要关机安装硬件后再开机安装驱动程序,只需直接将USB接口插上PC机的接口。USB接口为连接电缆和连接头提供了单一的模型,支持自我检测外设,自动地进行设备驱动设置。而过去的串口和并口只能接一个设备,并且从一个设备转而使用另一个设备时必须关机后才能进行。USB设计的驱动程序和应用软件可以自动启动,无需用户做更多的操作,为用户带来极大的方便。USB设备也不涉及IRQ冲突问题。USB口单独使用自己的保留中断,不会同其它设备争用PC机有限的资源,同样为用户省去了硬件配置的烦恼。(2)成本低廉,携带方便。USB接口以低廉的价格提供1.5Mbps的子通道设施将外设和主机硬件进行了最优化的集成促进了低价格外设的发展廉价的电缆和连接头。USB设备大多以“小、轻、薄”见长,对用户来说,同样20G的硬盘,USB硬盘比IDE硬盘要轻一半的重量,在想要随身携带大量数据时,当然USB硬盘会是首选了。(3)标准统一。大家常见的是IDE接口的硬盘,,串口的鼠标键盘,并口的打印机扫描仪,可是有USB之后,这些应用外设统统可以用同样的标准与PC连接,这时工程硕士学位论文接口通信协议研究和接口驱动开发就有了USB硬盘、USB鼠标、USB打印机,等等。(4)可以连接多个设备。USB接口适应不同的设备,并支持对多个设备的同时操作,在主机和设备之间可以利用底层协议传输多个数据和信息流,提高了总线利用率。USB在PC上往往具有多个接口,可以同时连接几个设备,如果接上一个有4个端口的USBHUB时,就可以再连上4个USB设备,以此类推,尽可以连下去,将你家的设备都同时连在一台PC上而不会有任何问题(最高可连接至127个设备)。USB采用“级联”方式,即每个USB设备用一个USB插头连接到一个外设的USB插座上,而其本身又提供一个USB插座供下一个外设连接用。通过这种类似菊花链式的连接,一个USB控制器可以连接多达127个外设,而每个外设间距离线缆长度可达5米。USB能智能识别USB链上外围设备的插入或拆卸,USB为PC的外设扩充提供了一个很好的解决方案。(5)同步传输带宽,确定的带宽和低延迟适合电话系统和音频的应用同步工作可以利用整个总线带宽。可以选择一系列大小的数据包,允许对设备缓冲区大小进行选择通过指定数据缓冲区大小和执行时间,支持各种数据传输率;通过协议对数据流进行缓冲处理。(6)可靠性。在协议中使用出错处/理差错恢复机制,可以对有缺陷设备进行认定。与.5.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用PC机即插即用的体系结构的一致;对现存操作系统接口的良好衔接。(7)传输速度快。速度性能是USB技术的突出特点之一。USBl.1支持两种传输速率:1.5Mbps和12Mbps,比串口快了整整100倍,比并口也快了十多倍,主要应用在中低速传输要求的场合。2000年发布的USB2.0规范提供了480Mbps的传输速率,以满足更快的数据传输要求。目前2.0已经广泛投入使用。(8)独立供电,生产成本低。普通的使用串口、并口的设备都需要单独的供电系统,而USB设备则不需要,因为USB接口提供了内置电源。USB电源能向低压设备提供5伏的电源,因此新的设备就不需要专门的交流电源了,从而降低了这些设备的成本并提高了性价比。(9)支持多媒体。USB提供了对电话的两路数据支持。USB可支持异步以及等时数据传输,使电话可与PC集成,共享语音邮件及其它特性。USB还具有高保真音频。由于USB音频信息生成于计算机外,因而减小了电子噪音干扰声音质量的机会,从而使音频系统具有更高的保真度。(10)USB存在的问题。.尽管在理论上,USB可以实现高达127个设备的串列连接,但是在实际应用中,也许串联3到4个设备就可能导致一些设备失效。而且,实际的USB产品中,只有键盘是有一个输入口、一个输出口的设备,其它的则只有一个输入口而已'根本无法再连接下一个USB设备,所以当前的应用中,使用HUB来连接多个USB设备是必需的。另一个问题出在的USB电源上,尽管USB本身可以提供500mA的电力,但一旦碰到高电耗的设备,就会导致供电不足。解决这个问题的办法仍然是使用Hub。1.6创建驱动程序的所用工具因为微软没有公布的源代码,Windows2000平台下的驱动程序开发工具目前只有Microsoft的驱动程序开发工具包DDK(DeviceDriverKit)。其他如VireoSoftware公司的等开发工具VtoolsD只是对DDK所提供的函数进行了一些封装,向开发者提供更友好的编程接口。它开发的驱动程序最终连接到的函数库仍然是DDK提供的,所以并不是一个独立的驱动程序开发工具。因此选用常用的开发工具DDK。Windows2000DDK是开发基于Windows2000平台设备驱动程序的开发工具包,从微软官方网站即可获得。安装了Windows2000DDK后,开始菜单上将出现DevelopmentKits菜单项。在Windows2000中可以为不同的处理器构造自由或检查版本的驱动程序。自由构造的目标是驱动程序的最终发行版本,所以要进行必要的优化并删除所有的调试符号。检查构造的目标是一个未优化的调试版本,包括用于驱动程序调试的符号。Windows2000有自由版本和检查版本。如果使用MicrosoftWinDog调试程序,则需要两台允许Windows2000的计算机。开发计算机应是允许Windows自由版本的更快的计算机,驱动程序应该在运行.6.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用检查本的另一台目标计算机上测试运行。我在编写驱动程序的过程中使用的是WinDebug和DebugView,利用WinDebug连接到Microsoft的网址后,打开PC自动保存在系统目录下的内存拷贝文件,可以跟踪到驱动最后运行而导致问题的代码处,能够解决例如PC突然蓝屏死机等问题。DebugView进行代码内打印信息跟踪和注册表跟踪。Windows2000还可在Alpha平台上运行,也可以为Alpha平台构造自由目标和检查目标。DDKbuild命令行实用程序是构造驱动程序的主要工具,它使用正确的编译器和链接程序设置调用nmake实用程序来构造驱动程序。如果有必要,build也可以用于构造标准用户态Win32下的可执行文件。必须设置build才可以在命令行运行它。除了源代码,还要指定一个SOURCE文件、一个标准的makefile、目录结构和可选的makefile.inc和文件dirs。Build把构造过程的详细信息和错误结果显示到标准输出。另外,它在build.err文件中记录错误信息,在build.wrrl中列出警告,在build.109中列出日志。在Windows2000中,这些文件都有一个自由构造版本和一个检查版本。即buildfre.109、buildchk.109等。Nmake实用程序使用makefile文件中的指令确定运行什么命令来更新一个项目。例如下面的makefile文件说明,如果driver..cpp文件已经更新,使用cl编译器把它编译成drivenobj,并使用链接工具把driver.obj链接生成drivenexe。driverclobj:driver.cppdriverdriver.Exe:driver.o巧link—Odrivenexedriver.obj大多数makefile文件比这个文件复杂的多,但是设置用于驱动程序的编译器和链接程序是相当复杂的工具,所以Microsoft坚持在驱动程序的编写过程中使用makefile文件。Build在当前目录中的查找一个叫做SOURCES的nmake宏文件,了解驱动程序构造的详细信息。例如下面的程序清单给出了I/O端口驱动程序的SOURCES文件。它给出了如下信息驱动程序目标名称为Scard.sys,要构造一个WDM类型的驱动程序,在OBJ目录中构造。DDK的ine目录被添加到头文件的搜索列表中;SOURCES宏指定要编辑的文件列表。如下程序段所示:TARGETNAME=ScardTARGETlYPE=DRIVERDRIVERTYPE=WDMTARGETPATH=OBJINCLUDES=¥(BASEDIR)kinc;\¥(BASEDIR)ksrc\usb\inc;|¥(BASEDIR)ksrc\wdm\usb\inc;|..\inc;、¥(BASEDIR)\inc\ddk;t。\CommonDef;\.'.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用E:\work、2007\CICDEFINES=¥fCDEFINES)TARGETLIBS=\¥(DDKL113PATH、\ks.1ib\¥(DDK_LIB_PATH)kksguid.1ib\¥(DDK_LIB_PATH)\BdaSup.1ib\¥(DDKLIBPATH)\usbd.1ib\E:\work\:200%Cllobjchkhx86\i386\CILIBlw_1.ibUSEMAPSYM=1SOURCES=Musbsys.cpp\firmware.cpp|STB0899.cpp\UDSTBda.rc1.7本论文的目的和主要内容本文的主要目的就是为一个基于USB通讯接口的卫星电视接收卡在Windows平台下开发的设备驱动程序。由于USB设备所具有的低成本、即插即用、热拔插、多级级联、传输距离远、带宽高、简单易用等优点,使其更加广泛地应用于各种PC外设、移动存储设备、消费类电子产品以及工业领域。为了支持对这些设备的控制,必然需要根据设备的特性开发相应的驱动程序,因此,认真研究和分析设备驱动程序的开发很有必要。本文首先深入分析了在Windows环境下WDM驱动程序开发模型的基本机制及实现的基本原理,并介绍了USB设备驱动程序的体系结构。在文章的后半部分详细描述了本人开发USB设备驱动程序的过程,并给出了部分驱动程序中的关键代码并加以诠释。本文组织结构如下:第一章介绍Windows设备驱动程序开发的背景及Windows驱动程序的种类,并对Windows驱动程序模型WDM的特点和USB设备驱动程序开发做了简单介绍。第二章讨论WDM的层次结构,驱动程序的加载流程以及驱动程序开发中用到的几个重要的数据结构和对象。第三章分析WDM的数据读写方式及中断处理方式。第四章对对WDM的一般处理流程进行了介绍。第五章详细介绍了卫星视频信号接收卡设备的驱动程序开发及对程序中的重要代码进行了列举与讲解。第六章是对本文的一个总结。.8一

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用第二章WDM驱动程序的基本构造和重要概念2.1WDM驱动程序基本构造2.1.1WDM的层次模型WDM模型是一种分层化的驱动程序模型,在这个模型中,驱动程序的层或堆栈一起工作处理I/0请求。Windows2000的I/O子系统是基于对象的。对于WDM驱动程序而言,最重要的对象是驱动程序对象和设备对象。Windows的I/O子系统也是包驱动的系统。在这个系统中,每个I/O操作可以通过一个IRP描述,驱动程序的工作过程就是对IRP的处理过程。图2.1WDM中设备对象和驱动程序的层次结构WDM模型使用了如图2.1的层次结构。图中左边是一个设备对象堆栈。设备对象是系统为帮助软件管理硬件而创建的数据结构。一个物理硬件可以有多个这样的数据结构。处于堆栈最底层的设备对象称为物理设备对象(PhysicalDeviceObject),或简称为PDO。位于设备对象堆栈中部的对象称为功能设备对象(FunctionalDeviceObject),或简称FDO。在FDO的上面和下面一般有一些过滤器设备对象(filterdeviceobject)。位于FDO上面的过滤器设备对象称为上层过滤器,位于FDO下面PDO之上的过滤器设备对象称为下层过滤器。在WDM驱动程序模型中,每个硬件设备一般包含两个驱动程序。其中一个驱动程序称为功能驱动程序,即硬件驱动程序。它知道如何控制设备的主要功能,负责初始化I/O操作,处理I/O操作完成时所产生的中断事件,并为用户提供一种适当的设各控制方式。另一个驱动程序称为总线驱动程序(busdriver),它控制对总线上的所有设备的访问。例如,如果想访问USB设备,必须使用USB总线驱动程序。总线驱动程序负责枚举它的总线,这意.9.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用味着发现总线上的全部设备和检测设备何时被添加或删除。‘有些设备除了这两个驱动程序以外还有许多过滤器驱动程序(filterdriver)。某些过滤器驱动程序仅仅是在功能驱动程序执行I/O操作时进行监视。上层过滤器驱动程序在功能驱动程序之前看到IRP,它们有机会提供功能驱动程序根本不知道的额外特征。低层过滤器驱动程序在功能驱动程序要向总线驱动程序发送IRP时看到IRP。在某些情况下低层过滤程序可以修改功能驱动程序要执行的总线操作流。在WDM驱动程序模型中,总线是一个广义概念,不仅包括PCI总线,还包括SCSI卡,并行口,串行口,USB集线器等。层次结构可以使I/O请求过程更加明了,见图2.1的右侧。每个影响到设备的操作都使用I/O请求包。通常IRP先被送到设备堆栈的最上层驱动程序,然后逐渐过滤到下面的驱动程序。每一层驱动程序都可以决定如何处理IRP。驱动程序可以不做任何事,直接将向IRP传递给下层;也可以直接处理完该IRP,不再向下传递:但更普遍的是驱动程序也可以既处理了IRP,又把IRP传递下去。操作系统的PnP管理器按照设备驱动程序的要求构造设备对象堆栈。总线驱动程序枚举出连接到总线上的设备,并为每个设备创建一个PDO。一旦总线驱动程序检查到新硬件存在,PnP管理器就创建一个PDO,之后便开始描绘如图2.1所示的结构。创建完PDO后,PnP管理器参照注册表中的信息查找与这个PDO相关的过滤器和功能驱动程序,它们出现在图2.1的中部。系统安装程序负责填写部分注册表项,控制硬件安装的INF文件负责填写其它的注册表项。这些表项定义了过滤器和功能驱动程序在堆栈中出现的次序。所以,PnP管理器是从安装最下层过滤驱动程序并调用它的AddDevice函数开始创建这个栈的。AddDevice函数创建一个FiDO对象,这样就在过滤器驱动程序和FiDO之间建立一个水平连接。AddDevice接着把PDO连接到FiDO上。PnP管理器继续向上执行,依次装入并调用每个低层过滤器、功能驱动程序和每个高层过滤器,直到完成整个堆栈。上述过程中,注册表中的三种注册表键起着重要的作用,这三种注册表键是硬件(hardware)键、类(class)键、服务(service)键。必须明确一点,这些名字(hardware。class。service)并不是某个专用子键的名称:它们是这三种键的一般称谓,其具体的路径名要取决于它们所属的设备。概括地讲,硬件键包含单个设备的信息,类键涉及所有相同类型设备的共同信息,服务键包含驱动程序信息。设备的硬件键出现在注册表localmachine分支的\System\CurrentControlSetkEnum子键上。通常不能查看到该键的内部信息,系统只允许拥有系统帐号的用户访问该键。即只有内核模式程序和运行在系统帐号下的用户模式服务可以读写Enum键和其子键,但是即使是管理员也不应该直接修改这些键的内容。要想查看Enum键的内容,可以在Administrator特权级帐户下使用REGEDIT32.EKE工具查看。硬件键中的大部分键值是在安装过程中自动填入的,或者在安装开始后的某个时刻,系统识.10.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用别出来了新硬件并由系统自动填入的。有些是由INF文件中指明安装位置。所有设备类的类键都出现在HKLM\System\CurrentControlSet\Control\Class键中。它们的键名是由Microsoft赋予的GUID值。对设备驱动程序重要的最后一个键是服务键。它指出驱动程序执行文件的位置,以及控制驱动程序装入的一些参数。服务键位于HKLM\System\CurrentControlSet\Services键中。,2.1.2驱动程序加载流程在WindowsNT中,I/O管理器负责加载驱动程序,而在Windows2000中,是由P11P管理器发现设备并加载驱动程序。不过在发现设备后,它,ff];On载驱动程序所作的操作是类似的。当PnP管理器检测到一个新设备装入时,打开设备的硬件键和类键并且按如下顺序装入驱动程序:1.安装任何硬件键中为设备指定的低层过滤器驱动程序。如果LowerFilter值的类型是REGMULTISZ,那么该键可以指定多个驱动程序,其装入顺序由它们在数据串中的顺序决定。2.安装类键中指定的任何下层过滤器驱动程序。同样,它也可以指定多个驱动程序,其装入顺序由它们在数据串中的顺序决定。3.安装由硬件键中Service值指定的驱动程序。4.安装任何硬件键中指定的高层过滤器驱动程序,同样,它也可以指定多个驱动程序,以在UpperFilters值数据串中的顺序依次加载。5.安装类键中指定的任何高层过滤器驱动程序,同样,它也可以指定多个驱动程序,以在UpperFilters值数据串中的顺序依次加载。系统“装入”一个驱动程序,是指系统把驱动程序的映像映射到虚拟内存中,并重定位内存参考,最后调用驱动程序的主入口点。主入口点通常命名为DriverEntry。如果驱动程序己经在内存中,则装入过程仅仅是增加驱动程序映像的参考计数。属于类和设备实例的上下层过滤器驱动程序在装入过程中并没有出现嵌套方式。系统以PnP管理器装入驱动程序的顺序调用驱动程序的AddDevice函数,而这个顺序与设备对象在设备堆栈中出现的顺序完全一致。2.2驱动程序用到的一些数据结构在WDM驱动程序和NT驱动程序中,系统使用多种数据结构及对象作为其控制的各种硬件设备的逻辑抽象。现将最常用到的一些数据结构和对象进行介绍:

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用2.2.1DriverObject对象每个驱动程序有唯一的一个Driver对象。I/O管理器使用Driver对象数据结构代表每个设备驱动程序。这个对象中保存驱动程序各个例程的指针。利用这些指针I/O管理器把IRP发送到正确的例程并执行。另外,Driver对象还有指向这个驱动程序的设备链表的指针,通过它,驱动程序可以找到它控制的设备。图2.2给出了DriverObject对象的结构。对象中的DevieeObject域(PDEVICEOBJECT)拥有一个设备对象数据结构串,驱动程序管理的每个设备都有一个PDEVICEOBJECT。I/O管理器把这些设备对象连接起来并维护这个域。非WDM驱动程序的DriverUnload函数,为了删除这些DeviceObject,会使用这些域来遍历设备对象链。WDM驱动程序可能并不特别需要使用这个域。图2.2Driver对象StartlO域(PD刚VERSTARTIO),指向一个驱动程序中处理实际I/O操作的函数。UnLoad域(PDRIVERUNLOAD),指向驱动程序中的一个清理函数,它和DriverEntry对应,是卸载驱动程序时清理现场用的。不过,WDM驱动程序可能没有任何重要的清理清理工作要做,因为在WDM驱动程序中,这些工作通常由PIlP管理器完成。MajorFunction域(PDRIVERDISPATCH数组),是一个指针数组,它指向驱动程序中的回调函数,这些函数处理大约20种类型的I/0请求。这个数组也有大量的处理工作要做,因为它定义了如何使用I/O请求进入我们编写的回调函数代码。2.2.2Device对象Device对象是设备的软件抽象。它代表驱动程序所管理的设备。驱动程序为它管理的每一个设备都建立一个Device对象。该对象保存有驱动程序Driver对象的指针和当前设备正在处理的IRP。它还维护一个挂接到Device对象上的IRP链表的指针。这个链表上的IRP是所有等待该设备处理的I/O请求的排队。另外,Device对象还有一个DeviceExtension域。-12.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用这是一块可变大小的非分页内存,其具体的内容在驱动程序中设定。通常存放与设备有关的变量和使用对象的指针。图2.3给出了Device对象的结构。Device对象中的DriverObject域(PDRIVER_OBJECT),指向描述与该设备对象相联的Driver对象。通常调用IoCreateDevice创建Device对象。过滤器驱动程序有时需要使用这个指针来找到它们正过滤的设备的Driver对象,以便能够查询MajorFunction表中的函数入口。Device对象NextDeviceD№r对象l卜等待IRPDriverObjectCurrentIRPDeviceExtensionIRPQuence一黼时一‰Dev心ice。n上等待IRP图2.3Device对象NextDevice域(PDEVICEOB厄CT),指向与本设备对象同属于一个驱动程序的下一个设备对象,这个域把以驱动程序对象中的DeviceObject成员为起始点的设备链连接起来。对于WDM驱动程序来说没有必要使用这个域。CurrentlRP域,指向最近发往驱动程序StartlO函数的I/O请求包。DeviceExtension域,指向程序员自己定义的包含设备特定信息的数据结构。I/O管理器为该数据结构分配空间,不过它的名称与其中的内容完全由程序员自己决定。常见约定是使用DEVICEEXn渊TION类型声明数据结构,用一个指向设备对象的指针访问它。2.2.3I/O请求包I/O请求包(II心)是驱动程序操作的中心。内核通常通过发送IRP来运行驱动程序中的代码。IRP是一个内核“对象”,使用一个预先定义好的数据结构,带有一组对它进行操作的I/O管理器例程。I/O管理器接受一个I/O请求,然后再把它传递到合适的驱动程序栈中的最高驱动程序之中,分配并初始化一个IRP。一个IRP由一个固定的首部和可变数目的IRP栈单元组成,每个I/0请求由一个主功能代码并有可能有次功能代码。例如IRPMJPNP即插即用IRP有几个次功能(如IRPMNSTARTDEVICE)。IRP含有该I/O请求的各项参数,如写I/O,转化成IRP则包

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用含了写地址指针、写长度、数据内容指针等参数。1.IRP首部,其首部结构如图2.4所示。IRPTypeSizeMdlAddressFlagsIoStatusR。叩哪。M甜elh耐mgMu眦dIs‰跹。咖lc峨mL0嘶bncancell乙ancellrplus6|rIA。spbcEnVlromemIL。catl。叶‘agsUserEventOverlay.CancelRoutineUserBufferT.ail图2.4IRP首部结构Flags(ULONG)域包含一些对驱动程序只读的标志。但这些标志与WDM驱动程序无关。Associatedlrp(union)域是一个三指针联合。其中,与WDM驱动程序相关的指针是Associatedlrp.SystemBuffer。SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中。对于IRP—MJREAD和IRPMJWRITE操作,如果顶级设备指定DOBUFFEREDIO标志,则I/O管理器就创建这个数据缓冲区。对于IRPMJDEVICECONTROL操作,如果I/0控制功能代码指出需要缓冲区,则I/0管理器就创建这个数据缓冲区。I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,这也是创建IRP过程的一部分。这些数据可以是与WriteFile调用有关的数据,或者是DeviceloControl调用中所谓的输入数据。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。对于指定了METHODBUFFERED的I/O控制操作,驱动程序把所谓的输出数据放到这个缓冲区,然后I/O管理器再把数据复制到用户模式的输出缓冲区。IoStatus(10STATUSBLOCK)是一个仅包含两个域的结构,驱动程序在最终完成请求时设置这个结构。loStatus.Status域将收到一个NTSTATUS代码,而loStatus.Information的类型为ULONG,它将收到一个信息值,该信息值的确切含义要取决于具体的RTP_类IRP型和请求完成的状态。Information域的一个公认用法是用于保存数据传输操作(如.14-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用IRPMJREAD)的流量总计。某些PnP请求把这个域作为指向另外一个结构的指针,这个结构通常包含查询请求的结果。RequestorMode将等于一个枚举常量UserMode或KemelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。PendingReturned0300LEAN)如果为TRUE,则表明处理该IRP的最低级分发例程返回了STATUSPENDING。完成例程通过参考该域来避免自己与分发例程间的潜在竞争。Cancel∞OOLEAN)如果为TRUE,则表明IoCancellrp己被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIi'p函数。Cancellrql(KIRQL)是一个IRQL值,表明取消自旋锁是在这个IRQL上获取的。当在取消例程中释放自旋锁时应参考这个域。CancelRoutine(PDRIVERIoSetCancelRoutine函数设置这个域而不是直接修改该域。UserBuffer(PVOID)对于METHODNEITHER方式的IRPMJDEVICECONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请求缓冲区的用户模式虚拟地址,但指定了DOBUFFEREDIO或DODIRECTIO标志的驱动程序,其读写例程通常不需要访问这个域。当处理一个METHOD这个地址创建自己的MDL。NEITHER控制操作时,驱动程序能用STACK只要一个IRP被核心态程序创建,就会有一串的IO处理这个IRP的驱动程序都有个对应的Location。10LOCATON被创建:每个STACKLOCATION主要存放I/O请求的函数指针和参数。可以说IRP相关的这两个数据结构是一切处理的基础,因此需要透彻了解其中的每个部分。2.I/o堆栈单元只要任何内核模式程序创建了一个IRP,那么它也创建了一个10STATCKLOCATION结构的关联数组:每层处理IRP的驱动程序对应一个栈单元,而且通常有一个额外的栈单元用于保存这个IRP的构造者(见图2.5)。一个栈单元包括IRP的类型和诸如“完成例程”之类的IRP参数信息。栈结构的说明参见图2.6。过滤器设备对象过滤器驱动程序Io_STACKLOCATION功能设备对象设备驱动程序lo-STACK_LOCATION物理设备对象总线驱动程序Io-STACKLOCATION图2.5各层驱动程序和I/O栈之间的对应关系

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用MajorFunctionMinorFunctionParameterFlagsContr01DeviceObjectFileObjectCompletionRoutionCoritext图2.6I/o栈单元的数据结构I/O栈单元是IRP中传递I/O请求信息最重要的数据结构。其成员的功能解释如下:MajorFunction(UCHAR)是与这个IRP关联的主功能码。它可以是一个像IRPMJREAD这样的值,这个值对应于Driver对象MajorFunction表中的一个调度函数指针。因为这个功能码在一个特定层驱动程序的I/O栈单元中,所以,一个IRP,例如IRPMJREAD开始的I/O请求,向驱动程序栈的下面传送的过程中,可能会转换成另外的形式。,MinorFunction(UCHAR)是从属于主功能码的辅功能码。例如,IRPMJPNP主功能码可以划分成大约十几个子类型,这些子类型都有诸如IRPMNIRPSTARTDEVICE,MNREMOVEDEVICE,等等的辅功能码。Parameters(union)是一个子结构的联合,每个带有参数的IRP请求都有一个Parameters。例如,这个子结构包括Create(IRPMJStartDevice(IRPMJPNP的IRPCREATE请求),Read(IRPMJREAD请求),和IVINSTARTDEVICE子类型)等类型。DeviceObject(PDEVICEOBJECT)是对应于这个栈单元的设备对象的地址。驱动程序使用IoCallDriver函数填写这个域。FileObject(PFILEOBJECT)是IRP指向的内核文件对象的地址。驱动程序经常使用FileObject指针关联队列中的IRP,以便(为了准备关闭文件对象而)取消所有己入列的IRP请求。CompletionRoutine口IOCOMPLETIONROUTINE)是“FO完成例程”的地址,它由该层栈单元上面的驱动程序设置。不能直接设置这个域一但可以通过loSetCompletionRoutine来设置,这个函数设置该层栈单元下面的那个栈单元(而不是驱动程序正处理的那个栈单元)。驱动程序层次结构中最下层(10west.1evel)的驱动程序永远不需要“完成例程”,因为它必须完成这个IRP请求。Context(PVOID)是一个“任意上下文”值,它将作为参数传送到“完成例程”。决不能直接设置这个域,它由一个来自于IoSetCompletionRoutine函数的参数自动设置。3.IRP处理当一个IRP由多个驱动程序处理时,使用多个IRP栈单元。每个驱动程序从当前栈单元得到它的IRP参数。如果把一个IRP沿当前设备的驱动程序栈向下传递,必须使用正确.16.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用的参数设置下一个栈单元。如:要处理大的传输,必须把这个IRP向下发送几次,向下发送的每个传输请求都将在此层驱动程序的能力之内。在驱动程序栈中处理IRP的过程如图2.7所示:JIRPL卜处理程序1处理程序2处理程序3处理程序41r使月对应觯元p使用对应觯元pIO_STACK—LOCATIONIo-STACK—LOCATION伽姚觯◇使用对应栈单亏/>10一STAClUOCATIONI吼STLOCATION图2.7IRP处理流程总之,一个IRP含有一个FO请求操作栈,一个驱动程序只能看到当前的IRP栈单元,且不必担心它上面是否有更高层的驱动程序。2.2.4Interrupt对象Interrupt对象用于给内核的中断分发器提供方法,在中断发生时找到正确的中断服务例程。在驱动程序初始化时需要为设备或控制器支持的每个中断向量创建一个Interrupt对象。驱动程序使用这个对象把中断向量和相应的ISP连接起来。发生中断时,内核中断分发器使用Interrupt对象找到ISR例程。在驱动程序退出时,使用这个对象断开向量和ISR的连接。2.2.5Adapter对象Adapter对象主要在处理DMA设备时使用。所有的DMA设备都要使用系统的DMA资源,WDM中使用DMA对象来协调各个驱动程序对DMA资源的申请和使用。Adapter对象代表了一套共享资源。这些资源可以是一个DMA通道或者是一套DMA映射寄存器。Adapter对象只能由HalGetAdapter这个函数来取得一个指向Adapter对象的指针。然后使用这个指针来进行操作。

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用第三章数据的读写与中断3.1数据的读写方式当应用程序发起一个读或写操作时,通过给出一个用户模式虚拟地址和长度,应用程序向I/O管理器提供了一个数据缓冲区。Windows为驱动程序访问用户模式数据缓冲区提供了三种模式:1.BUFFERED模式。在该模式中,I/O管理器先创建一个与用户模式数据缓冲区大小相等的系统缓冲区。而驱动程序将使用这个系统缓冲区工作。I/O管理器负责在系统缓冲区和用户模式缓冲区之间复制数据。2.DIRECT模式。在该模式中,I/O管理器锁定了包含用户模式缓冲区的物理内存页,并创建一个称为MDL(内存描述符表)的辅助数据结构来描述锁定页。因此驱动程序将使用MDL工作。3.NEITHER模式。在该模式中,I/O管理器仅简单地把用户模式的虚拟地址传递给驱动程序。而使用用户模式地址的驱动程序应十分小心。为了指定设备读写的缓冲方式,应该在AddDevice函数中,在创建设备对象后,立即设置其中的标志位,例如以下的程序设置为BUFFERED方式。NTSTATUSAddDevice(…){PDEVICE——OBJECTfdo;IoCreateDevice(…,&fdo);fdo·>FlagsI=DO_BUFFERE_IO;)3.1.1BUFFERED模式使用METHOD—BUFFERED模式时,I/O管理器创建一个足够大的内核模式拷贝缓冲区(与用户模式输入和输出缓冲区中最大的容量相同)。当分发例程获得控制后,用户模式的输入数据被复制到这个拷贝缓冲区。在IRP完成之前,应该向拷贝缓冲区写入需要发往应用程序的输出数据。当IRP完成时,应该设置loStatus.Information域等于放入拷贝缓冲区中的输出字节数。然后I/O管理器把数据复制到用户模式缓冲区并设置反馈变量。在驱动程序内部,以同一个地址访问这两个缓冲区,即IFuP中的Associatedlrp.SystemBuffer指针。这是一个内核模式虚拟地址,指向输入数据的一份拷贝。很明显,应该在完成输入数据的处理之后再向这个缓冲区写入输出数据。下面是一个IOCTL用于处理一个.18.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用METHODBUFFERED操作的例子:caseIOCTL皿)ERSION—BUFFERED:{if(cbout<sizeof(ULONG)){status=STATUS_INVALID_BUFFER_SIZE;break;}PULONGpversion=(PULONG)Irp->Associatedlrp.SystemBuffer;宰pversion=OxOOD4000A;info=sizeof(ULONG);)首先要确认得到的输出缓冲区的长度至少能容纳一个双字。然后使用SystemBuffer指针寻址系统拷贝缓冲区,在系统拷贝缓冲区中存入这个简单操作的结果。当外围的分发例程完成这个IRP时,局部变量info中的值将写入loStatus.Information域。I/O管理器将把系统拷贝缓冲区中的数据复制回用户模式输出缓冲区。3.1.2DIRECT模式在驱动程序中,METHOD—IN—DIRECT和METHOD—OUT—DIRECT模式都以相同方式处理。仅有的不同是它们访问用户模式缓冲区时所需的访问权限:METHOD—IN—DIRECT需要读权限;METHOD—OUT—DIRECT既需要读权限又需要写权限。使用这两种模式时,I/O管理器会为输入数据提供一个内核模式拷贝缓冲区(Associatedlrp。SystemBuff'er),为输出数据缓冲区提供一个MDL(内存描述符列表)。3.1.3NEITHER模式使用NEITHER模式时,I/O管理器不翻译用户模式的虚拟地址,得到输入缓冲区的用户模式虚拟地址(在堆栈单元的Type3InputBuffer参数中),和输出缓冲区的用户模式虚拟地址(在IRP的UserBuffer域)。3.2中断处理3.2.1CPU的优先级因为不同的CPU有不同的处理硬中断优先级的方法,WIN2000使用一个理想化,抽象化的方案去处理所有平台优先权的问题。这些方案的执行是利用HAL的功能去驱动相应.19.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用的平台。这个方案的基础是中断请求优先级(IRQL),IRQL是一个简单定义优先权的数字,一个正在执行的中断服务程序不能被具有低的IV,QL或者相等IRQL的中断请求中断。表3.1列出了WIN2000的IRQL,通过它可以了解任何时间下指令指示器在一定IRQL下的执行顺序。给定线程的执行环境中包括了它的IRQL,任何时候,操作系统知道当前的IRQL值。表3.1中的优先级从上到下依次增加,其中硬件中断的优先级高于软件中断。3.2.2中断处理的顺序当一个中断到达CPU,处理器比较中断的IRQL和处理器当前的IRQL,如果中断的IRQL低于或者等于处理器当前的IRQL,处理器就暂时不管这个中断,这个中断请求保持挂起直到处理器的IRQL下降到一个比较低的水平。如果中断的IRQL高于处理器当前的表3.1WIN2000的IRQLIRQL,处理器就会按照以下方式执行:1.挂起正在执行的指令存储足够的状态信息到堆栈,这样可以在中断程序完成之后就恢复存储时的状态来继续执行被挂起的代码。提高处理器当前的IRQL到当前响应的中断的IRQL水平,防止处理器再响应低IRQL的中断。传递控制权给请求的中断的服务程序。当中断完成时,中断服务程序执行一个解除中断的特殊指令,这个指令从堆栈中恢复处理器的状态(包括IRQL),把控制权移交还给挂起的程序代码。2.软件产生中断一些中断过程的执行是由内核模式的软件产生,WIN2000使用这些写软件中断去扩展中断优先级包含线程调度。它可以通过提高IRQL用来防止被其它的线程中断,以达到同步线程的目的。.20-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用3.2.3延迟过程调用执行机制完整的中断服务通常需要执行这样一些操作,这些操作不适合在ISR中执行,或者考虑到执行在提升IRQL上的ISR中会对系统性能造成影响。为了解决这个问题,WindowsNT的设计者提供了延迟过程调用(DPC)机制。DPC是~个通用机制,但通常都用在中断处理中。在最普通的情况下,ISR决定当前请求的完成并请求一个DPC之后,内核在DISPATCHLEVEL级上调用这个DPC例程。因此DPC中的代码要比ISR中的代码有更少的限制。特别是,DPC例程可以调用像loCompleteRequest或IoStartNextPacket这样的例程,在一个I/O操作的结尾处调用这些例程在逻辑上是必要的。每个设备对象中都含有一个DPC对象。即,DEVICEOBJECT中有一个内置的DPC对象Dpc。创建设备对象后需要立刻初始化这个内置DPC对象。DPC的构架允许高IRQL的代码触发(不是执行)一个任务。如图3.1所示,DPC的简要的执行过程如下:1.当一段具有高的IRQL代码想安排它的一些工作在低的mQL下工作时,它增加一个DPC对象到系统DPC分发队列的末尾,并且请求一个软中断,因为当前的IRQL高于DISPATCHLEVEL,这个中断不会马上执行,而是悬挂起来。2.当处理机的IROL跌落到DISPATCHLEVEL以下,以前挂起的中断被DPC分发器执行服务。3.DPC分发器使每个DPC对象从系统队列中出列,调用存储在DPC对象中的指针所指的函数,这时处理机的IRQL是在DISPATHLEVEL。4.当DPC队列被清空时,DPC分发器解除DIPATCHLEVEL软件中断。图3.1DPC执行过程.21.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用第四章一般的WDM处理流程4.1IRP处理的标准模型操作系统加载的时候,找到了硬件以后,首先加载这个硬件的驱动程序。顺序是先创建一个DriverObject对象,并且把它作为第一个参数传递给驱动程序的入口(DriverEntry函数)。在DriverEntry中完成一些初始化。然后,操作系统发送IRPSTARTDEVICENM_这个IRP给驱动程序,在这个处理例程中要完成下面的工作:创建设备对象、创建标号连接和把设备放到堆栈上。然后,操作系统发送IRP_MN_STARTDEVICE来启动设备,在这个的处理中要完成查看硬件资源、分配设备资源等设备相关的功能。等操作系统加载完毕以后,驱动程序就等待上层软件打开设备、读写设备或者控制设备等操作了。这个时候,它的一般操作流程是这个样了的:10派遣例程Startl0ISRlDPCIl10管理器例程卜-叫例程卜-叫管理器图4.IIRP处理的标准流程最初接触的时候我认为这是个比较复杂的概念,随着了解的不断深入我发现即使这个概念也不能满足所有问题,比如热拔插设备、动态资源再分配,和电源管理等等。因此本文中不再描述处理一些额外问题(比方说:IRP排队和取消)的方法。如果设备在系统运行时不能被删除或重配置,并且在低电源状态下拒绝I/O请求,那么可以使用这个标准模型。4.2初始化操作4.2.1DriverEntry例程前面已经说过:驱动程序本质上可以认为是一个工作在核心层的DLL。所以,与普通的DLL类似,它必然有一个开始的入口,在这个入口里作一些初始化的操作。在WDM中,这个入口就是DriverEntry,在这个入口中要做的就是指定一些ERP的处理函数。每个驱动程序都有一个DriverEntry例程,当驱动程序第1次被装入时,内核调用DriverEntry例程,它的主要工作是初始化驱动程序,在DdverObjectXVj:象(由操作系统分配,用于存储与驱动程序有关的任何信息)中存储一系列的回调例程指针,如处理各种I/OIRP的分发例程,串行处理IRP的Startlo例程,添加新设备的AddDevice例程,处理各种PnPIRP的例程等,内核在适当的时候调用这些例程。WDM中有几个例程是必须要处理的,其他的都是可选的。必须要处理的包括这么几.22—

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用MJPOWER和IRP个:DriverUnload。AddDevice和三个IRP(IRPMJCREATE。所以它的基本模型可以如下所示:emem“C’’NTSTATUSPNP、IRPMJDriverEntry(INPDRIVER—OBJECTDriverObject,INPUNICODE—STRINGRegistryPath){NTSTAnJSstatus;status=KslnitializeDriver(DriverObject,RegistryPath,&DeviceDescriptor);DriverObject->DriverUnload=DriverUnload;DriverObject-->DriverExtension-->AddDevice=AddDevice;DriverObject->DriverStartlo=Sta_rtlo;DriverObject->MajorFunction[RPMJ删】-DispatchPnp;DriverObject->MajorFunction[RPMJ—POWER]=DispatchPower;DriverObject->MajorFunction[RP—MJ—SYSTEM_CONTROL]-Dispatchwmi;…∥上面都是分配各个IRP的处理函数,这就是DriverEntry的全部功能。后由各个功能函数具体实现。return)status;4.2.2AddDevice例程在做好IRP的处理后操作系统就要进入DriverObject->DriverExtension.>AddDevice=AddDevice这个处理函数。对于功能驱动程序,其AddDevice函数的基本职责是创建一个设备对象并把它连接到以PDO为底的设备堆栈中。相关步骤如下:1.调用IoCreateDeviee创建设备对象,并建立一个私有的设备扩展对象。2.寄存一个或多个设备接口,以便应用程序能知道设备的存在。另外,还可以给出设备名并创建符号连接。3.初始化设备扩展和设备对象的Flag成员。4.调用loAttachDeviceToDeviceStack函数把新设备对象放到堆栈上。然后,系统相应IRPMJ类似的处理。如下程序所示:PNP的IRP,对于其他的一些IRPMN|E}料,可以给出一些NTSⅫ7SDeviceAdd(IN{//AllocatecontextstoragePKSDEVICEdevice)NTSTATUSresult=STATUS_SUCCESS,ntStatus;device->Context=-ExAllocatePoolWithTag(NonPagedPool,sizeof(DEVICE_CONTEXT),’BDOM’);.23-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用i行device一>Context—NULL)returnSTATUSrNSUFFICIENTRESOURCES;RtlZeroMemory(device->Context,sizeof(DEVICE_CONTEXT));GETCONTEXT(device).>DriverState=DRIVER||AllocateUSB、nfostorageINITIALIZE;GETCONTEXT(device)->pUsblnfo=(PUSB—INFO)ExAllocatePool(NonPagedPool,sizeof(USBINFO));if(GETCONTEXT(device)一>pUsblnfo—NULL)retumS咖7S烈SUFFICIENTRESOURCES;RtlZeroMemory(GETCONTEXT(device)->pUsblnfo,sizeof(USBJNFO));KelnitializeEvent(&GETCONTEXT(device)->WaitAccessFw,NotificationEvent.FALSE);KeSetEvent(&GETCONTEXT(device)一>WaitAccessFw,0,FALSE);KelnitializeEvent(&GETCONTEXT(device)·>TSTrdTem'NotificationEvem,FALSE);KelnitializeEvent(&GETCONTEXT(device)->TSSchedule,NotificationEvent,FALSE);GETCONTEXT(device).>blsLoader=TRUE:GETCONTEXT(deviee)->bBypassSupport2FALSE;GETCONTEXT(device)一>AccessFail=FALSE;GETCONTEXT(device).>bltfacOK=F.ALSE;GETCONTEXT(device).>bVDVBTEn=FALSE;GETCONTEXT(device).>bSimuEn=FALSE;GETCONTEXT(device)->SimuDevType=0:GETCONTEXT(devicel—>bATSCEn=FALSE;GETCONTEXT(device).>bMCEEn=FALSE;GETCONTEXT(device).>IRCConfiguration=0:GETCONTEXT(device)->bRegistryHWlnfo=FALSE;GETCONTEXT(device)一>bRegistryDeviceName=FALSE;MTablelnit(device);retumresult;4.2.3处理IRP—MN—START—DEVICE对于IRP—MN—START—DEVICE,则要重点对待。因为这个II诤的IO—STACK—LOCATION中有几个有特定意义的参数Parameters->StartDevice->AllocatedResources(指向描述设备资源的列表的指针)和Parameters->StartDevice.>AllocatedResourcesTranslated(指向设备资源转化值的列表的指针)。这些参数是即插即用管理器、输入输出管理器和硬件抽象层取得一致以后分配给该设备使用的资源。有了这些资源以后,就可以对这些资源进行相.24.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用应的转化和使用它fl'J(MmMaploSpacc,IoConnectlmerrupt等函数)。这些资源是以后操作这个设备的基础。在AddDevice例程中并没有为设备分配资源,而是F4qPnr'管理器发送一个次功能代码为“STARTDEVICE”的PnPIRP给驱动程序,传递分配给设备的资源列表。分配给设备的资源一般有I/O端口、内存、中断、DMA等。对于内存空间和内存映射的I/O空间,必须调用MmMaploSpace把它们映射到系统非分页内存,这样驱动程序才可以对它们进行访问。对于普通的I/O空间,驱动程序可以通过它的物理地址的低32位进行访问。对于中断,调用IoConnectInterrupt安装中断处理程序。但是需要注意的是,该IRP的处理顺序是沿设备栈由下而上,与IRP进入设备栈的顺序相反。因为必须先由低层驱动程序启动硬件设备后,功能驱动程序才能在功能级启动该设备。然而,在该IRP被下层驱动程序排队还没有被处理的时候,把IRP传到下层驱动程序处理的IoCallDriver函数,会以STATUSPENDING的状态返回。所以必须在把该IRP传递到低层驱动程序之前(也就是在调用IoCallDriver之前),调用loSetCompletionRoutine给该IRP挂接一个完成例程,它在低层驱动程序真正处理过该IRP以后会被调用。在完成例程里可以触发一个事件,这样,当IoCallDriver返回STATUSPENDING时,就等待该事件被触发,从而在下层驱动程序处理完该IRP以后再进行后续的处理。4.2.4分配资源在这个处理例程中,也要分配自己需要的一些资源。比方说,如果用到DMA则要分配Adapter对象和MapRegisters;如果用到Interrupt则要注明一个ISR例程,并且进行相应的连接和转化。具体的代码如下:NTSTATI7SStartDevice(PDEVICE-OBJECTfdo.PCM—PARTIAL·RESOURCE-LISTraw.PCM—PARTIAL—RESOURCE_LISTtranslated)//传递了两个参数,具体结构可以看DDK文档{PDEVICEEXTENSIONpdx=(PDEVICEEXTENSION)fdo-->DeviceExtension;resourcePCMPARTIAl,RESOURCEDESCRIPTOR--translated·}PartialDescriptors;ULONGnres--translated-->Count;<在这里加入自己的变量说明>for(ULONGi=o;i<nres;++i,++resource){switch(resource->Type)}caseCmResourceTy7pePort:.25.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用<发现是端口资源,进行相应的处理>break;caseCmResourceTypeInterrupt:<发现是中断资源,进行相应的处理>break;caseCmResourceTypeMemory:<发现是内存资源,进行相应的处理>break;。caseCmResourceTypeDma:<发现是DMA资源,进行相应的处理)break;)<根据得到的资源类型和数量,进行相应的处理和初始化工作>IoSetDeviceInterfaceState(&pdx->ifname,TRUE);4.3IRP操作MJCREATE过程CREATE4.3.1IRP操作系统启动了以后,驱动程序就等待应用层的调用了。首先肯定是IRPMJ(也就是调用函数CreateFile来打开函数),只有打开了设备,应用层才可以获得一个设备的句柄,然后才可以利用这个句柄来向驱动程序发送IRP请求(比方说IRPMJREAD就是调用函数ReadFile的时候发出的)。IRPMJCREATE的相应函数比较简单,如下所示:NTSTATUSCreateClose(PDEVICE.OBJECTDeviceONect.PIRPlw){PIOSTACKLOCATIONioStack=IoGetCurremlroStackLocation(Irp):POSRDEVICEEXTdevExt=-Deviceobject.>DeviceExtension;Iro.>IoStatus.Status=STATUSSUCCES;if(ioStack.>MajorFunction一---IRPdevExt->State<STATEALLMJCREATE&&BELOWFAIL){Irp->IoStatus.Status=STAnJSUNSUCCESSFUL;}Im.>IoStatus.Information=O;IoCompleteRequest(Irp,IOreturnNOINC!REVIENT);fSTATUS.SUCCESS);}.26.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用4.3.2读写处理对于Read和Write来说,这些操作都和具体的设备有着密切的联系,所以具体的操作也都不相同。但是,他们也有共同点,那就是可以简单的理解为:读写端口。如果设备是DMA设备,那么他们可能只是设置一些简单的硬件寄存器来让硬件发起DMA传输就可以了。然后他们等待DMA完成所出发的中断,然后进入中断处理程序ISR;如果设备是PIO(ProgrammedlO,也就相当于是轮训方式的传递数据),那么它可能要循环的进行一些查询端口和读写数据。他们处理的一般步骤是:1.检查要读写的数据长度,看看有没有明显的错误。比方说如果长度小于等于0则肯定不对,然后直接返回错误就是了。2.查看当前IRP有没有被取消,如果取消了的话,直接返回。3.检查当前有没有IRP处理在进行,如果有的话,把这个请求放到请求队列的末尾。如果没有,则开始处理这个请求。4.把IRP中传递过来的MDL进行地址转换,转换成为核心态虚拟地址,然后根据设备的不同进行寄存器读写。如果要产生中断的话,可以进入下一步。如果没有的话,则返回。4.3.3中断处理如果硬件在满足了一定的条件,产生了中断的话,就进入到ISR中。在ISR中要完成的处理有以下这些:1.首先通过读写硬件的寄存器来判断这个中断是不是自己这个设备的。如果不是则不作处理。如果是则通过向硬件端口写一些数据,把中断清除。2.根据要完成的处理不同,决定什么时候跳入到DPC中进行处理。因为根据设备的要求不同,要求ISR的处理内容也不同。如果要拷贝数据,则必须要进入DPC中进行,因为内存拷贝函数在DIR}上不能运行;如果只是要读写一些端口的话,可以在ISR中运行。3.在DPC中完成处理过程(比方说数据拷贝)。然后可以把这个IRP从队列中删除,然后返回。关于IRP队列,可以认为它就是一个FIFO的队列,每来一个IRP它就把它放入到队列中去,每完成一个IRP就从队列中删除一个,只要不空就可以不停的处理里面的IRP。一个驱动程序有一个默认的队列(称为:系统排队),也就是说把所有的IRP放入到了一个队列中。也可以在驱动程序中建立自己的IRP队列,分别存放不同类型的IRP。比方说,建立两个IRP队列,一个用来存放IRPMJREAD,另外一个用来存放IRPMJWRITE。本节仅介绍了驱动程序中的几个特别重要的例程(routine),而对于其他的一些例程(比方说PNP和POWER)则基本没有说明。因为它们基本都是类似的,除了PNP的START.27-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用4.4编写INF文件4.4.1INF文件的基本作用在Windows找到一个新硬件的时候,它会出现提示安装硬件的驱动程序。而此时会发现这个时候系统提示寻找的不是.sys的驱动程序文件,而是相同日录下的一个.inf文件,这个也就是inf文件。从这里可以很容易的看一出INF文件的基本作用:1.它告诉操作系统在哪个目录下面可以找到驱动程序,文件名是什么,应该拷贝到什么地方去。2.告诉操作系统这个设备的VID和DID是什么,以及其他的设备的信息。(比方说驱动程序的版本,开发商等不能在驱动程序中找到的信息)因为只有知道了VID和DID,操作系统才可以找到特定的设备,然后把这个设备相应的驱动程序加载。3.告诉操作系统应该修改注册表的什么地方,在其中记录驱动程序的位置、GUID、驱动程序加载的顺序和驱动程序加载的方法仁动态还是静态)。’从上面的功能可以看出,安装驱动程序的时候操作系统通过INF找到驱动程序文件,然后把它拷贝到INF指定的位置,并且根据INF文件来修改注册表。然后,系统重新启动的时候,发现了这个设备,就从注册表来寻找设备的VID和DID对应的驱动程序,然后加载这个驱动程序。里面包含了一些必要的要向计算机注册的信息。比如要复制的文件列表、要创建的注册表项、支持的设备硬件ID等,包含[Version]、【Manufacturer]、[SourceDisksFiles】等。4.4.2INF文件的结构层次和WINDOWS底下的其他INF文件一样,驱动程序的INF文件的结构是分层次的。下NF文件开始于一个Version段,该段确定文件中描述的设备类型。它的一般结构如下:【Version】signature=”¥CHICAGO¥”//signature可以是:¥CHICAGO¥、¥WindowsNT¥或者¥Windows955Class=MediaClassGuid={4d36e96c--e325--llce·-bfcl·-08002bel0318}一个INF文件也就是由类似与上面的段组成的,【】表示一个段的开始,后面的是这个段的命令。把一个大的INF文件看成是一个树结构的线形描述可以更容易理解INF文件。一个段就是树上的一个节点,而每个指令就是指向另一个段的指针。下图就是示意:.28.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用厂商I…●设备IIIV;?……一??4。A-ns钏段牛图4.2INF文件的树状结构这棵树的根是Manufacturer段,列出了文件中有硬件描述的所有公司。如下:[manufacturer]”Walter0neySoftware”=DeviceList’”FinestOrganizationOnEarthYet”=FOGEY每个独立厂商的model(硬件型号)段(例子中的DeviceList和FOGEY)描述了一个或多个设备,如下所示:[DevieeList.】AMCC55933Development10E8&DEVBoard(DlVtn)4750(等号前面是一个可以读的设备描述,可以在“控=Driverlnstall,USB\VEN制面板一设备管理”中看到。等号后面的Driverlnstall指向了另外一个段,USB\VEN10E8&DEV4750则是DID和VID。)install段包含指导安装程序安装所需软件的实际指示,例如上面的Driverlnstall段指向了一个段。一个典型的Windows2000安装段仅包含一个CopyFile指令:【Driverlnstall.nt】CopyFiles=DriverCopyFiles这个CopyFiles指出让安装程序用另一个工NF段中的信息来指导文件复制。对于PKTDll411例子,这个段名为DriverCopyFiles:[DriverCopyFiles】pktdma.sys,,,2该段指示安装程序把PKTDMI1.SYS复制到用户的硬盘上。CopyFiles段中的语句有下面通用形式:Destination,Source,Temporary,FlagsDestination是被复制文件出现在用户系统中的文件名(不包括任何路径名)。.29.Source是

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用源文件各,如果目标文件与源文件名字相同则这里可以为空。该参数对于Windows2000没有必要,系统会自动生成临时文件名。文件名本身不能为安装程序复制文件提供足够的信息,还需要知道文件要复制到的目录名。另外,如果安装过程中需要多个磁盘,则需要知道哪个磁盘含有源文件。这些信息来自INF文件的其它段。比方说:[DestinationDirs】DefaultDestDir=10,System32kDrivers【SourceDisksFiles】pktdma.sys=1【SourceDisksNames】1_,’WDMBookCompanionDisc",disklSourceDisksFiles段指出安装程序司以在1号盘上找到PKTDIVIA.SYS文件。SourceDisksNames段指出磁盘1有一个可读的标签“WDMBookCompanionDisc”并包含一个名为diskl的文件,用于安装程序寻找并检验驱动器中是否有正确的磁盘。注意这两个段名中有一个容易忘记的字母“S”。DestihationDirs段指出文件复制操作的目标路径。DefaultDestDir是未指定目标目录文件的默认目标路径。可以用一个数值代码来指定目标路径,经常使用的仅有如下几个:1.目录“10”为Windows目录(例如“\Windows”或“\winnt”)。2.目录“11”是system目录(例如,“\windows\System”或“\winnt\System32”)。3.目录“12”是Drivers目录,指在Windows2000系统中(例如,“\W'mnt\System32kDrivers”)。WDM驱动程序存在于Driver目录中。如果CopyFiles段仅用于向Windows2000安装,那么仅指定目录数值12就可以了。有一了上面的段,就已经有一了足够的信息把驱动程序复制到磁盘上的正确位置。但是,还需要知道怎么让系统找到驱动程序。这就需要一些别的服务(service)字段。段Services用于实现这个目标,例如:[Driverlnstall.NT.Services】AddService=PKTDMA,2,DriverService[DriverService】ServiceType=lStartType=3ErrorControl=lServiccBinary=%l0’%\systcm32\drivers\pktdma.sysAddService指令中的“2”指出PKTDMAservice将成为该设备的功能驱动程序。该段名字由install段名再加上“Services”词组成。这个指令的结果是使HKEY—LOCAL—MACHINE\System\CurrentControlSet\Services中出现个PKTDMA键(AddService指令的第一个参数)。它将为内核模式(ServiceType为1)驱动程序定义service项,内核模式驱动程序.30.

南京信息工程大学硕士学位论文基于Windows的USB接1:3WDM驱动研究和应用由PnP管理器按需求自动装载(StartType为3)。在装入时发生的错误应该被登记,但小要阻止系统启动(ErrorControl为1)。执行映像为\Winnt\System32kDrivers\pktdma.sys(ServiceBinary的值)。如果查看注册表,会看到执行文件的名存在于ImagePath名下而不是ServiceBinary。service的名最好与驱动程序的二进制文件名相同。这可以使service的名明显与驱动程序对应,还避免了两个不同、service键指向同一个驱动程序所带来的问题:如果某设备使用的驱动程序与在其后启动的设备所使用的驱动程序相同,除非在不同的service名下,否则其自身不能被启动。在这里列出的一些段,尤其是那些含有install的,可能会包括涉及到其他inf作者定义的段。在安装过程中,每个指令会触发在对应inf作者定义段中列出的将要进行的相应操作。对于任何特定的当前段的有效登录和指令集是有特定性的,并且在每个段的说明中都是按照正常的语法顺序来呈现的。.31.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用第五章实现DVB.S数字电视接收卡驱动程序5.1硬件设计为了降低硬件开发的风险,接收卡在设计时采用与主机硬件平台分开设计的方案,接收卡通过USB接口与硬件平台相连接,这样可以增强接收卡的可移植性,减小接收卡对主机硬件平台的依赖性。在本次设计中采用EZ.USB芯片作为USB桥芯片,ZARLINK公司的ZLl0039作为TUNNER芯片,ZLl031x作为DEMODULATOR芯片。5.1.1ZLl0039简介该ZLl0039是一种为数码卫星接收系统而设计的单芯片宽带直接转换与积分射频旁路优化调谐器。它提供了性能优良,适用于最高灵敏度要求。该设备为卫星调谐器设计提供,了一个高度整合的解决方案,包含一个低相位噪声锁相环频率合成器,一个正交下变频完全整合的本地振荡器和可编程基带频道过滤器。它提供多项额外的周边元件所需。其晶体参考源,也可以用作为解调器的参考器件。一个12C兼容总线接口控制所有的调谐器的功能。该ZLl0039既包含硬件和软件掉电模式。其原理图如下:图5.1ZLl0039原理图5.1.2ZLl031x简介该芯片是QPSK/BPSK在1-45MSps的解调器和符合欧洲播出联盟对外电讯服务.32.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研宜塑廑旦300421规格的信道解码器。它从调谐器接收模拟I和Q信号,并用数码解调信号,实现完全的的DVB/DSSFEC(前向纠错)和解绕功能。其输出形式是以MPEG2形式或DSS传输流数据包。该芯片还对射频前端设备提供自动增益控制。该芯片到控制微处理器有一个串行2线总线接口。ZLl031x由于内置自动搜索和解码控制功能需要最小的软件控制。图5.2ZLl03lx原理图5.1.3接收卡硬件简要框图整个接收卡主要由前端调谐芯片ZLl0039和DVB—T解调芯片ZLl031X构成。ZLl0039将从天线过的射频(RF.RadioFrequency信号经过降频后变为中频(IF-IntermediateFrequency)信号,然后送入ZLl031X芯片。ZLl031X首先将中频信号进行AJD变换,然后根据TPS信号的信息对信号OFDM进行解调,解调后得到MPEG.2传输流,然后TS流的信号格式变为USB传输格式,最后通过USB接口将码流输出。前端ZLl0039的增益控制由ZLl031X控制,ZLl031X与ZLl0039之间的通信通过12C总线来实现。如图5.3所示:图5.3接收卡硬件结构简单框图-33—

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用5.2软件设计5.2.1接收卡的工作流程图5.4驱动程序的大致工作流程图..34..

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用当接收卡接入系统后,Windows系统通过搜索注册表来查看系统中是否有与接收机匹配的驱动,如果有与之匹配的驱动程序,便开始运用驱动程序提供的函数接口对接收卡进行操作与控制。驱动程序的工作流程大致如图5.4所示:接收卡通过设备管理器确认驱动是否能够控制接收卡,接着调用接收卡驱动的接口函数来初始化与USB相关的配置,之后再进行下载固件(downfirmware)操作和初始化接收卡上那些需要初始化的芯片。初始化完成后就使用FilterOpenoi垂i数来打开上层AP应用程序,接下来应用程序就可以调用驱动程序提供的程序接口来完成对接收卡的读写和控制,实现接收卡的交互。当应用程序需要关闭接收卡时,则先关闭上层应用程序,然后可通过调用DevieeRemove()函数来关闭由DeviceStartO函数打开的设备。如果要卸载接收卡驱动时,由设备管理器调用完成。5.2.2RC文件编写驱动,除了前面介绍过的MAKEFILE文件、SOURCE文件,还有就是这个.rc文件是必须的,主要就是一些关于驱动文件版本、产品版本等一些产品信息,其具体内容如下:#include”resource.h”VSVERSIOND盯OVERSIoNINFOFILEVERSION1,0,0,2//文件版本PRODuCTVERsION0,0,O,O/庐品版本FILEFLAGSMASK0x3fL存ifdefDEBUG//用于调试FILEFLAGS0xlL#elseFILEFLAGS0x0L#endifFILEOS0x40004LFILETYPE0x0LFILESUBTYPEOxOLBEGINBLOCK”StringFilelnfo”BEGINBLOCK”040904b0”BEGIN、,ALUE”Comments”.”\o”VALUE”CompanyName”。”\0”//公司名称VALUE”FileDescription”.-35-”DTV-DVBUDST7022BDADVB—SUSB

南京信息工程大学硕士学位论文基于Windows的USB接ISIWDM驱动研究和应用Box\0”Ⅵ~LUE”FileVersion”,”1,O,0,2\0”VALUE”IntemalName”.”UDST7022Bda.sys\0”VALUE”LegalCopyright”,”\o”VALUE”LegalTrademarks”.”\o”VALUE”OriginalFilename”.”UDST7022Bda.sys\O”VALUE”PrivateBuild”.”\0”VALUE”ProductName”。”\0”//产品名称VALUE”ProductVersion”,”0,0,0,0\0”、,ALUE”SpecialBuild”.”\o”ENDENDBLOCK”VarFileInfo”BEGINⅥ、LUE”Translation”,0x409,1200’ENDEND5.2.3关键源代码函数列举上一节已将接收卡的大致工作流程展示出来,下面将把前文没有给出的各关键函数拿出一些进行列举和讲述。1.驱动程序的入口程序,是硬件被识别后相应驱动程序的入口,详细代码如下:eXtem”C”NTSTATUSDriverEntry(INPD刚VER—OBJECTDriverObject,INPUNICODE——STRINGRegistryPath){NTSTATUSstatus;//返回状态OBJEC飞,骶RIBUTESattributes;HANDLEserviceKey;//句柄KEY——VALUE——PARTIAL—.INFORMATIONkeyValuelnfo;status=KslnitializeDriver(DriverObject,RegistryPath,&DeviceDescriptor);//classdriversdispatchfunctionpointerisstoredforlateruse.g_fpClassDispatchfunction2DriverObject一>MajorFunction[IRPMJDEVICE_CONTROL];DriverObject一>MajorFunction[IRPMJDEVICE_CONTROL】BDAIOCtrlDispatch;g_fpPnpDispatchfunetion5DriverObject->MajorFunction[IRP—MJ胛】;.36-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用DriverObject->MajorFunction[IRPMJ—州P】=BDAPNPDispatch;Ezusb_KdPrint(CDriverEntryOK:status=%灿Ⅶ№”,status));‘//这是监控打印语句,用于测试调控。returnstatus;)2.分发派遣表,在驱动程序的最上层,就是类似于这样的分发表,功能是上层AP对驱动程序调用的一个接口,如下图,这个表里就是程序中关于设备打开、关闭、插拔等功能实现所调用的接口表程序:constKSDEVICE_DISPATCHDeviceDispatch={严Add,术Start卜Stop严Remove奎/DeviceAdd.宰/DeviceStarL毒|DeviceStop、堆/DeviceRemove.产QueryCapabilities’|DeviceCapabilities..≯SurpriseRemoval’|DeviceSurpriseRemoval,捧SetPower≮lDeviceSetPower);3.DevieeStart函数,此驱动程序在图5.4中所列前期从初始化USB到初始化芯片这几项功能都是在此函数中实现的,当然中间又调用了StartDevice()函数,StartDevice()函数又调用了USB通信函数CalIUSBD()、USB初始化函数ConfigureDevice()、8051芯片复位函数Ezusb一8051Reset()、读取注册表信息函数GetRegistrySet()、读取接收卡ID函数TH_GetMac()和初始化TUNNER芯片和DEMODuLATOR芯片函数QST’_Init()。,宰宰宰牛●木木木术奉枣木宰拳术|‘宰木宰木木木|‘宰枣木牛宰事宰宰牛宰宰宰宰木|c乖幸木木事幸丰幸禾宰卑幸事木枣|c牛木宰幸宰宰|Ic宰|c●(1)NTSlATUSDeviceStart(INPKSDEVICEirp,device.INPIRPINPCM_RESOURCE_LISTtranslatedResources,INPCM_RESOURCE_LISTuntranslatedResources){DEVICE—CONTEXTNTSTATUS木pdx=GETCONTEXT(device);2result;pFilterFactoryNULL;PKSFILrERFACTORY//StartUSBdeviceresult=StartDevice(device);//CreateVirtualDVB—Sfilterfactoryif(pdx->SimuDevType&Ox00000001llpdx一>SimuDevType==0x00000000){//Createfilterfactory.37.

南室笪皇三堡盔堂堡主兰垡盗壅董王婴里!竺!!丝型!呈垄旦塑坚登型婴!i塑壅旦-___。_●-__-______-_-_-__-___-__--_______--I_-______-____●_-___---_I-。--___-●。_-__--I_-I_●●’’。。’。。’。。。1。。—’’——————一一一一一result=BdaCreateFilterFactory(device,&FilterDescriptor,&FilterTemplate);if(result!=STATUS_SUCCESS){returnresult;)}returnSTATUS_SUCCESS;),宰水枣木拳木水掌堆宰水牛幸枣掌宰木宰木水宰牛宰宰枣木宰水搴木木掌枣木|c木木宰木●木木枣木木|c水木幸牛宰木宰书木幸木宰枣木水|c水|I‘(2)StartDevice(INPKSDEVICEdevice){NTSTATI)SntStatus=STATUSSUCCESS;deviceDescriptor=NULL;PUSBDEVICEDESCRIPTORPURBULONGDEVICECONTEXT//Allocateurbstorageurburb=NULL:siz;*pdx=GETCONTEXT(device);sizeof(struct=(PURB)ExAllocatePool(NonPagedPool,_URB_CONTROL_DESCRIPTOR_REQUEST));if(urb—NULL、returnSTf盯USINSUFFICIENTRESOURCES;t|AllocateUSBDEVICEDESCRIPTORsiz=sizeof(USBDEVICE_DESCRIPTOR);deviceDescriptor=(PUSB_DEVICEDESCRIPTOR)ExAIlocatePool(NortPagedPool,siz);iffdeviceDescriptor—NULL)returnSTATUSINSUFFICIENT.RESOURCES;l|BuildGetDescriptorRequestUsbBuildGetDescriptorRequest(urb,(USHORT)sizeof(struct_URB_CONTROL_DESCRIPTOR_REQUEST),ntStatus=CallUSBD(device,urb);…。(成功赋值,失败释放内存)GETCONTEXT(device)->pUsblnfo->UsbDeViceDescriptor=deViceDescriptor;ExFreePool(urb);//ConfigureUSBdeviceUSB_DEVICE_DESCRIPTO唧PE,0,0,deviceDescriptor,NULL,siz,NULL);ntStams=ConfigureDevice(device);if州T{SUCCESS(ntStatus)).38-

—_-———-—●_●_—_●—_-●_●—I-—●-_—●—●_—_-●_—●'—-●-●_●_-I-—-_—_—-●。-●—-●—●_●-●-—●-_————————一一堕京信垦王堡丕堂堡圭堂垡坠銮一董王塑翌垒211盟型兰呈堡旦塑坚坚塾婴窒塑查旦//DownloadFirmwareve巧important!Ezusb_8051Reset(device,1);TWDownloadFX2(device,firmware.f'm-nware);Ezusb_8051Reset(device,o);if(IsTwinhanDev(device)){//InitTunePropertiesmemcpy(&pdx->InfProp,&pdx->TuneProp,sizeof(TUNEPROPERTIES));GetRegistrySet(device);|lGetMACTH_GetMac(device);//InitPLDInfo&checkpdx一>bAPUsePID2FALSE;QST_]【nit(device);pdx->tsbufp=O:returnntStatus;))),车|c|‘木奎|I水奎木+枣木幸奉幸书枣木车宰奉牛宰木鼍【幸木奎幸枣术木乖拳木幸木幸木事奉宰木幸木木枣木木木幸丰幸幸宰牛木木牛水幸事木木功能:对USB接口进行访问(3)NTSTATUSCalIUSBD(INPKSDEVICEdevice,INPURBUrb){NTSTATUSntStatus。status=STATUSSUCCESS;//statusforreturilDEVICE—CONTEXT木pdx=GETCONTEXT(device);//pointerPII冲irp;//interruptrequesttodeExtensionKeWaitForSingleObject(&pdx->WaitAccessFw,Executive,KemelMode,FALSE,NULL);KeResetEvent(&pdx->WaitAccessFw);//issueasynchronousKelnitializeEvent(&event,NotificationEvent,FALSE);irp=IoBuildDeviceloControlRequest(IOCTL_INTERNAL_.USB—SUBMIT-URB,device->PhysicalDeviceObject,NULL,0,NULL,0,TRUE,&event&ioStatus);//PrepareforcallingtheUSBdriverstackrequestnextStack=IoGetNextlrpStackLocation(irp);ASSERT(nextStack!=NULL);.39·

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用//SetuptheURBptrtopasstotheUSBdriverstacknextStack->Parameters.Others.Argumentl2Urb;//CalltheUSBclassdrivertoperformtheoperation.Ifthereturnedstatus//isPENDING,waitfortherequesttocomplete.ntStatus=IoCallDriver(deVice->PhysicalDeViceObject,irp);if(ntStatus—STATU时ENDING){status=KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE.NULL);//&TimeoutntStatus=ioStatus.Status;)if(NT-sUCCESS(ntStatus)){pdx->AccessFail=FALSE;}else{pdx->AccessFail=TRUE;}KeSetEvem(&pdx->WaitAccessFw,0,FALSE);returnntStatus;},木木乖枣木幸木术幸木牛串牛|EI#乖丰十幸,#幸木幸幸宰|‘牛枣木幸宰宰奉幸牛奉牛宰宰牛宰宰宰宰宰木枣木水宰幸枣枣木●奉幸宰II|‘牛幸●幸功能:初始化USB接口(4)NTSTATUSConfigureDevice(INPKSDEVICEdevice1{DEVICE—CONTEXT宰pdx=GETCONTEXT(device);//pointertoDeviceExtensionPURBurb=NULL;//urbPUSB_CONFIGURATIONDESCRIPTORconfigurationDescriptor2NULL:urb=(PURB)ExAllocatePool(NonPagedPool,sizeof(struct_uru3_cONTROL--DESCRIPTOR_REQUEST));//GetmemoryfortheUSBRequestBlock(urb).if(urb!=NULL){//Setsizeofthedatabuffer.Noteweaddpaddingto//thatmaycausecoverhardwarefaultsthedevicetogopasttheendofthedatabuffersiz=sizeof(USB_CONFIGURATION_DESCRIPTOR)+16;//GetthenonpagedpoolmemoryforthedatabufferconfigurationDescriptor=(PUSB_CONFlGURATIONDESCRIPTOR)ExAllocatePool(NonPagedPool,siz);if(configurationDescriptor!=NULLl.-40.-

南京信息工程大学硕士学位论文基于Windows的USB接121WDM驱动研窒麴应用{UsbBuildGetDescriptorRequest(urb,(USHORT)sizeof(structURB_CONTROL_DESCRIPTOR_REQUEST),USB_CONFIGURATION_DESCRIPTOR_TYPE,0,0,configurationDescriptor,NULL,sizeof(USB_CONFIGURATION_DESCRIPTOR),7掌Getonlytheconfigurationdescriptor木/NULL);}))4.FilterCreate()函数与FilterClose()函数。这两个函数一个是用来打开上层AP,将AP与设备相连接,一个是相反的关闭上层AP,断开连接。它们所做的动作基本是相反动作。这里只给出FilterCreate()函数。NTSTATUSFilterCreate(INPKSFILTERFilter,INPIRPIrp){NTSTATUSresult;PKSDEVICEdevice;Filter->Context=KsFilterGetDevice(Filter);if((Filter->Context—NULL)I|(((PKSDEVICE)Filter->Context)->Come)【t—NULL))returnSTATUS_DEVICE_NOT_CONNECTED;device=(PKSDEVICE)Filter->Context;//Prepareforactionresult=BdalnitFilter(Filter,&FilterTemplate);returnSTATUS_SUCCESS;)5.12Cread()函数与12Cwrite()函数。本卫星视频接收卡运用的通讯方式是12C总线方式,所以12C访问控制函数在整个驱动程序中占有举足轻重的作用,在12C函数中,调用了TWVendorRequest()这个函数,其作用就是将数据构造成一个URB传递给USB总线。12Cread()函数体如下:void12CRead(BYTEdeviceAddr,BYTEregAddrNum,WORDregAddr,BYTElength,BYTE木buffer){VENDOR_REQUEST_INDEVICEUINT8VenReq;CONTEXT木pdx=GETCONTEXT(g_device);pbuffer[256];。41—

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用RtlZeroMemory(buffer,length);VenReq.bRequest=0xB9;VenReq。direction=USBD_TRANSFER_DIRECTION_IN;VenReq.wIndex=regAddr;VenReq.wValue=deviceAddr+(regAddrNum<<8);VenReq。wLength=length+5;TW_VendorRequest(g_device,&VenReq,pbuffer);for(i=O;i<length;i++){buffer[i】-pbuffer[i+5];})5.2.4数字签名要想被微软认为其合法,就得通过微软的驱动程序数字签名,也称“数字驱动签署”,通过此认证,就表明驱动程序是和Windows系统是兼容的,在最新的WindowsVista操作系统中,这一问题就很突出。因为如果你的驱动没有通过微软的认证,在安装时就会出现无法安装的问题,必须要在启动操作系统之前选中启动后不去认证数字签名后,才可以安装。要想获得微软的驱动数字签名,必须要通过微软的DTM(驱动程序测试管理器)的各项测试,其中包括43个严格的测试项目。涵盖系统、芯片组、软件、运行时效和稳定性等范畴。微软对测试的结果进行评估,然后决定是否通过认证。5.3接收测试测试环节是程序开发中的重要环节,本节将对接收卡的驱动程序进行测试,从多个方面去检测驱动程序的性能。测试用PC采用各种级别性能以及各种主板进行,测试系统采用WindowsXP/VISTA。上层AP采用己被此卡接口兼容的DigitalTV媒体播放工具。开发过驱动程序的人应该都知道,驱动程序如果程序内部有一些小问题,例如变量没有初始化,循环在某些情况退出失败,都会很容易导致操作系统蓝屏或死机。因此就应该运Dbgview进行打印信息跟踪,或运用修改注册表进行注册表跟踪,或使用微软WinDbg进行蓝屏问题的内存拷贝分析。5.3.1测试中发现并解决的问题在测试过程中,发现了不少驱动中存在的问题,现将举出一些由于软件原因而出现的BUG例子:1.在WindowsVISTA32位系统下测试中发现,反复插拔接收卡电源,当刚刚插上电.42.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用源后不久,会出现操作系统蓝屏的问题。原因在于在驱动程序中的DeviceAdd()函数中,有一个会被用到的全局变量gdevice被赋予了NuLL空值,将其去掉,也就是不用先给全局变量gdevice赋空值,便不再出现蓝屏的问题,具体为什么还没搞清楚。2.在WindowsVISTA64位系统下测试中发现,保持AP打开状态,然后让操作系统进入休眠状态,当唤醒操作系统后,播放之前已经锁定的频道,出现无法播放和所搜频道的情况。经过错误查询,发现问题出在当操作系统休眠的过程中,板卡的一些芯片的供电发生了改变,在醒来以后就无法正常工作了。所以,在驱动的休眠操作函数里的WakeUp动作里加了对相关问题芯片的复位操作,问题解决。3.在WindowsXP64位系统下测试中发现,AP无法锁定频道,锁台总是失败,经过排查,最后发现在芯片原厂提供的锁台代码中锁定频道代码段中有一个未初始化的变量参与了锁台判定。虽然都是Windows的操作系统,但在各种操作系统下对变量的初始化值都有所不同,在WindowsXP64位系统下,对变量的初始化值过于大,影响了锁台判定。又发现此变量无其他作用,便将其删除,剥离出程序,问题解决。5.3.2接收功能测试接收卡在驱动程序加载后就可以开始接收DVB.S电视信号,测试中使用采用已被此卡接口兼容的DigitalTV媒体播放工具,该媒体播放器可以实时播放来自USB接口MPEG.2传输流。测试地点为南京,测试的台为中央电视台综合频道及CCTVl,此时正在播放连续剧《京华烟云》。此频点的频点信息为:频率3840MHZ、码率27500。画面为节目正在进行播放,背景为DebugView正在运用驱动打印信息检测驱动运行情况。经过PID过滤后,接收卡通过USB接口向DigitalTV媒体播放工具发送TS流码,码流经过媒体播放器进行解码后就可播放,如图5.5所示:-43-

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应围图5.5应用程序播放的电视节目画面5.3.3测试中发现而未能解决的问题接收卡在测试中驱动程序能够正确加载,加载后配合应用程序实现电视节目的实时播放,基本达到了设计的要求,但是在测试也发现了一些问题暂时无法解决有待改进。1.全频段扫描时间过长,整个过程需时3分钟以上。由于测试用的程序目的是确定接收卡是否能在指定频点上找到信号,在编写测试程序时没有考虑的搜索算法的效率,而且锁台代码基本是由芯片厂商直接提供,也应该负有一定责任,上层应用软件在设计时也需要考虑这一问题。2.全频段扫描时,出现个别频点扫描失败的情况。可能在驱动程序和硬件上都存在设计缺陷,还有待改进和进一步查证。.44.

南京信息工程大学硕士学位论文基于Windows的USB接口WDM驱动研究和应用弟/\早思菊第六章总结本文论述了采用USB接口的DVB.S接收卡驱动程序的设计与实现。接收卡驱动遵循DVB.S标准和USB协议,符合Windows平台下的驱动程序规范。接收卡在硬件设计上采用ZLl0039与ZLl031x的双芯片方案,通过USB接口将码流送到Windows设备。接收卡驱动程序按照Windows平台下USB驱动的规范进行开发,实现了设备的正确加载。驱动加载后,上层应用软件通过调用驱动程序提供的函数实现电视节目的接收播放。经测试,接收卡驱动实现了DVB.S信号的正确接收,并能配合应用程序完成电视节目的播放,达到设计要求。本人负责的接收卡驱动程序编写的工作己基本完成,但是在测试过程中也发现了一些需要改进的问题,这些将是后续工作需要解决的问题。