Windows下usb接口驱动技术(二)

八、        Windows驱动程序模型

Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver,虚拟设备驱动程序),起源于Windows 3.1 时代,用于Windows 95/98/Me操作系统中;一类是KMD( Kernel Mode Driver,内核模式驱动程序),用于Windows NT下;还有一类就是WDM(Win32 Driver Mode,Win32驱动程序模型),是微软从Windows 98开始,推出的一个新的驱动类型,它是一个跨平台的驱动程序模型,不仅如此WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非Intel平台上运行,毫不夸张地讲,WDM算得上是21世纪的驱动程序框架。

 

WMD驱动程序模型

 

Windows下usb接口驱动技术(二)_第1张图片

应用程序通过API函数调用Win32系统子函数,驱动程序分为设备驱动程序,总线驱动程序(USBD)和主控制器驱动程序(HCD)三层,它们均运行在系统的内核模式。设备驱动程序使用IRP(I/ORequest Packet)通过总线驱动程序提供的软件接口(USBDI,USB Driver Interface)向总线驱动程序发出I/O请求,并根据数据传输方向提供一个或空或满的内存缓冲区;USBD负责管理数据的总线传输,也有设备驱动程序与其他软件接口的功能单元进行通信,没有直接调用USBD,但总有一个更低层的驱动软件发生USBD调用。主控制器驱动程序处在USB系统软件的最底层,直接与主控制器的硬件通信,它提供了只有总线驱动程序才能访问的主控制器驱动程序软件接口HCDI(Host CONTROL Driver Interface)。其中,总线驱动程序和主控制器驱动程序是系统的底层驱动程序。设备驱动程序是针对某一USB设备的专用驱动程序。

 

Windows为USB设备提供了底层驱动程序,与底层驱动程序接口的是I/O请求包(IRP),Windows为应用程序提供的接口则是API函数。因此必须在它们之间建立一个驱动程序,在底层驱动与Win32应用程序之间传递消息,即设备驱动程序。VC++、VB等软件开发的应用程序,在设备驱动程序的支持下,都可以调用ReadFile()、WriteFile()、DeviceIoCONTROL()等API函数向设备传递主机请求。Windows系统自动将API调用转化为IRP,设备驱动程序把它向下层驱动传递。直到完成其所指定的功能再沿驱动程序栈返回主机。

Windows下usb接口驱动技术(二)_第2张图片

WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件,一个PDO对应一个真实硬件。一个硬件只允许有一个PDO,但却可以拥有多个FDO,而在驱动程序中我们不是直接操作硬件而是操作相应的PDO与FDO。驱动程序和设备对象的分层情况如图所示。

其中总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,创建PDO代表发现的设备。功能驱动程序(Function Driver)控制设备的主要功能,分层在总线驱动的上面,负责创建FDO。在USB情况下,功能驱动程序必须使用USB类驱动程序访问设备。

 

九、        USB设备驱动程序开发工具

开发USB设备驱动程序需要专门的开发工具,目前应用广泛的工具主要有两大类。开发设备驱动程序一般采用以下几种方法:1)直接使用Windows DDK,这种方法开发难度较大,设计者必须对整个体系结构有很好的理解和把握。2)使用Driver Studio,该工具软件可为设计者提供驱动程序的整体框架,设计者只需要专心于功能代码设计。3)使用win Driver,这种方法开发驱动程序很容易,但工作效率不是很高。

 

1.    Microsoft公司提供的Windows DDK(Device Driver Kit)。

它有Windows 98 DDK和Windows 2000 DDK两个版本。Windows 98 DDK能够开发Windows 95/98/Me/NT下的VxD、KMD和WDM驱动程序。Windows 2000 DDK 能够开发Windows 98/Me/NT/2000下的KMD和WDM驱动程序。由于DDK基于汇编语言的编程方式和内核模式的调用,对没有深厚的OS原理和编程水平的人员来说,任务相当艰巨。

 

2.    NuMega公司提供的DriverStudio。

