天天看點

Windows下usb接口驅動技術

一、USB概述

        USB的英文全稱為Universal Serial Bus,中文含義是通用串行總線,是由Conpaq、DEC、IBM、Inter、Microsoft、NEC和Northen Telecom等公司為簡化PC與外設之間的互連而共同研究開發的一種免費的标準化連接配接器,它支援各種PC與外設之間的連接配接,還可實作數字多媒體內建。現在生産的PC幾乎都配備了USB接口,Microsoft 的Windows98、NT以及MacOS、Linux、FreeBSD等流行作業系統都增加了對 USB的支援。它是一種快速的,雙向的,同步傳輸的廉價的并可以進行熱拔插的串行接口。USB接口使用友善,它可以連接配接多個不同的裝置,而過去的序列槽和并口隻能接一個裝置。速度快是USB技術的突出特點之一。全速USB接口的最高傳輸率可達12Mb/s,比序列槽快了整整100倍,USB總線标準由1.1版更新到2.0版後,傳輸率由12Mbps增加到了480Mbps,.這使得高分辨率、真彩色的大容量圖象的實時傳送成為可能。USB接口支援多個不同裝置的串列連接配接,一個USB接口理論上可以連接配接127個USB裝置。連接配接方式也十分靈活,既可以使用串行連接配接,也可以使用集線器(Hub)把多個裝置連接配接在一起,再同PC機的USB接口相接。普通的使用序列槽、并口的裝置都需要單獨的供電系統,而USB裝置則不需要。正是由于USB的這些特點,使其獲得了廣泛的應用。

二、USB的總線結構

Windows下usb接口驅動技術

        USB的總線結構是采用階梯式星形(tiered star)的拓撲(topology)結構,如上圖和下圖所示。每一個星形的中心是集線器,而每一個裝置可以通過集線器上的接口來加以連接配接。從圖中可以看到USB的設各包含了兩種類型:USB集線器與USB裝置。位于最頂端的就是Host(主機端)。從Host的聯機往下連接配接至Hub(集線器),再由集線器按階梯式以一層或一階的方式往下擴充出去,連接配接在下一層的裝置或另一個集線器上。事實上,集線器也可視為一種裝置。而其中最大層數為6層(包括計算機内部的根集線器)。每一個星形的外接點的數目可加以變化,一般集線器具有2、4或7個接口。

Windows下usb接口驅動技術

        在此的主機端通常是指PC主機。當然,主機端因具有根集線器,是以也含有集線器的功能。而集線器是在USB規範中特别定義出來的外圍裝置,除了擴增系統的連接配接點外,還負責中繼(repeat)上端/下端的信号以及控制各個下端端口的電源管理。至于另一個裝置,即是使用者常見的外圍裝置。但在USB規範書中,稱這種裝置為“功能”(functions),意味着此系統提供了某些“能力”,例如具有鍵盤或滑鼠等功能。當然不同的外圍設各可以具有不同的功能。通過這種階梯式星形的連接配接方式,最多可同時連接配接到127個裝置。

三、USB結構與工作原理

        一個USB系統可以從三個方面加以描述:

                (1) USB互聯。

                (2) USB裝置。

                (3) USB主機。

        USB互聯是指一個USB裝置與USB主機相聯并和其通信的方式,它包括:

                (1) 總線拓撲結構:USB主機和USB裝置的連接配接模型。

                (2) 層間關系:USB在系統中的每一層都要完成一定的任務。

                (3) 資料流模型:USB系統中信源和資訊之間的資料傳送方式。

                (4) 任務規劃:USB提供可以共享的互聯機制。通過規劃對互連機制的通路,可以支援同步資料傳輸。

