Windows下usb接口驱动技术

来源:互联网 发布:知乎桌面版 编辑:程序博客网 时间:2024/04/30 09:19

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

 

WMD驱动程序模型

 

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

 

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

usb

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

其中总线驱动程序(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 DDKWindows 2000 DDK两个版本。Windows 98 DDK能够开发Windows 95/98/Me/NT下的VxDKMDWDM驱动程序。Windows 2000 DDK 能够开发Windows 98/Me/NT/2000下的KMDWDM驱动程序。由于DDK基于汇编语言的编程方式和内核模式的调用,对没有深厚的OS原理和编程水平的人员来说,任务相当艰巨。

 

2.   NuMega公司提供的DriverStudio

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

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

 

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

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

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

 

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

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

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

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

(4)在驱动程序支持的功能项中选择ReadWriteDevice ControlCleanup;

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

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

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

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

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

 

2USB设备驱动程序的编程

在使用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个字段,定义了传输请求及相关信息。

 

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

 

              bRequest1字节,用来指定请求。

 

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

 

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

 

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

 

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

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

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

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

 

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

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

 

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

 

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

 

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

 

int DMARead(unsigned char usbSelectunsigned char *rbufferint lenint waitTime),主要功能是计算机批量读取ISP1581中的数据,而ISP1581DMA方式从外部RAM读取数据。

 

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

原创粉丝点击