它是一个大的开发工具包,包含VtoolsD、SoftICE和DriverWorks等开发工具。 VtoolsD开发包提供了对VxD编程的C/C++类库支持,利用VtoolsD中的QuickVxD工具可以快速生成VxD的C/C++代码框架,开发者可以在此基础上根据各自的需要添加自己的代码。DriverWorks用于开发KMD和WDM驱动程序,并且对DDK函数进行了类的封装,从而为开发Windows NT、Windows 2000和Widnwos98 WDM设备驱动程序提供了一个自动化的方法。

DriverWorks,提供了VC++下的开发向导Driver Wizard,按照它的提示可以迅速地生成驱动程序的框架。这个框架结构提供可以正确执行WDM动态环境中IRP的请求,而且,也包含用于简化系统提供的标准类驱动程序(如HID、流)和总线驱动程序(如PCI和USB)接口的类等。总之,利用DriverWorks开发WDM驱动程序,可以大大简化开发人员的工作量、缩短开发周期以及降低开发驱动程序的难度。

 

十、        USB设备驱动程序的设计

使用DriverStudio3.2开发USB设备驱动程序。

该驱动程序的主要功能包括:从控制端点0读取规定个数的数据、向端点0发出控制命令、从端点2批量读数据、向端点2批量写数据,驱动程序的开发采用DriverStudio3.2驱动程序开发包及VC++6.0,使用开发包中的向导程序DriverWizard就可以方便的生成驱动程序框架、模块及部分程序源代码,开发者只需要在功能模块中加入自己的实现程序就能完成复杂的USB设备驱动程序设计。

 

1.   DriverWizard生成一ISP1581驱动程序的过程:

(1)启动DriverWizard,选择DriverWorks Project创造一个名为USBDIO的 VC++项目;

(2)在驱动程序类型中选择WDM Driver,WDM Function Driver,在硬件设备所支持的总线类型中选择USB(WDM Only),在USB Vendor ID(厂商识别码)中填写0741,在USB Product ID(产品识别码)中填写0821;

(3)增加USB设备端点,设置端点2为批量输入/输出传输方式;

(4)在驱动程序支持的功能项中选择Read、Write、Device Control、Cleanup;

(5)选择自动产生批量读及批量写程序代码;

(6)在I/O请求IRP处理方式中选择None,即IRP不排队;

(7)在接口的打开方式中选择Symbolic link:UsbdioDevice,即应用程序以符号链接名打开设备;

(8)定义应用程序调用DeviceIo Control 函数对WDM驱动程序通信的控制命令。

(9)最后选择完成并确认生成新的项目信息,向导程序就会在usbdio目录中生成一个名为USBDIO的项目文件,其中包括了ISP1581驱动程序框架、模块及部分源代码。

 

2. USB设备驱动程序的编程

在使用DriverWizard生成驱动程序框架、模块及部分程序源代码后,开发者只需完成三个控制代码所对应的三个功能模块的编程:模块USBDIO_IOCTL_ ID_CODE_Handler的功能是从控制端点0读取数据,模块USBDIO_IOCTL_ TEST_COMMAND_Handler的功能是向控制端点0发送一个控制命令,模块USBDIO_IOCTL_DMA_COMMAND _Handler的功能是向控制端点0发送一个要求USB设备进行DMA传输的控制命令,下面是第一个模块的编程实例。

 

        NTSTATUS USBDIODevice::USBDIO_IOCTL_ID_CODE_Handler(KIrp I)

        {

               NTSTATUS status =STATUS_SUCCESS;

 

t << "Entering USBDIODevice::USBDIO _IOCTL_ID_ CODE_Handler, " << I << EOL;

 

               PURB pUrb;

 

               ULONG numData;

 

               numData=*(PUCHAR)I.IoctlBuffer();

 

               //设置读取的数据个数

 

pUrb=m_Lower.BuildVendorRequest((PUCHAR)I.IoctlBuffer(),//驱动程序存放读取的数据的内存区

numData,//wLength,读取的数据个数

0,0x0c,//bRequest 0,//wValue

               TRUE,//input

               TRUE,

               NULL,

               0x0472,//wIndex,传输到固件程序的读数命令码

 

               URB_FUNCTION_VENDOR_ENDPOINT,

 

               NULL);

 

               if(pUrb==NULL)

 

               {

                      I.Information() =0;

 

                      status=STATUS_INSUFFICIENT_

 

                      RESOURCES;

 

               }

 

               else

 

               {

                      I.Information() =numData;

 

                      tatus=m_Lower.SubmitUrb(pUrb,NULL,NULL,0);

delete pUrb;

               }

 

                      return status;

               }

 