四、USB硬體結構

        一個USB系統包含三類硬體裝置: USB主機(USB HOST)、 USB裝置(USB DEVICE)、USB集線器(USB HUB)。

  (1) USB HOST -  一般是指有USB接口的電腦。

        在一個USB系統中,當且僅當有一個USB HOST時,USB HOST有以下功能:

                        Ø  管理USB系統;

                        Ø  每毫秒産生一幀資料;

                        Ø  發送配置請求對USB裝置進行配置操作;

                        Ø  對總線上的錯誤進行管理和恢複。

  (2) USB DEVICE - 一般是指的是優盤、手機等裝置。

        在一個USB系統中,USB DEVICE和USB HUB總數不能超過127個。USB DEVICE接收USB總線上的所有資料包,通過資料包的位址域來判斷是不是發給自己的資料包:若位址不符,則簡單地丢棄該資料包;若位址相符,則通過響應USB HOST的資料包與USB HOST進行資料傳輸。

  (3)USB HUB - 一般指一轉多的USB裝置。

        USB HUB用于裝置擴充連接配接,所有USB DEVICE都連接配接在USB HUB的端口上。一個USB HOST總與一個根HUB (USB ROOT HUB)相連。USB HUB為其每個端口提供100mA電流供裝置使用。同時,USB HUB可以通過端口的電氣變化診斷出裝置的插拔操作,并通過響應USB HOST的資料包把端口狀态彙報給USB HOST。一般來說,USB裝置與USB HUB間的連線長度不超過5m,USB系統的級聯不能超過6級(包括ROOT HUB)。

        USB總線最多可支援127個USB外設連接配接到計算機系統。USB的拓撲是樹形結構,有1個USB根集線器(root hub),下面還可有若幹集線器。1個集線器下面可接若幹USB接口。USB線纜包括4條線:Vbus(USB電源)、D+(資料)、D-(資料)和 Gnd(USB地)。線纜最大長度不超過5m。USB1.1的傳輸速率最高為12Mb/s(低速外設的标準速率為1.5Mb/s,高速外設的标準速率為 12Mb/s)。USB外設可以采用計算機裡的電源(+5V,500mA),也可外接USB電源。在所有的USB信道之間動态地配置設定帶寬是USB總線的特征之一,這大大地提高了USB帶寬的使用率。當一台USB外設長時間(3ms以上)不使用時,就處于挂起狀态,這時隻消耗0.5mA 電流。按USB1.0/1.1标準,USB的标準脈沖時鐘頻率為12MHz,而其總線時脈沖時鐘為1ms(1kHz),即每隔1ms,USB器件應為 USB線纜産生1個時鐘脈沖序列。這個脈沖系列稱為幀開始資料包(SOF)。高速外設長度為每幀12000bit(位),而低速外設長度隻有每幀 1500bit。1個USB資料包可包含0~1023位元組資料。每個資料包的傳送都以1個同步字段開始。

五、USB的資料流

        主要制器負責主機和USB裝置間資料流的傳輸。這些傳輸資料被當作連續的比特流。每個裝置提供了一個或多個可以與客戶程式通信的接口,每個接口由0個或多個管道組成,它們分别獨立地在客戶程式和裝置的特定終端間傳輸資料。USBD為主機軟體的現實需求建立了接口和管道,當提出配置請求時,主要制器根據主機軟體提供的參數提供服務。

        USB支援四種基本的資料傳輸模式:控制傳輸,等時傳輸,中斷傳輸及資料塊傳輸。每種傳輸模式應用到具有相同名字的終端,則具有不同的性質。

        控制傳輸類型:支援外設與主機之間的控制,狀态,配置等資訊的傳輸,為外設與主機之間提供一個控制通道。每種外設都支援控制傳輸類型,這樣主機與外設之間就可以傳送配置和指令/狀态資訊。

        等時傳輸類型:支援有周期性,有限的時延和帶寬且資料傳輸速率不變的外設與主機間的資料傳輸。該類型無差錯校驗,故不能保證正确的資料傳輸,支援像計算機-電話內建系統(CTI)和音頻系統與主機的資料傳輸。

        中斷傳輸類型:支援像遊戲搖桿,滑鼠和鍵盤等輸入裝置,這些裝置與主機間資料傳輸量小,無周期性,但對響應時間敏感,要求馬上響應。

        資料塊傳輸類型:支援列印機,掃描器,數位相機等外設,這些外設與主機間傳輸的資料量大,USB在滿足帶寬的情況下才進行該類型的資料傳輸。

        USB采用分塊帶寬配置設定方案,若外設超過目前帶寬配置設定或潛在的要求,則不能進入該裝置。同步和中斷傳輸類型的終端保留帶寬,并保證資料按一定的速率傳送。集中和控制終端按可用的最佳帶寬來傳輸傳輸資料。

