32位Windows操作系统下WDM型USB设备驱动程序设计

1. 前言
通用串行总线( USB)是由Intel、Compaq、Microsoft、IBM、Northern Telecom和NEC等7家公司发起制定的微机总线接口规范。它充分解决了日益增加的PC外设与有限的主板插槽和接口之间的矛盾。现在几乎所有的台式PC和便携式笔记本电脑都配备了USB接口,几乎所有流行的操作系统如Win98,Windows2000/xp,Linux等都支持USB功能。由于目前多数的开发工具还没有对USB进行控制的函数和控件,开发一个基于USB的应用系统(如基于USB的数据采集系统),就需要开发者自己写一个USB设备驱动程序。
2. USB 简介
一个 USB系统包括硬件系统和软件系统。硬件系统包括:USB主控制器,根集线器(HUB),USB集线器(HUB),USB设备。软件系统包括:USB类驱动程序,USB设备驱动程序,设备端固件程序和应用程序。USB的通信结构模型如图1所示。
USB具有以下特点:
1、              速度快。 USB1 .1支持全速和低速模式:12Mbps和1.5Mbps,USB2.0支持的高速模式可达480Mbps。
2、              扩展方便。 USB的星式的拓扑结构,在每个PC的USB端口最多扩展127个外设。
3、              支持完全的即插即用功能,可方便的热拔插。
4、              可自动检测外设并配置外设,灵活的供电方式,设备可自供电或总线供电;支持设备的挂起和唤醒,节省电源。
5、              USB有控制、等时、中断和批量等四种数据传输方式。可满足不同的外设使用。
 
 
图1 
 
 

 

3. WDM 驱动程序模型介绍
WDM Windows Driver Model ),即Windows驱动程序模型,是Microsoft力推的全新驱动程序模式,旨在通过提供一种灵活的方式来简化驱动程序的开发,在实现对新硬件支持的基础上减少并降低所必须开发的驱动程序的数量和复杂性。
WDM是一种 PNP驱动程序,同时还遵循电源管理协议,它直接对硬件抽象层HAL操作,还能在Windows98和Windows2000间实现源码级兼容。在 WDM驱动程序模型中,每个硬件设备至少有两个驱动程序。其一为功能(function)驱动程序,即硬件设备驱动程序。它了解使硬件工作的所有细节,负责初始化I/O操作,有责任处理I/O操作完成时所带来的中断事件,有责任为用户提供一种设备适合的控制方式。另一个为总线(bus)驱动程序。它负责管理硬件与计算机的连接。WDM模型使用了如图 2的层次结构。
 
图2 

 

WDM驱动程序总是使应用程序调用设备时,就像操作一个文件。通常,当一个应用程序需要从硬件端口读取数据时,是通过调用标准的 Windows API函数,如ReadFile来实现的。而Win32子系统(如KERNEL32.DLL)通过调用平台相关的系统服务接口实现该API,而平台相关的系统服务将调用内核模式支持例程。Windows 2000/xp的所有内核模式IO操作都使用一个公用的数据结构(IRP)。内核发出各种IRP请求给WDM驱动程序,驱动程序处理各种IRP请求.每个IRP有一个IO堆栈结构,对应相应的驱动程序。
4. USB 设备驱动程序的编写
USB设备驱动程序完全具有 WDM驱动程序的特点,也采用分层结构.USB设备驱动程序是使用标准Windows系统USB总线驱动程序访问使用USBDI(驱动程序接口)的USB设备的设备驱动程序。图3可以看到USB驱动的层次模型。
USB总线驱动程序负责实际与 USB总线通讯,加载和/卸载USB驱动程序;与USB设备通过端点建立通讯来执行设备配置,数据与USB协议框架和打包格式的双向转换任务。USB设备驱动程序(即功能驱动程序),通过发送含有USB请求包(URB)的IRP_MJ_INTERNAL_DEVICE_CONTROL IRP给USB总线驱动程序来实现与USB设备的通讯。

