開發(fā)WDM型的USB設(shè)備驅(qū)動程序

2010-08-28 10:45:06來源:西部e網(wǎng)作者:

    摘要: 文章介紹了USB和WDM驅(qū)動程序的基本概念和結(jié)構(gòu),結(jié)合實例闡述了用NuMega 公司的DriverStudio工具包開發(fā)Windows 2000環(huán)境下WDM USB設(shè)備驅(qū)動程序的方法,并給出關(guān)鍵例程主要代碼。

  關(guān)鍵詞:USB WDM 設(shè)備驅(qū)動程序 DriverStudio

  引言

  隨著微機技術(shù)水平的日益提高,傳統(tǒng)的計算接口已經(jīng)不能滿足當前計算機高速發(fā)展的需求,計算機業(yè)界迫切需要新的通用型、高速總線接口。通用外設(shè)接口標準USB應(yīng)運而生。USB,全稱為通用串行總線(Universal Serial Bus),它是Compaq、IBM等PC大廠商聯(lián)合開發(fā)的一種新型的、基于令牌的、高速的串行總線標準。開發(fā)者要設(shè)計USB設(shè)備接口,就必須首先了解USB協(xié)議,在此基礎(chǔ)上有針對性的開發(fā)USB設(shè)備驅(qū)動程序。

  USB簡介

  在眾多的PC機總線中,USB以其突出的優(yōu)點獨樹一幟:① 使用方便。支持熱拔插,不涉及中斷請求(IRQ)沖突等問題,能真正做到“即插即用”。②傳輸速率高。目前的USB 2.0協(xié)議速度高達480Mbps 。③易于擴展。通過使用Hub擴展可連接多達127個外設(shè)。④使用靈活。USB共有4種傳輸模式:控制(control)、同步(Synchronization)、中斷(interrupt)、批量(bulk),以適應(yīng)不同設(shè)備的需要。⑤獨立供電。正由于上述優(yōu)點,開發(fā)USB接口的設(shè)備已成為一種發(fā)展趨勢。

  一個完整的USB系統(tǒng)包括主機系統(tǒng)和USB設(shè)備。所有的傳輸事務(wù)都是由主機發(fā)起的。一個主機系統(tǒng)又可以分為以下幾個層次結(jié)構(gòu),如圖1所示:

\
圖1 USB 互連通信模型

    USB總線接口包括USB主控制器和根集線器,其中USB主控制器負責處理主機與設(shè)備之間電氣和協(xié)議層的互連,根集線器提供USB設(shè)備連接點。USB系統(tǒng)使用USB主控制器來管理主機和USB設(shè)備之間的數(shù)據(jù)傳輸,另外它也負責管理USB資源,如帶寬等。應(yīng)用軟件不能直接訪問USB設(shè)備硬件,而通過USB系統(tǒng)和USB總線接口與USB設(shè)備進行交互。

  USB設(shè)備包含一些向主機軟件提供一系列USB設(shè)備的特征和能力的信息的設(shè)備描述符,用來配置設(shè)備和定位USB設(shè)備驅(qū)動程序。這些信息確保了主機以正確的方式訪問設(shè)備。通常,一個設(shè)備有一個或多個配置(Configuration)來控制其行為。配置是接口(Interface)的集合,接口指出軟件應(yīng)該如何訪問硬件。接口又是端點(endpoint)的集合,每一個與USB交換數(shù)據(jù)的硬件就為端點,它是作為通信管道的一個終點。圖1顯示了一個多層次結(jié)構(gòu)的通信模型,它表明了端點和管道所扮演的角色。

  WDM驅(qū)動程序和USB驅(qū)動程序的分層結(jié)構(gòu)

  設(shè)備驅(qū)動程序?qū)嶋H上是指一系列控制硬件設(shè)備的函數(shù),是操作系統(tǒng)中控制和連接硬件的關(guān)鍵模塊。它提供連接到計算機的硬件設(shè)備的軟件接口。

  1、WDM 驅(qū)動程序介紹

  WDM(Win32 Driver Model)是Microsoft公司力推的一種符合Windows2k/XP下的內(nèi)核模式驅(qū)動程序的分層體系結(jié)構(gòu)的驅(qū)動程序模式。它源于 Windows NT的分層32位設(shè)備驅(qū)動程序模型,它支持更多的特性,如即插即用( PnP ,Plug and Play )、電源管理( PM ,Power Management )、Windows管理診斷( WMI ,Windows Management Instrumentation )和 NT 事件。它為Windows操作系統(tǒng)的設(shè)備驅(qū)動程序提供了統(tǒng)一的框架,在Windows平臺上,WDM將成為主流的驅(qū)動模式。

  WDM引入了功能設(shè)備對象FDO(Function Device Object)與物理設(shè)備對象PDO(Physical Device Object)兩個新類來描述硬件,一個PDO對應(yīng)一個真實的硬件。一個硬件只允許有一個PDO,卻可以擁有多個FDO,在驅(qū)動程序中直接操作的不是硬件而是相應(yīng)的PDO和FDO。

  WDM是通過一個128位的全局唯一標識符(GUID)實現(xiàn)驅(qū)動程序的識別。應(yīng)用程序與WDM驅(qū)動程序通信時,應(yīng)用程序?qū)⒚坑脩粽埱笮纬蒊/O請求包(IRP)發(fā)送到驅(qū)動程序。驅(qū)動程序識別出IRP請求后指揮硬件執(zhí)行相應(yīng)操作。

  2、開發(fā)WDM驅(qū)動程序的方法

  目前開發(fā)WDM驅(qū)動程序的方法有三種:

 、偈褂 Microsoft 的 Windows2000 DDK工具開發(fā)。②使用 KRFTech 公司的 WinDriver 。③使用 NuMega 公司的 DriverStudio 。

  3、WDM型的USB驅(qū)動程序結(jié)構(gòu)

  對于USB設(shè)備來說,其WDM驅(qū)動程序分為USB底層(總線)驅(qū)動程序和USB功能(設(shè)備)驅(qū)動程序。USB驅(qū)動程序符合Windows 2000下的內(nèi)核模式驅(qū)動程序的分層體系結(jié)構(gòu),如圖2所示:

