基于Windows8与Visual Studio11开发第一个USB内核驱动程序

USB ,是英文Universal Serial BUS(通用串行总线)的缩写,而其中文简称为“通串线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。USB接口支持设备的即插即用和热插拔功能。USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出的。

 

从1994年11月11日发表了USB V0.7版本以后,USB版本经历了多年的发展,到现在已经发展为3.0版本,成为目前电脑中的标准扩展接口。目前主板中主要是采用USB1.1和USB2.0,各USB版本间能很好的兼容。USB用一个4针(USB3.0标准为9针)插头作为标准插头,采用菊花链形式可以把所有的外设连接起来,最多可以连接127个外部设备,并且不会损失带宽。USB需要主机硬件、操作系统和外设三个方面的支持才能工作。目前的主板一般都采用支持USB功能的控制芯片组,主板上也安装有USB接口插座,而且除了背板的插座之外,主板上  USB接口
还预留有USB插针,可以通过连线接到机箱前面作为前置USB接口以方便使用(注意,在接线时要仔细阅读主板说明书并按图连接,千万不可接错而使设备损坏)。而且USB接口还可以通过专门的USB连机线实现双机互连,并可以通过Hub扩展出更多的接口。USB具有传输速度快(USB1.1是12Mbps,USB2.0是480Mbps,USB3.0是5 Gbps),使用方便,支持热插拔,连接灵活,独立供电等优点,可以连接鼠标、键盘、打印机、扫描仪、摄像头、闪存盘、MP3机、手机、数码相机、移动硬盘、外置光软驱、USB网卡、ADSL Modem、Cable Modem等,几乎所有的外部设备。   USB接口可用于连接多达127个外设,如鼠标、调制解调器和键盘等。USB自从1996年推出后,已成功替代串口和并口,并成为当今个人电脑和大量智能设备的必配的接口之一。   USB各版本区别版本最大传输速率速率称号最大输出电流协议推出时间:   USB1.0:1.5Mbps(192KB/s)低速(Low-Speed)500mA……1996年1月   USB1.1:12Mbps(1.5MB/s)全速(Full-Speed)500mA……1998年9月   USB2.0:480Mbps(60MB/s)高速(High-Speed)500mA……2000年4月   USB3.0:5Gbps(640MB/s)超速(Super-Speed)900mA……2008年11月
USB的应用
  随着计算机硬件飞速发展,外围设备日益增多,键盘、鼠标、调制解调器、打印机、扫描仪早已为人所共知,数码相机、MP3随身听接踵而至,这么多的设备,如何接入个人计算机?USB就是基于这个目的产生的。USB是一个使计算机周边设备连接标准化、单一化的接口,其规格是由Intel(英特尔)、NEC、Compaq、DEC、IBM(商业机器公司)、Microsoft(微软)、Northern Telecom联系制定的。   USB1.1标准接口传输速率为12Mbps,但是一个USB设备最多只可以得到6Mbps的传输频宽。因此若要外接光驱,至多能接六倍速光驱,无法再高。而若要即时播放MPEG-1的VCD影片,至少要1.5Mbps的传输频宽,这点USB办得到,但是要完成数据量大四倍的MPEG-2的DVD影片播放,USB可能就很吃力了,若再加上AC-3音频数据,USB设备就很难实现即时播放了。   一个USB接口理论上可以支持127个装置,但是目前还无法达到这个数字。其实,对于一台计算机,所接的周边外设很少有超过10个的,因此这个数字是足够我们使用的。   USB还有一个显著优点就是支持热插拔,也就是说在开机的情况下,你也可以安全地连接或断开USB设备,达到真正的即插即用。不过,并非所有的Windows系统都支持USB。目前,Windows系统中有许多不同的版本,在这些版本中,只有Windows98以上版本的系统对USB的支持较好,而其他的Windows版本并不能完整支持USB。例如Windows95的零售版是不支持USB的,只有后来与PC捆绑销售的Windows95版本才支持USB。   目前USB设备虽已被广泛应用,比较普遍的是USB2.0接口,它的传输速度为480Mbps。用户的需求,是促进科技发展的动力,厂商也同样认识到了这个瓶颈。这时, COMPAQ、Hewlett Packard、Intel、Lucent、Microsoft、NEC和PHILIPS这7家厂商联合制定了USB 2.0接口标准。USB 2.0将设备之间的数据传输速度增加到了480Mbps,比USB 1.1标准快40倍左右,速度的提高对于用户的最大好处就是意味着用户可以使用到更高效的外部设备,而且具有多种速度的周边设备都可以被连接到USB 2.0的线路上,而且无需担心数据传输时发生瓶颈效应。   所以,如果你用USB 2.0的扫描仪,就完全不同了,扫一张4M的图片只需0.1秒钟左右的时间,一眨眼就过去了,效率大大提高。   而且,USB2.0可以使用原来USB定义中同样规格的电缆,接头的规格也完全相同,在高速的前提下一样保持了USB 1.1的优秀特色,并且,USB 2.0的设备不会和USB 1.X设备在共同使用的时候发生任何冲突。   USB2.0兼容USB1.1,也就是说USB1.1设备可以和USB2.0设备通用,但是这时USB2.0设备只能工作在全速状态下(12Mbit/s)。USB2.0有高速、全速和低速三种工作速度,高速是480Mbit/s,全速是12Mbit/s,低速是1.5Mbit/s。其中全速和低速是为兼容USB1.1和USB1.0而设计的,因此选购USB产品时不能只听商家宣传USB2.0,还要搞清楚是高速、全速还是低速设备。USB总线是一种单向总线,主控制器在PC机上,USB设备不能主动与PC机通信。为解决USB设备互通信问题,有关厂商又开发了USB OTG标准,允许嵌入式系统通过USB接口互相通信,从而甩掉了PC机。   新USB2.0规范重新命名了USB标准将原先的USB 1.1改成了USB 2.0 Full Speed(全速版),同时将原有的USB 2.0改成了USB 2.0High-Speed(高速版),并同时公布了新的标识。不言而喻,高速版的USB 2.0速度当然超过全速版的USB 2.0。   电脑USB端口可以提供最大电流为500mA。
