Linux2.6環(huán)境下USB設備的驅動(dòng)實(shí)現
嵌入式linux系統環(huán)境以其易于移植裁減、內核小、效率高、完整、原代碼開(kāi)放及性能優(yōu)異等特點(diǎn),在嵌入式領(lǐng)域得到了非常廣泛的應用。Linux的USB設備端的源代碼中主要有USB device的海量存儲設備、串口設備、網(wǎng)絡(luò )設備等設備驅動(dòng)程序及各種USB device控制器芯片的驅動(dòng)程序。市場(chǎng)上USB設備控制器芯片種類(lèi)繁多,大多數用戶(hù)需要針對特定應用來(lái)開(kāi)發(fā)相關(guān)的USB設備控制器驅動(dòng)程序,才能使設備正常工作在linux操作系統下。
1 USB設備端驅動(dòng)系統
Linux Gadget子系統主要分為三層:第一層為芯片驅動(dòng)層,負責將各種USB device控制器抽象為統一的函數接口,以供上層驅動(dòng)程序調用;第二層主要是對操作函數的簡(jiǎn)單封裝;第三層為設備驅動(dòng)層,可根據系統的需求實(shí)現所對應的功能。圖1所示是Linux Gadget子系統的驅動(dòng)層次。Linux Gadget子系統的設備驅動(dòng)層主要根據各個(gè)類(lèi)別的規范及協(xié)議實(shí)現各種設備的驅動(dòng),本設計需要使一個(gè)嵌入式設備擁有移動(dòng)硬盤(pán)的功能,所以,可以根據海量存儲類(lèi)的規范及協(xié)議來(lái)實(shí)現該功能。

1.1 UDC驅動(dòng)的基本構架
圖2所示是UDC驅動(dòng)的基本構架圖。在控制器驅動(dòng)程序中,首先應注冊platform驅動(dòng),調用其probe函數搜索設備,并在probe函數內初始化usb_ep和usb_gadget等結構,然后注冊設備,并申請中斷,接著(zhù)等待中斷進(jìn)入中斷服務(wù)子程序,最后聲明和實(shí)現usb_gadget_register_driver注冊函數并輸出給上層驅動(dòng)。在該過(guò)程中,聯(lián)系它們的紐帶是一些全局結構體變量。
1.2 Gadget API
Gadget API為Gadget系統定義了統一的數據結構和接口函數,它和主機端的USB Core地位類(lèi)似,但功能僅限于提供編程接口,如用結構體usb_gadget_ops和usb_ep_ops對設備控制器驅動(dòng)操作函數和端點(diǎn)操作函數進(jìn)行重新封裝。比較特殊的是Gadget驅動(dòng)程序注冊函數usb_gadget_register_driver,它們是由設備控制器(UDC)驅動(dòng)直接提供的,用于將UDC綁定到gadget driver。這增加了Gadget Driver和UDC之間的依賴(lài)性。
在設備端,Gadget系統雖然類(lèi)似主機驅動(dòng)系統分了三層結構,但Gadget API只定義了一些數據結構、宏和功能函數,并對UDC驅動(dòng)程序進(jìn)行了簡(jiǎn)單包裝,而沒(méi)有驅動(dòng)管理等功能。
1.3設備應用驅動(dòng)程序
設備端應用程序(Gadget Driver)用于控制USB設備功能的實(shí)現,使設備表現出“網(wǎng)絡(luò )連接”、“打印機”或“大容量存儲設備”等特性。本文以大容量移動(dòng)存儲設備為例來(lái)實(shí)現移動(dòng)硬盤(pán)的功能。
BULK ONLY傳輸指的是主機和大容量存儲設備之間的一種數據傳輸方式。
2設備端驅動(dòng)調度
在嵌入式Linux操作系統中,Gadget driver和Gadget API可完成部分USB協(xié)議處理、BULK ONLY等傳輸協(xié)議以及指令的解析處理,用戶(hù)只需要在設備控制器驅動(dòng)程序中完成部分USB協(xié)議處理和Gadget API的銜接工作。
圖3所示的流程圖給出了USB設備端驅動(dòng)程序的基本調度思想。該方案的主要思路是被動(dòng)的接受主機端的傳輸命令(任何類(lèi)型的通信都由USB主機發(fā)起,USB設備間不能直接通信),然后通過(guò)中斷觸發(fā)的方式完成主機端的數據傳輸。當產(chǎn)生設備端中斷時(shí),設備控制器驅動(dòng)程序首先判斷中斷類(lèi)型。當其為批量傳輸端點(diǎn)IN中斷時(shí),驅動(dòng)程序會(huì )將該EP下鏈接的REQ中的數據依次寫(xiě)入USB2.0 OTG IP的設備控制器的內存區;當其為批量傳輸OUT中斷時(shí),驅動(dòng)程序會(huì )將設備控制器內存區的數據讀入REQ中的buffer中;當其為端點(diǎn)0的控制傳輸中斷時(shí),驅動(dòng)程序將讀取端點(diǎn)緩沖區的數據,并解析當前的設備請求。如果主機傳輸給設備的設備請求為USB REO SEDRESS(設置設備地址)、USB_REQ_GET_STATUS(獲取設備狀態(tài))、USB_REQ_SET_FEATURE(設置設備特性),設備控制器驅動(dòng)程序會(huì )自行響應請求。但是,如果是其它設備請求,如GET_DESCRIPTOR(獲取設備描述符)時(shí),設備控制器驅動(dòng)便會(huì )將該請求提交給Gadget Driver,然后由Gadget Driver排隊將該設備請求提交給端點(diǎn),以等待下次控制端點(diǎn)中斷。

控制傳輸比較復雜,它需要完成建立階段、數據傳輸階段和狀態(tài)階段。整個(gè)控制端點(diǎn)中斷的處理可通過(guò)四個(gè)狀態(tài)實(shí)現,分別是:端點(diǎn)0空閑(EP0_IDLE)、 數據IN傳輸(EP0 IN DATA_PHASE)、數據OUT傳輸(EP0 OUT DATA_PHASE)和狀態(tài)階段(EPO_STATUS)。
EP0_IDLE狀態(tài)主要處理建立階段的setup令牌,并根據獲得的設備請求處理能夠處理的設備請求,同時(shí)把不能處理的設備請求(如獲取設備描述符,配置描述符等)提交給上層Gadget Driver;EP0_OUT_DATA_PHASE狀態(tài)主要處理數據階段的OUT傳輸;EP0_OUT_DATA_PHASE狀態(tài)主要處理數據階段的IN傳輸;EP0_STATUS狀態(tài)則主要完成控制傳輸過(guò)程中的狀態(tài)階段。
在圖3所示的流程圖中,EP0為控制傳輸端點(diǎn),EP1、EP2、EP3為批量傳輸端點(diǎn),它們主要包括端點(diǎn)傳輸類(lèi)型、端點(diǎn)緩沖區大小等信息。REQ為Gadget Driver提交的端點(diǎn)請求,主要包含傳輸的數據長(cháng)度和地址。
評論