USB是由Intel,Compaq,Digital,IBM,Microsoft.NEC,Northern Telecom等七家世界著名的计算机和通信公司共同推出的新一代接口标准:由于USB具有传输速率高,扩展方便,可以热插拔,支持PNP等优点,迅速得到了众多PC厂商和半导体厂商的大力支持.外设向USB过渡成为必然的趋势。
在开发数控测并系统中,笔者采用了USB进行数据的采集和传输,而目前的开发工具中,没有对USB进行操作控制的函数和控件,必须自行开发USB设备驱动程序。LSB设备驱动程序一般采用WDM方式。
1 USB简介
USB是为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准.现在台式PC和使携式PC中几乎都配备了USB接口.而且流行的操作系统都支持USB功能。
1.1 USB的系统构成
USB系统的基本硬件和基本软件如表1所示。
1.2 USB的基本特点
- 速度快。USBl.1支持高速和低速两种方式:12Mbps和1.5Mbps,分别满足不同设备的需要。最新推出的USB2.0速度可以达到480Mbps。
- 扩展方便。在USB设备上通常应该有USB下行端口,也有专用的集线器。这种扩展方式使USB能够驳接多个USB外设。通常用这种方式每个PC的USB端口最多可以扩展127个外设。USB系统一般采用星型拓扑结构.如图1所示:
图l USB拓扑结构
- 自动检测和配置外围设备
- 支持即插即用方式
- 支持热插拔
- 供电方式灵活。USB设备有两种供电方式:总线供电和自供电,并且支持设备的挂起和唤醒。
- 四种传输类型:中断传输(Interrupt)、控制传输(Control)、块传输(Bulk)和同步传输(Synchnoization),满足不同设备的需要。
1.3 USB系统通佰模型
USB系统中的通信分层模型如图2所示。
图2 USB通信分层模型
2 WDM设备驱动程序简介
2.1 WDM设备驱动程序的特点及构成
WDM(Win32 Driver Model)的驱动程序构架Micmsoft早在1997年就提出了该项技术并在Windows 98中得到了应用,即Wind帅98也支持WDM。这样WDM就成为了一个跨平台的驱动程序模型。不仅如此,WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非InteI平台上运行。可以不夸张地讲,WDM算得上是21世纪的驱动程序构架。
WDM是在NT 4.0驱动程序结构上发展起来的,所以它与NT 4.0的驱动程序极为相似,但是它却有了本质上的提高,比如它支持USB,IEEEl394,ACPI等全新的硬件标准。
在WDM驱动程序中,即插即用(PNP)管理器告知何时向系统添加了一个设备,或者从系统删除了设备。PNP管理器使用安装INF文件查找新设备的正确驱动程序,而NT式驱动程序通常在它的初始化例程中发现设备。NT式驱动程序通常使用专门的安装程序安装,WDM设备驱动程序支持总线驱动程序和类驱动程序,而且还支持电源管理和WMI特性。
与NT 4.0驱动程序一样,WDM驱动程序也是分层的。Windows驱动程序模型(WDM)为了适应即插即用系统,重新定义了驱动程序分层,它至少有总线驱动程序和功能驱动程序。过滤驱动程序,根据具体的需要可以选择:WDM还引入了功能设备对象FD0(Functional Device Object)与物理设备对象FDO(Functional Device 0bject)两个新概念来描述硬件。一个PDO代表一个真实硬件、在驱动程序看来则是一个则是一个硬件只允许有一个FDO,但却可以拥有多个FDO,而在驱动程序中我们不是直接操作硬件而是操作相应的PD0与FD0。在WDM中、驱动程序和设备对象的分层情况如图3所示。其中总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,负责枚举它的总线,即发现总线上的全部设备和检测设备被添加或者删除。总线驱动程序创建物理设备对象(FD0)代表发现的设备。功能驱动程序(Function Driver)控制设备的主要功能,分层在总线驱动的上面,负责创建功能设备对象(FDO)。在USB情况下,功能驱动程序必须使用USB类驱动程序访问设备。过滤驱动程序(Filter Driver)既可以位于总线驱动程序之上,也可以位于功能驱动程序之上,它一般用于改变IRP的操作。
图3 WDM中驱动程序和设备对象的分层情况
2.2 WDM设备驱动程序的设计
WDM驱动程序是PE格式的,但是它却没有WinMain或Main小这样的入口,取而代之的是DriverEntry。在DriverEntry中向操作系统登记并注册一些消息处理器,而且还要指明是否对驱动程序输入输出的数据进行缓冲;另外还要提供一个AddDevice例程来把驱动程序添加到驱动程序堆栈中,并且为各种请求,如IRP_MJCREATE,IRP_MF_WRITE,IRP_MJ_CLOSE,IRP_MJ_READ,IRP_MJ_DEVICE_CONTROL,IRP_MJ_PNF等指定各自的处理例程。
- DriverEntry(IN PDRIVER_OBJECT DriverObject,...)
- //驱动程序入口
- {
- ...
- DriverObject->DriverExtension->AddDevice = XXAddDevice;
- //XX对应自己给驱动程序的命名
- DriverObject->DriverUnload = XXUnload;
- DriverObject->MajorFunction[IRP_MJ_CREATE] = XXDriverCreateClose;
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = XXDriverCreateClose;
- DriverObject->MajorFunction[IRP_MJ_READ] = XXDriverReadWrite;
- DriverObject->MajorFunciton[IRP_MJ_WRITE] = XXDriverReadWrite;
- ...
- }
在设计的过程中一定要注意函数的可运行级别,比如有的函数只能在PASSIVE_LEVEL下运行,有的函数则可以在DISPATCH_LEVEL以下级别运行,级别越高的时候,对代码的要求就越严格,比如在DISPATCH_LEVEL的时候就不能使用分页内存。通常情况下应该尽可能让代码在低运行级别如PASSIVE_LEVEL下运行,在高级别下运行过长时间将导致系统效率降低,影响系统响应的实时性。
3 USB软件系统的组成
USB软件系统一般由四部分组成,分别为:应用程序、USB设备驱动程序(USB客户驱动程序)、USD驱动程序(USBD)、USB主控制器驱动程序(UHCD)。USB软件系统的构成层次如图4所示。其中USB客户驱动程序控制一个给定的USD功能设备。连接到USB设备的每一种类型的功能单元都必须有客户驱动程序。客户驱动程序把USD设备看作是一个可以被访问端点的集合,USB设备可以被控制并与它的功能单元通信。客户驱动程序一般是编写USD软件的重点。USD驱动程序(USBD)知道设备的需求(通过设备描述符获知),也知道USB的能力;USBD一般由Windows操作系统自带。USBD把IRP划分成USB和设备需要大小的块。USBD确保每一个设备能分配到它所要求的资源,支持USN设备配置。在配置的过程中,它为检测到的端点建立通信管道。USBD提供了一个编程接口,即USBDI(USB驱动程序接口),客户驱动程序就是通过USBDI来传输请求。USB主控制器驱动程序提供了对USB的低级支持,通过把IRP转换成为单独的事务处理后在USD上执行。目前定义了USB主控制器的两种实现方式:开放主控制器驱动程序(0penHCl)和通用主控制器(UHCD)。OpenHCI和UHCD分别是由compaq和Intel定义的一个和硬件有关的底层驱动程序标准,可以根据需要进行选择。
图4 USB软件层次
4 USB软件的开发
USB软件系统中应用程序的开发,一船书籍和文章都有比较详细的介绍,本文主要介绍USB设备驱动程序的开发。相对于连接到传统PCI总线上的设备驱动程序.USD设备驱动程序从来不直接操作硬件,而是生成一种数据结构对象,即USB请求块(URB),发送到下层驱动程序。USB设备通过USBDI向下层驱动程序发送URB。USBDI是微软Windows操作系统USB驱动程序分层体系的一部分,在体系中的位置如图5所示:USBDI是基于IRP的接口.它把单独的请求封装成WDM I/O请求包(IRP),并发送到下层驱动程序的设备对象。
图5 USB Windows驱动程序模型的一部分
4.1 初始化URB
首先为URB结构分配一块内存,并启动一个初始化例程填充将要发送的请求块的相关区域。例如响应IRP_MN_START_DEVICE请求来配置设备.需要先读取设备描述符。首先声明一个局部变量(URB)来保存URB数据结构。URB是一系列子结构的联合.在此使用子结构UrbControlDescriptorRequest,它是struct URB_CONTROL_DESCRIPTOR_REQUEST的对象。然后使用服务例程UsbBuildGetDescriptorRequest(实际上是宏)初始化获取描述符请求子结构的相关区域。
- USB_DEVICE_DESCRIPTOR dd;
- URB urb;
- UsbBuildGetDescriptorRequest(&urb,sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST)),USB_DEVICE_DESCRIPTOR_TYPE,0,0,&dd,NULL,sizeof(dd),NULL);
4.2 发送URB
首先创建一个内部I/0控制请求(I0CTL),一般使用例程IoBuildDevicetoControlRequest。例程的第一个参数指明控制请求的I/O控制代码,第二个参数指明接受请求的设备对象。然后在pARAMETERS.0THERS的Argument上指定URB的地址。最后调用IoCallDriver发送请求到下层驱动。
4.3 配置设备
总线驱动程序自动检测新USB设备的添加、读取设备描述符,以决定何种设备添加到系统中。然后决定加载何种驱动程序,配置管理器调用AddDevice函数生成设备对象,连接设备对象到驱动栈中。配置管理器发送IRP-MN-START-DEVICE即插即用请求到驱动程序。然后调用StartDevice函数开始大部分配置工作。在配置过程中,首先读取配置描述符,选择设备的配置和配置的接口,然后发送选择配置URB到总线驱动程序;总线驱动程序开启设备的配置和接口,并创建管道来允许和所选接口的端点通信;而且提供操作管道的句柄.一服从完成的URD中取出句柄并保存,以备以后使用。
4.4 管理传输管道
传输方式的不同.传输管道的管理也不同。以中断传输为例,中断传输的特点是主机以固定的频率查询中断端点,主要例程有:创建中断URB例程,该例程创建中断URB和相关的IRP,并用设备扩展的PollingUrb和PollingIrp指向相应的结构;开始中断URB例程,该例程发送URB轮流查询中断端点:中断服务例程,根据具体设备和功能进行操作,删除中断URB例程;舍弃管道例程:重置管道功能等。
5 USB软件系统的开发工具
USB应用软件的开发工具很多,如VC,VB,C++ Builder等,在此不再赘述。USB设备驱动程序的开发工具有Windows的DDK,KRFTech公司的Windriver,Nnmega公司的DriverWorks等。其中DDK功能强大,但是要求开发人员对操作系统比较熟悉,开发的难度比较大;Windriver属于傻瓜型开发工具,使用非常方便,开发周期短,但是不能满足性能较高的USB设备。Windriver分为用户型和内核型两种方式.内核型可以满足性能较高的设备,但是难度加大lD;DriverWorks使用比较方便,功能强大,是比较理想的开发工具。