基本特性
1.USB的硬件结构
  USB采用四线电缆,其中两根是用来传送数据的串行通道,另两根为下游(Downstream)设备提供电源,对于高速且需要高带宽的外设,USB以全速12Mbps的传输数据;对于低速外设,USB则以1.5Mbps的传输速率来传输数据。USB总线会根据外设情况在两种传输模式中自动地动态转换。USB是基于令牌的总线。类似于令牌环网络或FDDI基于令牌的总线。USB主控制器广播令牌,总线上设备检测令牌中的地址是否与自身相符,通过接收或发送数据给主机来响应。USB通过支持悬挂/恢复操作来管理USB总线电源。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机(Host),集线器(Hub)和功能设备。   主机,也称为根,根结或根Hub,它做在主板上或作为适配卡安装在计算机上,主机包含有主控制器和根集线器(Root Hub),控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。   集线器是USB结构中的特定成分,它提供叫做端口(Port)的点将设备连接到USB总线上,同时检测连接在总线上的设备,并为这些设备提供电源管理,负责总线的故障检测和恢复。集线可为总线提供能源,亦可为自身提供能源(从外部得到电源),自身提供能源的设备可插入总线提供能源的集线器中,但总线提供能源的设备不能插入自身提供能源的集线器或支持超过四个的下游端口中,如总线提供能源设备的需要超过100mA电源时,不能同总线提供电源的集线器连接。   功能设备通过端口与总线连接。USB同时可做Hub使用。