六、USB外設控制器的兩種實作方式

        USB晶片在外設領域的應用面很廣。USB外設控制晶片通常包括USB收發器、串行接口引擎(SIE)、USB控制器和外設功能等四個子產品(SIE 主要以硬體方式處理大多數USB協定,USB控制器負責與PC互動通信資訊)。USB控制器一般有兩種類型:一種是MCU內建在晶片裡面的,如 Intel的8X930AX、CYPRESS的EZ-USB、SIEMENS的C541U以及 MOTOLORA、National Semiconductors等公司的産品;另一種就是純粹的USB接口晶片,僅處理 USB通信,如PHILIPS的PDIUSBD11(I2C接口)、 PDIUSBP11A、PDIUSBD12(并行接口),National Semiconductor的USBN9602、USBN9603、USBN9*等。

        內建MCU的USB控制晶片優點是CPU與控制器在同一片晶片裡,CPU隻需要通路一系列寄存器和存儲器,便可實作USB口的資料傳輸,最大限度的發揮 USB高速的特點。而且簡化了程式的設計,極大地降低了USB外設的開發難度。缺點是靈活性不夠高,開發成本較大。

        純粹的USB接口晶片的優點是系統組成靈活,可根據不同的系統需求,搭配不同的MCU,具有較高的性能價格比。但因為USB控制器是通過串行口或并行口與MCU連接配接,在傳輸速度方面和開發難度方面不如內建了MCU的控制晶片。

        不同的實作方式在設計開銷、上市時間、元器件開銷和引腳數方面各有優劣,選擇不同的方案意味着在以上各項名額中進行取舍。如PHILIPS公司的PDIUSBD12器件。該晶片是一款成本效益很高的USB器件,它通常用作微控制器系統中實作與微控制器進行通信的高速通用并行接口,設計者可根據需要選擇合适的微控制器,靈活性較大,适用于開發低成本且高效的USB外圍裝置。

七、USB裝置的枚舉過程

        USB架構中, hub負責檢測裝置的連接配接和斷開,利用其中斷IN端點(Interrupt IN Endpoint)來向主機(Host)報告。在系統啟動時,主機輪詢它的根hub(Root Hub)的狀态看是否有裝置(包括子hub和子hub上的裝置)連接配接。

Windows下usb接口驅動技術

        一旦獲悉有新裝置連接配接上來,主機就會發送一系列的請求(Resqusts)給裝置所挂載到的hub,再由hub建立起一條連接配接主機(Host)和裝置(Device)之間的通信通道。然後主機以控制傳輸(Control Transfer)的方式,通過端點0(Endpoint 0)對裝置發送各種請求,裝置收到主機發來的請求後回複相應的資訊,進行枚舉(Enumerate)操作。所有的USB裝置必須支援标準請求(Standard Requests),控制傳輸方式(Control Transfer)和端點0(Endpoint 0)。

        當枚舉完成後,這個新添加的裝置可在Windows的裝置管理器裡面看到,當使用者删除這個裝置/硬體時,系統把這個裝置從裝置管理器裡删除。

        對于一般的裝置,固件(Firmware)内包含主機所要請求的資訊,而有些裝置則是完全由硬體來負責響應主機的請求。在主機方面則是由作業系統而非應用程式負責處理相關枚舉操作。

        USB協定定義了裝置的6種狀态,僅在枚舉過程種,裝置就經曆了4個狀态 的遷移:上電狀态(Powered),預設狀态(Default),位址狀态(Address)和配置狀态(Configured)(其他兩種是連接配接狀态和挂起狀态(Suspend))。

        USB協定定義了裝置的6種狀态,僅在枚舉過程種,裝置就經曆了4個狀态的遷移:上電狀态(Powered),預設狀态(Default),位址狀态(Address)和配置狀态(Configured)(其他兩種是連接配接狀态和挂起狀态(Suspend))。

        下面步驟是Windows系統下典型的枚舉過程,但是固件不能依此就認為所有的枚舉操作都是按照這樣一個流程行進。裝置必須在任何時候都能正确處理所有的主機請求。

                1. 使用者把USB裝置插入USB端口或給系統啟動時裝置上電。

                        這裡指的USB端口指的是主機下的根hub或主機下行端口上的hub端口。Hub給端口供電,連接配接着的裝置處于上電狀态。

                2. Hub監測它各個端口資料線上(D+/D-)的電壓

                        在hub端,資料線D+和D-都有一個阻值在14.25k到24.8k的下拉電阻Rpd,而在裝置端,D+(全速,高速)和D-(低速)上有一個1.5k的上拉電阻Rpu。當裝置插入到hub端口時,有上拉電阻的一根資料線被拉高到幅值的90%的電壓(大緻是3V)。hub檢測到它的一根資料線是高電平,就認為是有裝置插入,并能根據是D+還是D-被拉高來判斷到底是什麼裝置(全速/低速)插入端口(全速、高速裝置的區分在我将來的文章中描述)。如下圖。