对象I包含了应用程序下传的IRP内容,包括命令或数据等参数,函数BuildVendorRequest用来分配并初始化一个用于厂商请求的URB(USB Request Block),该URB将作为下传IRP的一个参数,通过函数SubmitUrb发送给总线驱动程序,以便完成与硬件的通信。

 

在初始化URB时需要了解USB的传输方式及传输协议,该功能使用了USB的控制传输方式,该方式包括三个阶段:设置阶段、数据阶段和状态阶段,其中数据阶段可选,开发者主要关注设置阶段中的8个关键字节的定义,8字节分成了5个字段,定义了传输请求及相关信息。

 

BmRequestType:1字节,用来指定数据流动的方向,请求的类型,以及接收者。

 

               bRequest:1字节,用来指定请求。

 

wValue:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。

 

wIndex:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。

 

               wLength:2字节,包含数据阶段中接下来要传输的数据字节数目。

 

十一、USB设备驱动程序的安装及调用

1.      USB设备驱动程序的安装

驱动程序编译完成后会生成一个名为USBDIO.SYS的文件,即USB设备驱动程序,另外在使用向导程序WizardDriver生成驱动程序时会产生一个名为USBDIO.INF的驱动程序安装程序,对此程序只需稍做修改就能正常使用,具体是将类改为USB,即Class=USB,由于本驱动程序使用符号链接名打开设备,所以删除ClassGUID选项,注意设备标识符必需为:%DeviceDesc%=USBDIO_DDI, USBVID_0471&PID_0821,其中0471是USB控制芯片的厂商识别码,0821是USB设备标识码。

驱动程序安装过程是:将USB设备加电,连入计算机的USB接口,这时候会看到Windows操作系统提示发现新硬件,提问是否安装驱动程序,选择是,然后选择驱动程序所在文件夹,选择文件USBDIO.INF即可完成安装.

 

2.      USB设备驱动程序的调用

为了完成对驱动程序的调用,使用VC++6.0编写USB应用程序包,程序包共由五个功能模块组成,用户通过调用这些模块即可方便的完成对USB外设的控制及读写,这些模块如下。

 

int CTRLReadData(unsigned char usbSelect,unsigned char *rbuffer,unsigned char numData),主要功能是读取ISP1581控制端点0发来的数据,数据存放在缓冲区rbuffer中。

 

int CTRLSendTestCommand (unsigned char usbSelect,unsigned short int testCommand),主要功能是发送测试命令,变量testCommand定义了测试命令。

 

int CTRLSendDMACommand (unsigned char usbSelect,unsigned char dmaDirection,unsigned char ramSelect,unsigned long dmaLength),主要功能是发送DMA传输命令,变量dmaDirection定义数据传输方向,ramSelect定义将要操作的USB外设的存储器,dmaLength定义了数据传输总数。

 

int DMARead(unsigned char usbSelect,unsigned char *rbuffer,int len,int waitTime),主要功能是计算机批量读取ISP1581中的数据,而ISP1581以DMA方式从外部RAM读取数据。

 

int DMAWrite(unsigned char usbSelect,unsigned char *rbuffer,int len, int waitTime),主要功能是计算机批量写数据到ISP1581,而ISP1581将以DMA方式写数据到外部RAM

转自:http://blog.csdn.net/sshhbb/article/details/6122371

你可能感兴趣的:(usb)