2.USB的软件结构
  每个USB只有一个主机,它包括以下几层:   (1)USB总线接口   USB总线接口处理电气层与协议层的互连。从互连的角度来看,相似的总线接口由设备及主机同时给出,例如串行接口机(SIE)。USB总线接口由主控制器实现。   (2)USB系统   USB系统用主控制器管理主机与USB设备间的数据传输。它与主控制器间的接口依赖于主控制器的硬件定义。同时,USB系统也负责管理USB资源,例如带宽和总线能量,这使客户访问USB成为可能。USB系统还有三个基本组件:   主控制器驱动程序(HCD)这可把不同主控制器设备映射到USB系统中。HCD与USB之间的接口叫HCDI,特定的HCDI由支持不同主控制器的操作系统定义,通用主控制器驱动器(UHCD)处于软结构的最底层,由它来管理和控制主控制器。UHCD实现了与USB主控制器通信和控制USB主控制器,并且它对系统软件的其他部分是隐蔽的。系统软件中的最高层通过UHCD的软件接口与主控制器通信。   USB驱动程序(USBD)它在UHCD驱动器之上,它提供驱动器级的接口,满足现有设备驱动器设计的要求。USBD以I/O请求包(IRPs)的形式提供数据传输架构,它由通过特定管道(Pipe)传输数据的需求组成。此外,USBD使客户端出现设备的一个抽象,以便于抽象和管理。作为抽象的一部分,USBD拥有缺省的管道。通过它可以访问所有的USB设备以进行标准的USB控制。该缺省管道描述了一条USBD和USB设备间通信的逻辑通道。   主机软件 在某些操作系统中,没有提供USB系统软件。这些软件本来是用于向设备驱动程序提供配置信息和装载结构的。在这些操作系统中,设备驱动程序将应用提供的接口而不是直接访问USBDI(USB驱动程序接口)结构。   (3)USB客户软件   它是位于软件结构的最高层,负责处理特定USB设备驱动器。客户程序层描述所有直接作用于设备的软件入口。当设备被系统检测到后,这些客户程序将直接作用于外围硬件。这个共享的特性将USB系统软件置于客户和它的设备之间,这就要根据USBD在客户端形成的设备映像由客户程序对它进行处理。   主机各层有以下功能:   检测连接和移去的USB设备。   管理主机和USB设备间的数据流。   连接USB状态和活动统计。   控制主控制器和USB设备间的电气接口,包括限量能量供应。   HCD提供了主控制器的抽象和通过USB传输的数据的主控制器视角的一个抽象。USBD提供了USB设备的抽象和USBD客户与USB功能间数据传输的一个抽象。USB系统促进客户和功能间的数据传输,并作为USB设备的规范接口的一个控制点。USB系统提供缓冲区管理能力并允许数据传输同步于客户和功能的需求。
3.USB的数据流传输
  主控制器负责主机和USB设备间数据流的传输。这些传输数据被当作连续的比特流。每个设备提供了一个或多个可以与客户程序通信的接口,每个接口由0个或多个管道组成,它们分别独立地在客户程序和设备的特定终端间传输数据。USBD为主机软件的现实需求建立了接口和管道,当提出配置请求时,主控制器根据主机软件提供的参数提供服务。   USB支持四种基本的数据传输模式:控制传输,等时传输,中断传输及数据块传输。每种传输模式应用到具有相同名字的终端,则具有不同的性质。   控制传输类型 支持外设与主机之间的控制,状态,配置等信息的传输,为外设与主机之间提供一个控制通道。每种外设都支持控制传输类型,这样主机与外设之间就可以传送配置和命令/状态信息。   等时(lsochronous)传输类型 支持有周期性,有限的时延和带宽且数据传输速率不变的外设与主机间的数据传输。该类型无差错校验,故不能保证正确的数据传输,支持像计算机-电话集成系统(CTI)和音频系统与主机的数据传输。   中断传输类型 支持像游戏手柄,鼠标和键盘等输入设备,这些设备与主机间数据传输量小,无周期性,但对响应时间敏感,要求马上响应。   数据块(Bulk)传输类型 支持打印机,扫描仪,数码相机等外设,这些外设与主机间传输的数据量大,USB在满足带宽的情况下才进行该类型的数据传输。   USB采用分块带宽分配方案,若外设超过当前带宽分配或潜在的要求,则不能进入该设备。同步和中断传输类型的终端保留带宽,并保证数据按一定的速率传送。集中和控制终端按可用的最佳带宽来传输传输数据。
USB vs IEEE1394
一、USB与IEEE1394的相同点主要有哪些?
  两者都是一种通用外接设备接口。   两者都可以快速传输大量数据。   两者都能连接多个不同设备。   两者都支持热插拨。   两者都可以不用外部电源。
二、USB与IEEE1394的不同点有哪些?
  两者的传输速率不同。USB最高的速度可达5Gb/s,但由于USB3.0尚未普及,目前主流的USB2.0只有480Mb/s,并且速度不稳定;相比之下,IEEE1394目前的速度虽然只有800Mb/s,但较为稳定,故在数码相机等高速设备中还保留了IEEE1394接口,但也开始采用USB接口了。   两者的结构不同。USB在连接时必须至少有一台电脑,并且必须需要HUB来实现互连,整个网络中最多可连接127台设备。IEEE1394并不需要电脑来控制所有设备,也不需要HUB,IEEE1394可以用网桥连接多个IEEE1394网络,也就是说在用IEEE1394实现了63台IEEE1394设备之后也可以用网桥将其他的IEEE1394网络连接起来,达到无限制连接。   两者的智能化不同。IEEE1394网络可以在其设备进行增减时自动重设网络。USB是以HUB来判断连接设备的增减了。   两者的应用程度不同。现在USB已经被广泛应用于各个方面,几乎每台PC主板都设置了USB接口,USB2.0也会进一步加大USB应用的范围。IEEE1394现在只被应用于音频、视频等多媒体方面。