Windows下usb接口驅動技術

                        檢測到裝置後,hub繼續給裝置供電,但并不急于與裝置進行USB傳輸。

                        3. Host了解連接配接的裝置。

                        每個hub利用它自己的中斷端點向主機報告它的各個端口的狀态(對于這個過程,裝置是看不到的,也不必關心),報告的内容隻是hub端口的裝置連接配接/斷開的事件。如果有連接配接/斷開事件發生,那麼host會發送一個 Get_Port_Status請求(request)以了解更多hub上的資訊。Get_Port_Status等請求屬于所有hub都要求支援的hub類标準請求(standard hub-classrequests)。

                        4. Hub檢測所插入的裝置是高速還是低速裝置。

                        hub通過檢測USB總線空閑(Idle)時差分線的高低電壓來判斷所連接配接裝置的速度類型,當host發來Get_Port_Status請求時,hub就可以将此裝置的速度類型資訊回複給host。(USB 2.0規範要求速度檢測要先于複位(Reset)操作)。

                        5. hub複位裝置。

                        當主機獲悉一個新的裝置後,主機控制器就向hub發出一個 Set_Port_Feature請求讓hub複位其管理的端口。hub通過驅動資料線到複位狀态(D+和D-全為低電平 ),并持續至少10ms。當然,hub不會把這樣的複位信号發送給其他已有裝置連接配接的端口,是以其他連在該hub上的裝置自然看不到複位信号,不受影響。

                        6. Host檢測所連接配接的全速裝置是否是支援高速模式。

                        因為根據USB 2.0協定,高速(High Speed)裝置在初始時是預設全速(Full Speed )狀态運作,是以對于一個支援USB 2.0的高速hub,當它發現它的端口連接配接的是一個全速裝置時,會進行高速檢測,看看目前這個裝置是否還支援高速傳輸,如果是,那就切到高速信号模式,否則就一直在全速狀态下工作。

                        同樣的,從裝置的角度來看,如果是一個高速裝置,在剛連接配接bub或上電時隻能用全速信号模式運作(根據USB 2.0協定,高速裝置必須向下相容USB 1.1的全速模式)。随後hub會進行高速檢測,之後這個裝置才會切換到告訴模式下工作。假如所連接配接的hub不支援USB 2.0,即不是高速hub,不能進行高速檢測,裝置将一直以全速工作。

                        7.  Hub建立裝置和主機之間的資訊通道。

                        主機不停得向hub發送 Get_Port_Status請求,以查詢裝置是否複位成功。Hub傳回的報告資訊中有專門的一位用來标志裝置的複位狀态。

                        當hub撤銷了複位信号,裝置就處于預設/空閑狀态(Default state),準備着主機發來的請求。裝置和主機之間的通信通過控制傳輸,預設位址0,端點号0進行。在此時,裝置能從總線上得到的最大電流是100mA。

                        8. 主機發送Get_Descriptor請求擷取預設管道的最大包長度。

                        預設管道(Default Pipe)在裝置一端來看就是端點0。主機此時發送的請求是預設位址0,端點0,雖然所有位配置設定位址的裝置都是通過位址0來擷取主機發來的資訊,但由于枚舉過程不是多個裝置并行處理,而是一次枚舉一個裝置的方式進行,是以不會發生多個裝置同時響應主機發來的請求。

                        裝置描述符的第8位元組代表裝置端點0的最大包大小。對于Windows系統來說,Get_Descriptor請求中的wLength一項都會設為64,雖然說裝置所傳回的裝置描述符(Device Descriptor)長度隻有18位元組,但系統也不在乎,此時,描述符的長度資訊對它來說是最重要的,其他的瞄一眼就過了。Windows系統還有個怪癖,當完成第一次的控制傳輸後,也就是完成控制傳輸的狀态階段,系統會要求hub對裝置進行再一次的複位操作(USB規範裡面可沒這要求)。再次複位的目的是使裝置進入一個确定的狀态。

                        9. 主機給裝置配置設定一個位址。

                        主機控制器通過Set_Address請求向裝置配置設定一個唯一的位址。在完成這次傳輸之後,裝置進入位址狀态(Address state),之後就啟用新位址繼續與主機通信。這個位址對于裝置來說是終生制的,裝置在,位址在;裝置消失(被拔出,複位,系統重新開機),位址被收回。同一個裝置當再次被枚舉後得到的位址不一定是上次那個了。

                        10. 主機擷取裝置的資訊。

                        主機發送 Get_Descriptor請求到新位址讀取裝置描述符,這次主機發送Get_Descriptor請求可算是誠心,它會認真解析裝置描述符的内容。裝置描述符内資訊包括端點0的最大包長度,裝置所支援的配置(Configuration)個數,裝置類型,VID(Vendor ID,由USB-IF配置設定), PID(Product ID,由廠商自己定制)等資訊。Get_Descriptor請求(Device type)和裝置描述符(已抹去VID,PID等資訊)之後主機發送Get_Descriptor請求,讀取配置描述符(Configuration Descriptor),字元串等,逐一了解裝置更詳細的資訊。事實上,對于配置描述符的标準請求中,有時wLength一項會大于實際配置描述符的長度(9位元組),比如255。這樣的效果便是:主機發送了一個Get_Descriptor_Configuration 的請求,裝置會把接口描述符,端點描述符等後續描述符一并回給主機,主機則根據描述符頭部的标志判斷送上來的具體是何種描述符。

                        11. 主機給裝置挂載驅動(複合裝置除外)。

                        主機通過解析描述符後對裝置有了足夠的了解,會選擇一個最合适的驅動給裝置。在驅動的選擇過程中,Windows系統會和系統inf檔案裡的廠商ID,産品ID,有時甚至用到裝置傳回來的産品版本号進行比對。如果沒有比對的選項,Windows會根據裝置傳回來的類,子類,協定值資訊選擇。如果該裝置以前在系統上成功枚舉過,作業系統會根據以前記錄的登記資訊而非inf檔案挂載驅動。當作業系統給裝置指定了驅動之後,就由驅動來負責對裝置的通路。對于複合裝置,通常應該是不同的接口(Interface)配置給不同的驅動,是以,需要等到當裝置被配置并把接口使能後才可以把驅動挂載上去。

                        裝置-配置-接口-端點關系見下圖:

Windows下usb接口驅動技術

                        實際情況沒有上述關系複雜。一般來說,一個裝置就一個配置,一個接口,如果裝置是多功能符合裝置,則有多個接口。端點一般都有好幾個,比如Mass Storage裝置一般就有兩個端點(控制端點0除外)。

                        12. 裝置驅動選擇一個配置。

                        驅動(注意,這裡是驅動,之後的事情都是有驅動來接管負責與裝置的通信)根據前面裝置回複的資訊,發送Set_Configuration請求來正式确定選擇裝置的哪個配置(Configuration)作為工作配置(對于大多數裝置來說,一般隻有一個配置被定義)。至此,裝置處于配置狀态,當然,裝置也應該使能它的各個接口(Interface)。

                        對于複合裝置,主機會在這個時候根據裝置接口資訊,給它們挂載驅動。

                        13. 裝置可使用。

                        至此,步驟完成,裝置可用了。

八、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接口驅動技術

        應用程式通過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接口驅動技術

        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。

繼續閱讀