\
圖2 WDM型的USB驅(qū)動程序體系結(jié)構(gòu)

    USB底層驅(qū)動程序由操作系統(tǒng)提供,負責與實際的硬件打交道,實現(xiàn)煩瑣的底層通信。USB功能驅(qū)動程序由設(shè)備開發(fā)者編寫,不對實際的硬件進行操作,而是通過向USB底層驅(qū)動程序發(fā)送包含URB(USB Request Block,請求塊)的IRP,來實現(xiàn)對USB設(shè)備信息的發(fā)送和接收。采用這種分層驅(qū)動程序的設(shè)計方法有兩個優(yōu)點:(1)多個USB設(shè)備可以通過USB底層驅(qū)動程序來協(xié)調(diào)它們的工作。(2)編寫分層驅(qū)動程序較之編寫單一驅(qū)動程序相對簡單,且可以節(jié)省內(nèi)存和資源,不易出錯。

  USB驅(qū)動程序工作簡述如下:當應(yīng)用程序想對USB設(shè)備進行I/O操作,它需調(diào)用Windows API函數(shù),I/O管理器將此請求構(gòu)造成一個合適的I/O請求包(IRP)并把它傳遞給USB功能驅(qū)動程序。USB功能驅(qū)動程序接收到這個IRP后,根據(jù)IPR中包含的具體操作代碼構(gòu)造相應(yīng)USB請求塊(URB),并把此URB放到一個新的IRP中,然后把它傳遞給USB底層驅(qū)動程序。USB底層驅(qū)動程序根據(jù)IRP中所含的URB執(zhí)行相應(yīng)的操作,并把操作的結(jié)果返回給USB功能驅(qū)動程序。USB功能驅(qū)動程序接收到此返回的IRP后,將操作結(jié)果通過IRP返還給I/O管理器,最后I/O管理器將此IRP操作結(jié)果傳回給應(yīng)用程序,至此應(yīng)用程序?qū)υO(shè)備的一次I/O操作完成。

    用Driver Studio工具包開發(fā)WDM型的USB設(shè)備驅(qū)動程序

  前文所提及的WDM驅(qū)動程序開發(fā)方法,筆者都曾嘗試過。個人認為用DriverStudio開發(fā)工具包來開發(fā)USB驅(qū)動程序行之有效。其中的Driver Wizard是創(chuàng)建WDM驅(qū)動程序框架的一個很好的工具,后文將介紹用它來創(chuàng)建USB設(shè)備驅(qū)動程序的基本框架。

  1、搭建開發(fā)平臺

  由于利用 DriverStudio 開發(fā)WDM驅(qū)動程序在搭建開發(fā)平臺的過程中對軟件的安裝順序要求頗高,在開發(fā)過程中我也曾因為安裝順序的顛倒而失敗。在實踐中總結(jié)了以下的安裝步驟,有必要在此作以介紹。

 、僭谝蜒b了Windows 2000 操作系統(tǒng)的機子上安裝 Microsoft Visual C++6.0。 ②安裝 Win2000 DDK 。③安裝 NuMega DriverStudio 2.0 ( or 2.6 ) 驅(qū)動程序開發(fā)工具包。它包含DriverWorks( 用于開發(fā)內(nèi)核模式WDM驅(qū)動程序 )、SoftICE( 用于調(diào)試WDM驅(qū)動程序 )等開發(fā)工具。④由于DriverWorks 所用的類庫是對 DDK 函數(shù)的封裝,必須在 VC中編譯,創(chuàng)建自己的庫文件。⑤設(shè)置 DDK 路徑。

  2、利用DriverStudio 的DriverWorks生成USB設(shè)備驅(qū)動程序框架

  驅(qū)動程序開發(fā)平臺搭建成功后,我們可利用驅(qū)動程序生成向?qū)river Wizard,根據(jù)硬件設(shè)置較為容易的生成USB設(shè)備驅(qū)動程序的大體框架。本人的設(shè)置如下:①選擇WDM的驅(qū)動程序類型和Windows 2000運行平臺。②選擇USB總線類型,系統(tǒng)選擇的USB芯片是Philip公司的ISP1581,填寫它的VID(供應(yīng)商ID)和PID(設(shè)備ID),這些信息由芯片的供應(yīng)商提供。③增加端點1和端點2,它們分別具有IN和OUT屬性。④根據(jù)需要選擇對設(shè)備的操作有:Read、Write、Device Control和CleanUp。⑤選擇給端點2產(chǎn)生BULK Read和Write的代碼, 向?qū)詣赢a(chǎn)生一套對端點2進行讀、寫的代碼。⑥設(shè)置驅(qū)動程序的屬性,采用WDM接口;在選取讀寫方式時應(yīng)遵循一條原則:需要快速傳送大量數(shù)據(jù)時,用 Direct I/O ,反之用 Buffer I/O ,這里選擇BufferI/O;由于無特殊的電源需求,故選用系統(tǒng)默認的Manage Power For This Device。⑧增加IOCTL接口,在其生成的代碼框架中加入自己的操作,以實現(xiàn)一個完整的USB設(shè)備驅(qū)動程序。最后就生成了一個WDM型的USB設(shè)備驅(qū)動程序框架和一個測試該驅(qū)動程序的測試程序大體框架。然后在其中添加需要的功能代碼。

  3、USB設(shè)備驅(qū)動程序中的關(guān)鍵例程代碼實現(xiàn)

  下面以我們的驅(qū)動程序為例,介紹USB驅(qū)動程序開發(fā)中的幾個關(guān)鍵例程的實現(xiàn)。本驅(qū)動程序的主要功能是控制USB設(shè)備上LED燈通斷并且對設(shè)備進行讀寫。

  1) 初始化例程 DriverEntry()

  設(shè)備驅(qū)動程序與應(yīng)用程序不同,它沒有main()或WinMain()函數(shù),而是有一個名為DriverEntry()的入口函數(shù),它通常完成一些初始化工作。當設(shè)備驅(qū)動程序被加載時,操作系統(tǒng)調(diào)用這個入口。在使用DriverWizard 創(chuàng)建的驅(qū)動程序基本框架中,DriverEntry()函數(shù)已經(jīng)寫好了,無需添寫代碼。在該例程中,驅(qū)動程序要向操作系統(tǒng)登記并注冊一些消息處理器,通過RegistryPath來找到位于注冊表中的驅(qū)動程序參數(shù),當驅(qū)動程序正確安裝后,在注冊表KEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Service 下可以找到MyUSB 項。而用DDK編寫該入口函數(shù)還需初始化Dispatch(分派)例程入口。

  2) 創(chuàng)建設(shè)備例程 AddDevice()

  大多數(shù)的PDO 都是在 PnP 管理器調(diào)用該程序入口點時被創(chuàng)建的。插入新設(shè)備后,系統(tǒng)啟動時,總線枚舉器會發(fā)現(xiàn)總線上的所有設(shè)備,會自動尋找并安裝設(shè)備的驅(qū)動程序,并由驅(qū)動程序中的處理 PnP 功能模塊自動處理 AddDevice() 例程及其他PnP消息。此例程使用IoCreateDevice() 函數(shù)創(chuàng)建設(shè)備對象,再使用 IoRegisterDeviceInterface() 函數(shù)將設(shè)備組成為一個特定的設(shè)備接口,然后使用IoAttachDeviceToDeviceStack() 函數(shù)關(guān)聯(lián)設(shè)備棧。