USB的扩展应用及发展趋势
前置USB接口
  前置USB接口是位于机箱前面板上的USB扩展接口。目前,使用USB接口的各种外部设备越来越多,例如移动硬盘、闪存盘、数码相机等等,但在使用这些设备(特别是经常使用的移动存储设备)时每次都要钻到机箱后面去使用主板板载USB接口显然是不方便的。前置USB接口在这方面就给用户提供了很好的易用性。目前,前置USB接口几乎已经成为机箱的标准配置,没有前置USB接口的机箱已经非常少见了。   前置USB接口要使用机箱所附带的USB连接线连接到主板上所相应的前置USB插针(一般是8针、9针或10针,两个USB成对,其中每个USB使用4针传输信号和供电)上才能使用。在连接前置USB接口时一定要事先仔细阅读主板说明书和机箱说明书中与其相关的内容,千万不可将连线接错,不然会造成USB设备或主板的损坏。   另外,由于USB2.0接口输出电压为5V,输出电流为500mA。使用前置USB接口时要注意前置USB接口供电不足的问题,在使用耗电较大的USB设备时,要使用外接电源或直接使用机箱后部的主板板载USB接口,以避免USB设备不能正常使用或被损坏。
USB口硬盘盒
  目前的主流,其最大优点是使用方便,支持热插拔和即插即用。USB有两种标准:一种是USB1.1接口,其传输速度只有12Mbps,一种是USB2.0接口,其传输速度高达480Mbps。目前的主板上的USB都支持USB1.1,但USB 2.0只有较新的主板才能支持,购买时根据个人情况选择产品,虽然USB2.0向下兼容USB1.1,但支持USB2.0接口的移动硬盘盒比USB1.1的要贵一些。
无线USB
  USB开发者论坛的主席兼英特尔公司的技术策略官Jeff Ravencraft表示,无线USB技术将帮助用户在使用个人电脑连接打印机、数码相机、音乐播放器和外置磁盘驱动器等设备时,从纷繁复杂的电缆连线中解放出来。无线USB标准的数据传输速率与目前的有线USB 2.0标准是一样的,均为每秒480M,两者的区别在于无线USB要求在个人电脑或外设中装备无线收发装置以代替电缆连线。   在英特尔开发者论坛举办的前夕,Ravencraft称,首先采用这一标准的将是外置磁盘驱动器、数码相机和打印机。而越来越多的产品将在今年第三季度开始推向市场。   为了使无线USB标准得以实用,必须改善这一技术的一些不足。USB标准小组宣布了无线联盟规范,以确保只有经过认证才能让电脑和外设通过无线USB连接起来。   Ravencraft补充,一直以来USB标准已经广泛的用于将数码相机、扫描仪、手机、PDA、DVD刻录机和其他设备与个人电脑的连接。而无线联盟规范则详细规定了个人电脑和外设如何通过无线USB进行连接,一台电脑最多可以同时连接127个外设。   无线联盟规范规定了两种建立连接的方法。第一种方法是电脑和外设先用电缆连接起来,然后再建立无线连接以供以后使用。第二种方法是外设可以提供一串数字,用户在建立连接的时候输入到电脑里面。   无线USB采用超宽带技术进行通信。目前无线局域网的802.11g协议采用位于2.4GHz附近的一小段频带进行通信,而超宽带技术则采用从3.1GHz到10.6GHz的频带进行通信。超宽带的信号水平足够低,因此对于其他无线通信技术来说,超宽带信号的影响类似于噪声。   无线网络目前广泛使用的技术是IEEE的802.11标准,也就是英特尔所推动的Wi-Fi。这一技术广泛的使用在笔记本电脑上,甚至部分尼康公司和佳能公司的数码相机也采用这一技术。而无线USB技术则是一个完全不同的技术,由于这一技术实现上相对简单同时功耗只有802.11的一半,因此不少厂商都更愿意采用无线USB技术。   Ravencraft表示,在高端的手机和数码相机上采用802.11技术,关键是要解决电池寿命问题。而厂商们发现超宽带技术是解决这一问题的最好的办法。   在距离电脑10英尺范围内,无线USB设备的传输速率将保持每秒480M。如果在30英尺范围内,传输速率将下降到每秒110M。然而随着技术的发展,无线USB的传输速率将会超过每秒1G甚至更快。   目前超宽带技术不仅可以用于无线USB连接中,还可以在蓝牙和IEEE的1394火线连接甚至WiNet短距离连接中使用。
