八、 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 驅動程序模型
應用程序通過 API 函數調用 Win32 系統子函數,驅動程序分為設備驅動程序,總線驅動程序 (USBD) 和主控制器驅動程序 (HCD) 三層,它們均運行在系統的內核模式。設備驅動程序使用 IR P(I / ORequest Packet) 通過總線驅動程序提供的軟件接口 (USBDI , USB Driver Interface) 向總線驅動程序發出 I / O 請求,并根據數據傳輸方向提供一個或空或滿的 內存 緩沖區; USBD 負責管理數據的總線傳輸,也有設備驅動程序與其他軟件接口的功能單元進行通信,沒有直接調用 USBD ,但總有一個更低層的驅動軟件發生 USBD 調用。主控制器驅動程序處在 USB 系統軟件的最底層,直接與主控制器的硬件通信,它提供了只有總線驅動程序才能訪問的主控制器驅動程序軟件接口 H CDI (Host C ON TROL Driver Interface) 。其中,總線驅動程序和主控制器驅動程序是系統的底層驅動程序。設備驅動程序是針對某一 USB 設備的專用驅動程序。
Windows 為 USB 設備提供了底層驅動程序,與底層驅動程序接口的是 I / O 請求包 (IRP) , Windows 為應用程序提供的接口則是 API 函數。因此必須在它們之間建立一個驅動程序,在底層驅動與 Win32 應用程序之間傳遞消息,即設備驅動程序。 VC++ 、 VB 等軟件開發的應用程序,在設備驅動程序的支持下,都可以調用 ReadFile() 、 WriteFile() 、 DeviceIo CONTROL () 等 API 函數向設備傳遞主機請求。 Windows 系統自動將 API 調用轉化為 IRP ,設備驅動程序把它向下層驅動傳遞。直到完成其所指定的功能再沿驅動程序棧返回主機。
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
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