图3

 USB设备驱动程序可按照处理 IRP的不同分为:驱动程序初始化模块、即插即用(PnP)IRP处理模块、电源管理IRP处理模块、系统控制模块(WMI)IRP处理模块,USB设备IO和读写IRP模块等几部分。
4 .1驱动程序初始化模块
该模块提供一个驱动程序的入口例程 DriverEntry(),所有对各种IRP的处理例程都在此模块的DriverEntry例程中得到定义。此模块添加设备AddDevice例程,调用IocreatDevice()内核函数创建一个功能设备对象FDO,并进行WMI和电源管理的一些初始化工作。设备卸载例程UnLoad用于清理硬件在系统中留下的痕迹。DriverEntry例程部分源码如下:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{     PDEVICE_OBJECT deviceObject = NULL;
………
DriverObject->MajorFunction[IRP_MJ_PNP] = D12_PnP;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= D12_IoCtrL;
DriverObject->MajorFunction[IRP_MJ_WRITE] = D12_Write;
DriverObject->MajorFunction[IRP_MJ_POWER] = D12_PowerIrp;
DriverObject->DriverExtension->AddDevice = D12_AddDevice;
DriverObject->DriverUnload = D12_Unload;
………
return ntStatus;}
4 .2即插即用(PnP)模块
该模块实现设备的即插即用功能,热拔插和动态配置。当硬件检测到 USB设备插入时,Windows 2000查找相应的驱动程序,并调用它的DriverEntry例程,即插即用管理器调用驱动程序的AddDevice例程,通知它添加设备,驱动利用IocreatDevice()内核函数创建一个功能设备对象FDO,在此过程中驱动程序收到IRP_MN_START_DEVICE IRP,请求驱动程序启动USB设备和分配资源。当然,设备运行过程中,如果设备状态发生变化(如带电拔插,暂停等),系统的即插即用管理器也同样发出相应的IRP,由驱动程序进行处理。
该模块的启动设备例程中要对 USB设备进行初始化操作,它首先读取设备描述符,根据设备描述符来读取配置描述符.在读取配置描述符时,往往先读一次配置描述符,取出总的描述符长度,再将配置描述符,接口描述符,端点描述符一并读出,从中获取各种描述符提供的信息,设置管道信息,创建一个配置URB,进行设备配置。需要调用以下例程:
UsbBuildGetDescriptorRequest(Urb, // 组建一个获取设备描述符的URB请求
(USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
0,0,deviceDescriptor// 描述符的类型
,NULL,siz,NULL);
CallUSBD( DeviceObject,urb);// 发送usb给总线驱动,
interfaceDescriptor=USBD_ParseConfigurationDecriptorEx(// 从配置描述符中搜索接口信息
ConfigurationDecriptor,// 配置描述符地址
ConfigurationDesriptor,// 搜索起始地址
interfacedex,// 搜索的接口索引
0,-1,-1,-1)// 然后选择接口,配置设备
urb=USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,interfacelist)
// 创建一个配置设备的URB。这里使用一个链表结构,可配置不只一个接口
4 .3电源管理模块
实现 USB系统的电源管理功能,实现设备的挂起与唤醒。在USB电源管理IRP的处理必须尽可能的快,否则可能出现奇怪的响应时间长现象。在电源管理模块中将IRP向下传递的例程是PoCallDriver,用它的目的就是使一切和电源管理有关的IRP都在系统电源管理器的掌握之下。
4.4 系统控制模块(WMI)
WMI( Windows Management Instrumentation)是Windows提供给驱动的一种服务机制,它可以完成注册表的操作,并且可以在用户应用程序和驱动程序之间直接数据交换,从而使用户在除了使用IO设备控制之外,还有一个途径和驱动程序交流。它处理IRP_MJ_SYSTEM_CONTROL IRP请求。此IRP在AddDevice中进行一些初始化工作,确定WMI请求处理的例程,并调用IoWMIRegistrationControl进行WMI注册。
4.5 USB 设备IO模块
本模块实现完成 IO请求的大部分工作。工作过程:应用程序调用Win32函数如DeviceIoControl向设备发出IO控制命令,系统的IO 管理器构造一个IRP IRP_MJ_DEVICE_CONTROL.设备驱动收到IRP,根据其中的控制代码,构造相应的URB(USB请求块),并把它放到一个新的IRP,传递到USB类驱动,执行IRP。并把结果返回给设备驱动,设备驱动在通过IRP返回给IO管理器,IO管理器将结果返回给应用程序,即完成一次IO操作。读写例程也安排在此模块,响应读写设备用户请求。
USB有四种数据传输方式:控制,批量,中断和同步方式。这里需要先检查传输类型 ,然后根据传输类型的不同要求建立适当的URB请求,如下:
UsbBuildInterruptOrBulkTransferRequest(urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER,
PipeInformation->PipeHandle
NULL,mdl,StageLenth,urbFlags,NULL)// 建立传输请求URB
利用总线驱动提供的内部控制码 IOCTL_INTERNAL_USB_SUBMIT_URB,向下层驱动发送URB,并设置完成例程等待请求完成:
nextStack->MajorFuntion=IRP_MJ_INTERNAL_DEVICE_CONTROL;// 设置下一个IO堆栈的主
nextStack->parameters.Others.Argument1=(PVOID)urb;// 功能代码
nextStack->Parameters.DeviceIoControl.IoControlCode=IOCTL_INTERNAL_USB_SUBMIT_URB;// 内部控制USB设备提交的URB
IoSetCompletionRoution(Irp,
(PIO_COMPLETION_ROUTINE)BulkUsb_ReadWriteCompletion, // 设置的完成例程
rwContext,TRUE,TRUE,TRUE);
IoCallDriver(deviceExtention->NextStackDeviceObject,Irp);// 提交IRP
   该模块完成了几乎所有的应用程序与驱动程序的交互,这一部分也是与 USB设备联系最为紧密的部分。需要对USB协议有一定的了解。