USB的不同接口与数据线
  随着各种数码设备的大量普及,特别是MP3和数码相机的普及,我们周围的USB设备渐渐多了起来。然而这些设备虽然都是采用了USB接口,但是这些设备的数据线并不完全相同。
USB接口(12张)这些数据线在连接PC的一端都是相同的,但是在连接设备端的时候,通常出于体积的考虑而采用了各种不同的接口。   绝大部分数码产品连接线的接头除了连在PC上的都一样,另外一头也都是遵循着标准的规格。   USB是一种统一的传输规范,但是接口有许多种,最常见的就是咱们电脑上用的那种扁平的,这叫做A型口,里面有4根连线,根据谁插接谁分为公母接口,一般线上带的是公口,机器上带的是母口。
USB A型公口
  右上面的图片是最常见的USB A型公口   常见Mini B型5Pin接口:   接下来就是在数码产品上最常见的接口了,由于数码产品体积所限,所以通常用的是Mini B型接口,但是Mini B型接口也有许多种类。
Mini B型5Pin
  右面的图为Mini B型5Pin接口示意图  
  这种接口可以说是目前最常见的一种接口了,这种接口由于防误插性能出众,体积也比较小巧,所以正在赢得越来越多的厂商青睐,现在这种接口广泛出现在读卡器、MP3、数码相机以及移动硬盘上。   下图为:Sony F828上的Mini B型5Pin接口   目前采用这种接口的设备目前有SONY相机、摄像机和MP3,Olympus相机和录音笔,佳能相机和惠普的数码相机等等,数量相当繁多。   常见Mini B型4Pin接口:   除了前面我们看到的最常见的Mini B型5Pin的接口以外,Mini B型还有很多种别的接口,其中的一些也比较常见。
Mini B型4Pin
  右图为:Mini B型4Pin的接口   下图为:Mini B型4Pin的接口的转接线缆   这种接口常见于以下品牌的数码产品:奥林巴斯的C系列和E系列,柯达的大部分数码相机,三星的MP3产品(如Yepp),SONY的DSC系列,康柏的IPAQ系列产品……   富士Mini B型4Pin Flat接口:   Mini B型4Pin还有一种形式,那就是Mini B型4Pin Flat。顾名思义,这种接口比Mini B型4Pin要更加扁平,在设备中的应用也比较广泛。
富士Mini B型4Pin Flat
  右图为:Mini B型4Pin Flat接口   这种接口和前面讲腗INI B型4pin非常类似,但是这种接头更为扁平,所占用的体积更小。   这种接口常见于以下设备:富士的FinePix系列,卡西欧的QV系列相机,柯尼卡的产品。   我们看到,富士的机器用这种接口的比较多,几乎旧有的机型全是这种接口。不过值得注意的是,富士在最新的S5000和S7000上已经放弃了这种接口,改投Mini B 5Pin的阵营。   尼康独有,Mini B型8Pin接口:   Mini B型除了前面的4Pin和5Pin的,还有一种就是8Pin的了,这种接头在其他设备上出现的几率就非常少了,通常出现在数码相机上。Mini B型的接口也有3种,一种是普通型的,一种是Round(圆)型的,还有一种是2×4布局的扁平接口。
MINI B型8Pin
  右图为:Mini B型8Pin的接口   这种接口适用的设备,据笔者所知目前只有Nikon Coolpix 775一个款型的产品使用这种接口。
Mini B型8Pin Round
  左图为:Mini B型8Pin Round接口   这种接口和前面的普通型比起来,就是将原来的D型接头改成了圆形接头,并且为了防止误插在一边设计了一个凸起。   这种接头可以见于一些Nikon的数码相机,CoolPix系列比较多见。虽然Nikon一直坚持用这种接口,但是在一些较新的机型中,例如D100和CP2000也都采用了普及度最高的Mini B型5Pin接口。   差点儿就普及,8Pin 2×4接口:   除了我们前面见过的Mini B型5Pin的接口,我想大家一定还对下面这种接口非常熟悉,这种接口也曾经相当的普及。
Mini B型8Pin 2×4
  图为:Mini B型8Pin 2×4接口   这种接口也是一种比较常见的接口了,例如我们熟悉的iRiver的著名的MP3系列,其中号称“铁三角”的180TC,以及该系列的很多其他产品采用的均是这种接口。这种接口的应用范围也还算是广,不过从iRiver自3XX系列全面换成Mini B型5Pin的接口后,这种规格明显没有Mini B型5Pin抢眼了。   对应部分图片:  常见USB图片