NTSTATUS MyUSBDevice::AddDevice( PDEVICE_OBJECT Pdo )
{
 // 產(chǎn)生一個DDK中KDevice類新的設(shè)備對象
 MyUSBDevice *pDevice = new ( static cast<PCWSTR>( KUnitizedName(L“MyUSBDevice”,m_Unit) ),// 設(shè)備名
  FILE_DEVICE_UNKNOWN, // 設(shè)備類型
  NULL, // 指針鏈接名
  0, // 設(shè)備特征標志位
  DO_BUFFERED_IO| DO_POWER_PAGABLE); // I/O傳輸方式
 MyUSBDevice(Pdo, m_Unit);
 if ( pDevice == NULL )
 {
  return STATUS_INSUFFICIENT_RESOURCES;
 }
 NTSTATUS status = devices -> ConstructorStatus();
 if ( !NT_SUCCESS(status) ) // 不成功,返回錯誤狀態(tài)并刪除指針
 {
  delete pDevice;
 }
 else // 如果成功,向系統(tǒng)報考設(shè)備的電源狀態(tài)變化為PowerDeviceD0
 {
  m_Unit++;
  pDevice -> ReportNewDevicePowerState( PowerDeviceD0 );
 }
 return status;
}

  3) LED控制處理例程 MyUSB_IOCTL_LED_Handler()

  該例程是實現(xiàn)本驅(qū)動程序功能的關(guān)鍵例程,它是用來控制設(shè)備上的LED燈通斷,主要利用USB Vendor Request來向設(shè)備傳送。其中,request=1的時候表示讓LED亮,request=0的時候讓LED滅。它是通過DeviceControl由上層應(yīng)用程序傳下來。實現(xiàn)代碼如下:

