天天看點

Windows下usb接口驅動技術(二)十一、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接口驅動技術(二)十一、USB裝置驅動程式的安裝及調用

應用程式通過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接口驅動技術(二)十一、USB裝置驅動程式的安裝及調用

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