USB On-The-Go补充标准
  USB On-The-Go Supplement 1.0:2001年12月发布。USB On-The-Go Supplement 1.0a:2003年6月发布,即当前版本。   USB OTG是USB On-The-Go的缩写,是近年发展起来的技术,2001年12月18日由USB Implementers Forum公布,主要应用于各种不同的设备或移动设备间的联接,进行数据交换。特别是PDA、移动电话、消费类设备。改变如数码照相机、摄像机、打印机等设备间多种不同制式连接器,多达7种制式的存储卡间数据交换的不便。   USB技术的发展,使得PC和周边设备能够通过简单方式、适度的制造成本将各种数据传输速度的设备连接在一起,上述我们提到应用,都可以通过USB总线,作为PC的周边,在PC的控制下进行数据交换。但这种方便的交换方式,一旦离开了PC,各设备间无法利用USB口进行操作,因为没有一个从设备能够充当PC一样的Host。   On-The-Go,即OTG技术就是实现在没有Host的情况下,实现从设备间的数据传送。例如数码相机直接连接到打印机上,通过OTG技术,连接两台设备见的USB口,将拍出的相片立即打印出来;也可以将数码照相机中的数据,通过OTG发送到USB接口的移动硬盘上,野外操作就没有必要携带价格昂贵的存储卡,或者背一个便携电脑。   在OTG产品中,增加了一些新的特性:   * 新的标准,适用于设计小巧的连接器和电缆;   * 在传统的周边设备上,增加了Host能力,适应点到点的连接;   * 这种能力可以在两个设备间动态地切换;   * 低的功耗,保证USB可以在电池供电情况下工作   使用OTG后,不影响原设备和PC的连接,但使得在市场上已有超过10亿个USB接口的设备,也能通过OTG互联。

下面我们来亲自实践基于Windows8与Visual Studio11的开发

Visual studio11与Windows8带来格外不同的新体验

 

1.启动Vs11

2.看见满目的驱动开发模板

3.选择USB内核模式

4.我们看见驱动安装包,以及驱动程序框架

 

5.按下F5选择继续调试

6.编译成功,选择虚拟机进行调试

7.开始调试

 

 

 

8.具体代码分析,设备代码如下

/*++

Module Name:

    device.c - Device handling events for example driver.

Abstract:

   This file contains the device entry points and callbacks.
    
Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "device.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, USBDriverMVPCreateDevice)
#pragma alloc_text (PAGE, USBDriverMVPEvtDevicePrepareHardware)
#endif


NTSTATUS
USBDriverMVPCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    DeviceInit - Pointer to an opaque init structure. Memory for this
                    structure will be freed by the framework when the WdfDeviceCreate
                    succeeds. So don't access the structure after that point.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = USBDriverMVPEvtDevicePrepareHardware;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (NT_SUCCESS(status)) {
        //
        // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an
        // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the
        // device.h header file. This function will do the type checking and return
        // the device context. If you pass a wrong object  handle
        // it will return NULL and assert if run under framework verifier mode.
        //
        deviceContext = WdfObjectGet_DEVICE_CONTEXT(device);
        deviceContext->PrivateDeviceData = 0;

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(
            device,
            &GUID_DEVINTERFACE_USBDriverMVP,
            NULL // ReferenceString
            );

        if (NT_SUCCESS(status)) {
            //
            // Initialize the I/O Package and any Queues
            //
            status = USBDriverMVPQueueInitialize(device);
        }
    }

    return status;
}

NTSTATUS
USBDriverMVPEvtDevicePrepareHardware(
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourceList,
    _In_ WDFCMRESLIST ResourceListTranslated
    )
/*++

Routine Description:

    In this callback, the driver does whatever is necessary to make the
    hardware ready to use.  In the case of a USB device, this involves
    reading and selecting descriptors.

Arguments:

    Device - handle to a device

Return Value:

    NT status value

--*/
{
    NTSTATUS status;
    PDEVICE_CONTEXT pDeviceContext;
    WDF_USB_DEVICE_CREATE_CONFIG createParams;
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;

    UNREFERENCED_PARAMETER(ResourceList);
    UNREFERENCED_PARAMETER(ResourceListTranslated);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    status = STATUS_SUCCESS;
    pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(Device);

    if (pDeviceContext->UsbDevice == NULL) {

        //
        // Specifying a client contract version of 602 enables us to query for
        // and use the new capabilities of the USB driver stack for Windows 8.
        // It also implies that we conform to rules mentioned in MSDN
        // documentation for WdfUsbTargetDeviceCreateWithParameters.
        //
        WDF_USB_DEVICE_CREATE_CONFIG_INIT(&createParams,
                                         USBD_CLIENT_CONTRACT_VERSION_602
                                         );

        status = WdfUsbTargetDeviceCreateWithParameters(Device,
                                                    &createParams,
                                                    WDF_NO_OBJECT_ATTRIBUTES,
                                                    &pDeviceContext->UsbDevice
                                                    );

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
                        "WdfUsbTargetDeviceCreateWithParameters failed 0x%x", status);
            return status;
        }

        //
        // Select the first configuration of the device, using the first alternate
        // setting of each interface
        //
        WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&configParams,
                                                                     0,
                                                                     NULL
                                                                     );
        status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,
                                                WDF_NO_OBJECT_ATTRIBUTES,
                                                &configParams
                                                );

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
                        "WdfUsbTargetDeviceSelectConfig failed 0x%x", status);
            return status;
        }
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

