成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

開發WDM型的USB設備驅動程序

2010-08-28 10:45:06來源:西部e網作者:

    摘要: 文章介紹了USB和WDM驅動程序的基本概念和結構,結合實例闡述了用NuMega 公司的DriverStudio工具包開發Windows 2000環境下WDM USB設備驅動程序的方法,并給出關鍵例程主要代碼。

  關鍵詞:USB WDM 設備驅動程序 DriverStudio

  引言

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

  USB簡介

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

  一個完整的USB系統包括主機系統和USB設備。所有的傳輸事務都是由主機發起的。一個主機系統又可以分為以下幾個層次結構,如圖1所示:

\
圖1 USB 互連通信模型

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

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

  WDM驅動程序和USB驅動程序的分層結構

  設備驅動程序實際上是指一系列控制硬件設備的函數,是操作系統中控制和連接硬件的關鍵模塊。它提供連接到計算機的硬件設備的軟件接口。

  1、WDM 驅動程序介紹

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

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

  WDM是通過一個128位的全局唯一標識符(GUID)實現驅動程序的識別。應用程序與WDM驅動程序通信時,應用程序將每用戶請求形成I/O請求包(IRP)發送到驅動程序。驅動程序識別出IRP請求后指揮硬件執行相應操作。

  2、開發WDM驅動程序的方法

  目前開發WDM驅動程序的方法有三種:

  ①使用 Microsoft 的 Windows2000 DDK工具開發。②使用 KRFTech 公司的 WinDriver 。③使用 NuMega 公司的 DriverStudio 。

  3、WDM型的USB驅動程序結構

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

\
圖2 WDM型的USB驅動程序體系結構

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

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

    用Driver Studio工具包開發WDM型的USB設備驅動程序

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

  1、搭建開發平臺

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

  ①在已裝了Windows 2000 操作系統的機子上安裝 Microsoft Visual C++6.0。 ②安裝 Win2000 DDK 。③安裝 NuMega DriverStudio 2.0 ( or 2.6 ) 驅動程序開發工具包。它包含DriverWorks( 用于開發內核模式WDM驅動程序 )、SoftICE( 用于調試WDM驅動程序 )等開發工具。④由于DriverWorks 所用的類庫是對 DDK 函數的封裝,必須在 VC中編譯,創建自己的庫文件。⑤設置 DDK 路徑。

  2、利用DriverStudio 的DriverWorks生成USB設備驅動程序框架

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

  3、USB設備驅動程序中的關鍵例程代碼實現

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

  1) 初始化例程 DriverEntry()

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

  2) 創建設備例程 AddDevice()

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

NTSTATUS MyUSBDevice::AddDevice( PDEVICE_OBJECT Pdo )
{
 // 產生一個DDK中KDevice類新的設備對象
 MyUSBDevice *pDevice = new ( static cast<PCWSTR>( KUnitizedName(L“MyUSBDevice”,m_Unit) ),// 設備名
  FILE_DEVICE_UNKNOWN, // 設備類型
  NULL, // 指針鏈接名
  0, // 設備特征標志位
  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) ) // 不成功,返回錯誤狀態并刪除指針
 {
  delete pDevice;
 }
 else // 如果成功,向系統報考設備的電源狀態變化為PowerDeviceD0
 {
  m_Unit++;
  pDevice -> ReportNewDevicePowerState( PowerDeviceD0 );
 }
 return status;
}

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

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

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

  4) 訪問硬件例程 DeviceControl()

  上層應用軟件程序就是通過此例程來將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;
 }
}

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

  結束語

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



主站蜘蛛池模板: 和林格尔县| 富平县| 陇川县| 乌兰县| 涿鹿县| 黔西县| 曲周县| 富川| 美姑县| 衢州市| 公安县| 韶关市| 龙井市| 松原市| 文昌市| 阿拉善左旗| 晋江市| 宁武县| 肃北| 南汇区| 玉树县| 新巴尔虎左旗| 宁津县| 攀枝花市| 册亨县| 唐河县| 来凤县| 封开县| 渝北区| 江永县| 樟树市| 松原市| 开远市| 阳新县| 靖宇县| 新闻| 庄河市| 含山县| 清苑县| 铁力市| 永顺县|