5. 驱动程序的几种开发工具
开发一个 USB驱动程序需要有一个合适的开发环境。下面是比较流行的几种开发工具。
    Microsoft为开发驱动者提供了一个软件包 Driver Development Kit即DDK,其中包含了驱动程序的编译器和调试工具,以及一些帮助文档和范例,可以在Microsoft的网站上免费下载DDK。代码的编写采用c或C++语言,只是编译,连接需要使用VC++和DDK的工具。DDK提供了各类驱程序的源代码,对开发者编写自己的驱动程序很有参考价值。
DriverWorks是 Numega公司提供的一个商业化驱动程序集成开发包,提供VC++下的开发向导DriverWizard,按照它的提示可以迅速地生成驱动程序的框架。在其生成的代码框架中在加入自己的操作,就可以实现一个完整的USB设备驱动程序。
WinDriver也是一个商业化的驱动程序开发包。 WinDriver 使硬件访问变成一件很容易的事。在常规开发环境下,使用WinDriver,可以在很短的时间内完成访问IO端口和存储区域,处理中断,执行DMA操作及访问PCI和自定义寄存器的工作。这种易用性是通过一个非常强大的组合向导来实现的。
6. 结束语
USB设备驱动程序提供了应用设备与应用软件的接口,使应用程序能以文件调用的方式来高速,快捷地操作设备。通过设计 USB设备驱动程序,我们实现了自己开发的智能仪器基于USB的数据采集系统与PC的通信,取得较好的效果。USB设备驱动程序是一个USB应用系统设计当中的关键环节,要想对USB开发有一个全面深入的理解,必须深入理解USB驱动程序设计。而且随着USB技术的快速发展及其广泛应用,USB驱动程序的编写也将变得越来越重要。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值