9.驱动代码如下


/*++

Module Name:

    driver.c

Abstract:

    This file contains the driver entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "driver.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, USBDriverMVPEvtDeviceAdd)
#pragma alloc_text (PAGE, USBDriverMVPEvtDriverContextCleanup)
#endif


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    DriverEntry initializes the driver and is the first routine called by the
    system after the driver is loaded. DriverEntry specifies the other entry
    points in the function driver, such as EvtDevice and DriverUnload.

Parameters Description:

    DriverObject - represents the instance of the function driver that is loaded
    into memory. DriverEntry must initialize members of DriverObject before it
    returns to the caller. DriverObject is allocated by the system before the
    driver is loaded, and it is released by the system after the system unloads
    the function driver from memory.

    RegistryPath - represents the driver specific path in the Registry.
    The function driver can use the path to store driver related data between
    reboots. The path does not store hardware instance specific data.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;

    //
    // Initialize WPP Tracing
    //
    WPP_INIT_TRACING( DriverObject, RegistryPath );

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Register a cleanup callback so that we can call WPP_CLEANUP when
    // the framework driver object is deleted during driver unload.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = USBDriverMVPEvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(&config,
                           USBDriverMVPEvtDeviceAdd
                           );

    status = WdfDriverCreate(DriverObject,
                             RegistryPath,
                             &attributes,
                             &config,
                             WDF_NO_HANDLE
                             );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
        WPP_CLEANUP(DriverObject);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

NTSTATUS
USBDriverMVPEvtDeviceAdd(
    _In_    WDFDRIVER       Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS status;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    status = USBDriverMVPCreateDevice(DeviceInit);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

VOID
USBDriverMVPEvtDriverContextCleanup(
    _In_ WDFDRIVER Driver
    )
/*++
Routine Description:

    Free all the resources allocated in DriverEntry.

Arguments:

    Driver - handle to a WDF Driver object.

Return Value:

    VOID.

--*/
{
    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE ();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Stop WPP Tracing
    //
    WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) );

}


 

/*++

Module Name:

    driver.c

Abstract:

    This file contains the driver entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "driver.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, USBDriverMVPEvtDeviceAdd)
#pragma alloc_text (PAGE, USBDriverMVPEvtDriverContextCleanup)
#endif


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    DriverEntry initializes the driver and is the first routine called by the
    system after the driver is loaded. DriverEntry specifies the other entry
    points in the function driver, such as EvtDevice and DriverUnload.

Parameters Description:

    DriverObject - represents the instance of the function driver that is loaded
    into memory. DriverEntry must initialize members of DriverObject before it
    returns to the caller. DriverObject is allocated by the system before the
    driver is loaded, and it is released by the system after the system unloads
    the function driver from memory.

    RegistryPath - represents the driver specific path in the Registry.
    The function driver can use the path to store driver related data between
    reboots. The path does not store hardware instance specific data.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;

    //
    // Initialize WPP Tracing
    //
    WPP_INIT_TRACING( DriverObject, RegistryPath );

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Register a cleanup callback so that we can call WPP_CLEANUP when
    // the framework driver object is deleted during driver unload.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = USBDriverMVPEvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(&config,
                           USBDriverMVPEvtDeviceAdd
                           );

    status = WdfDriverCreate(DriverObject,
                             RegistryPath,
                             &attributes,
                             &config,
                             WDF_NO_HANDLE
                             );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
        WPP_CLEANUP(DriverObject);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

NTSTATUS
USBDriverMVPEvtDeviceAdd(
    _In_    WDFDRIVER       Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS status;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    status = USBDriverMVPCreateDevice(DeviceInit);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

VOID
USBDriverMVPEvtDriverContextCleanup(
    _In_ WDFDRIVER Driver
    )
/*++
Routine Description:

    Free all the resources allocated in DriverEntry.

Arguments:

    Driver - handle to a WDF Driver object.

Return Value:

    VOID.

--*/
{
    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE ();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Stop WPP Tracing
    //
    WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) );

}