NTSTATUS MyUSBDevice::MyUSB_IOCTL_LED_Handler(KIrp I)
{
 NTSTATUS status = STATUS_INVALID_PARAMETER;
 //檢查輸入?yún)?shù)是否正確,如果不正確,返回STATUS_INVALID_PARAMETER
 if(I.IoctlOutputBufferSize() || !I.IoctlBuffer() ||(I.IoctlInputBufferSize() != sizeof(UCHAR)))
  return status;
 //處理MyUSB_IOCTL_LED_ON請求
 PURB pUrb = m_Lower.BuildVendorRequest(NULL, // 傳輸緩沖區(qū)
  0, // 傳輸緩沖區(qū)大小
  0, // 請求保留位
  (UCHAR)(*(PUCHAR)I.IoctlBuffer()), // 請求1=LED_ON ,0=LED_OFF
  0 ); // 值
 //向下傳送URB
 status = m_Lower.SubmitUrb(pUrb, NULL, NULL, 5000L);
 //若請求在此處理,設(shè)置I.Information指示多少數(shù)據(jù)拷貝回用戶
 I.Information()=0;
 I.Status()=status;
 return status;
}

  4) 訪問硬件例程 DeviceControl()

  上層應(yīng)用軟件程序就是通過此例程來將IRP傳到下層。

NTSTATUS MyUSBDevice::DeviceControl(KIrp I)
{
 NTSTATUS status;
 switch (I.IoctlCode())
 {
  case MyUSB_IOCTL_LED:
   status = MyUSB_IOCTL_LED_Handler(I);
   break;
  default: // 未被聲明的I/O 控制請求
   status = STATUS_INVALID_PARAMETER;
   break;
 }
}

  限于篇幅,這里僅介紹本驅(qū)動程序中的部分例程實現(xiàn)代碼。編寫完驅(qū)動程序后,首先在Visual C++ 中編譯通過,然后連接硬件,用DriverStudio 工具包中的SoftICE調(diào)試器調(diào)試該驅(qū)動程序,并且修改編譯DriverStudio產(chǎn)生的該驅(qū)動程序的測試程序,就通過命令行來測試我們的驅(qū)動程序。最后對于LED的控制,我們可以直觀的在設(shè)備上看到。

  結(jié)束語

  USB技術(shù)的不斷發(fā)展和完善,已經(jīng)使其逐漸成為先進總線接口技術(shù)的標志和方向,如今USB OTG標準已經(jīng)發(fā)布,那么USB的應(yīng)用領(lǐng)域也將越發(fā)的廣泛。開發(fā)一些特定功能的USB接口并設(shè)計其設(shè)備驅(qū)動程序也將成為應(yīng)用USB技術(shù)的關(guān)鍵。通過對USB的學習和Windows 2000下的WDM驅(qū)動程序的研究,本文已經(jīng)給出了編寫WDM型USB設(shè)備驅(qū)動程序的一般方法,讀者可以在實際應(yīng)用中逐步提高對USB和驅(qū)動程序的認識,取得事半功倍的效果。