10.队列代码如下

/*++

Module Name:

    queue.c

Abstract:

    This file contains the queue entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "queue.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, USBDriverMVPQueueInitialize)
#endif

NTSTATUS
USBDriverMVPQueueInitialize(
    _In_ WDFDEVICE Device
    )
/*++

Routine Description:


     The I/O dispatch callbacks for the frameworks device object
     are configured in this function.

     A single default I/O Queue is configured for parallel request
     processing, and a driver context memory allocation is created
     to hold our structure QUEUE_CONTEXT.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    VOID

--*/
{
    WDFQUEUE queue;
    NTSTATUS status;
    WDF_IO_QUEUE_CONFIG    queueConfig;

    PAGED_CODE();
    
    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
         &queueConfig,
        WdfIoQueueDispatchParallel
        );

    queueConfig.EvtIoDeviceControl = USBDriverMVPEvtIoDeviceControl;

    status = WdfIoQueueCreate(
                 Device,
                 &queueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue
                 );

    if( !NT_SUCCESS(status) ) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", status);
        return status;
    }

    return status;
}

VOID
USBDriverMVPEvtIoDeviceControl(
    _In_ WDFQUEUE Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength,
    _In_ ULONG IoControlCode
    )
/*++

Routine Description:

    This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.

Arguments:

    Queue -  Handle to the framework queue object that is associated with the
             I/O request.

    Request - Handle to a framework request object.

    OutputBufferLength - Size of the output buffer in bytes

    InputBufferLength - Size of the input buffer in bytes

    IoControlCode - I/O control code.

Return Value:

    VOID

--*/
{
    TraceEvents(TRACE_LEVEL_INFORMATION, 
                TRACE_QUEUE, 
                "!FUNC! Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d", 
                Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode);

    WdfRequestComplete(Request, STATUS_SUCCESS);

    return;
}


 


/*++

Module Name:

    queue.c

Abstract:

    This file contains the queue entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "queue.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, USBDriverMVPQueueInitialize)
#endif

NTSTATUS
USBDriverMVPQueueInitialize(
    _In_ WDFDEVICE Device
    )
/*++

Routine Description:


     The I/O dispatch callbacks for the frameworks device object
     are configured in this function.

     A single default I/O Queue is configured for parallel request
     processing, and a driver context memory allocation is created
     to hold our structure QUEUE_CONTEXT.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    VOID

--*/
{
    WDFQUEUE queue;
    NTSTATUS status;
    WDF_IO_QUEUE_CONFIG    queueConfig;

    PAGED_CODE();
    
    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
         &queueConfig,
        WdfIoQueueDispatchParallel
        );

    queueConfig.EvtIoDeviceControl = USBDriverMVPEvtIoDeviceControl;

    status = WdfIoQueueCreate(
                 Device,
                 &queueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue
                 );

    if( !NT_SUCCESS(status) ) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", status);
        return status;
    }

    return status;
}

VOID
USBDriverMVPEvtIoDeviceControl(
    _In_ WDFQUEUE Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength,
    _In_ ULONG IoControlCode
    )
/*++

Routine Description:

    This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.

Arguments:

    Queue -  Handle to the framework queue object that is associated with the
             I/O request.

    Request - Handle to a framework request object.

    OutputBufferLength - Size of the output buffer in bytes

    InputBufferLength - Size of the input buffer in bytes

    IoControlCode - I/O control code.

Return Value:

    VOID

--*/
{
    TraceEvents(TRACE_LEVEL_INFORMATION, 
                TRACE_QUEUE, 
                "!FUNC! Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d", 
                Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode);

    WdfRequestComplete(Request, STATUS_SUCCESS);

    return;
}


 

赶紧下载VS11体验吧

http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200098144

 

posted on 2012-03-25 19:53  三少爷的剑123  阅读(246)  评论(0编辑  收藏  举报

导航