今天來看看WinCE6.0平臺下USB Function驅動部分加載流程,USB Function是指WinCE設備相對於PC機而講的,通常能夠支持Mass Storage、RNDIS、Printer或者Serial Class。在實際中用的最多的莫過於串口功能,做爲一個串口設備鏈接PC機,實現activesync的功能。
在目錄WINCE600\PUBLIC\COMMON\OAK\DRIVERS\USBFN下面有微軟提供的關於USB Function的驅動程序,此目錄下的層次結構爲:
在以前的博文中已經對該目錄的總體功能進行了說明,這裏就不重複了。
在CONTROLLER控制器文件夾是整個Function驅動的入口處,在該目錄下的MDD文件夾內實現並導出了總線接口,並利用該接口加載USB Function Client驅動。下面具體分析。
注意在CONTROLLER目錄下面有一個NET2280的文件夾,它實現的NET2280控制器的PDD部分。可是在common.reg下面並無找到相關的註冊表信息,說明實際的設備平臺中並無使用微軟默認的控制器型號。
本人使用的平臺是Android6410的開發板,在PLATFORM目錄下發現了USB Funtion Contrller的PDD部分,在 WINCE600\PLATFORM\SMDK6410\SRC\DRIVERS\OTG\Device的目錄下,這裏使用了OTG做爲了Function功能。該目錄下面的內容爲:
同時在platform.reg文件中發現了關於控制器的註冊表信息,以下:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\SC6410USBFN]
"Dll"="s3c6410_usbfn.dll"
"Prefix"="UFN"
"Order"=dword:20
"Priority256"=dword:64
"Irq"=dword:60 ; USB OTG Virtual IRQ = 96 (0x60), Physical IRQ = 58
"BusIoctl"=dword:2a0048
"IClass"=multi_sz:"{E2BDC372-598F-4619-BC50-54B3F7848D35}=%b","{6F40791D-300E-44E4-BC38-E0E63CA8375C}=%b"
因此係統加載的USB Function Controller驅動是s
3c
6410_usbfn.dll,由設備管理Device.exe從註冊表HKEY_LOCAL_MACHINE\Drivers\BuiltIn下面加載該驅動。
看看s
3c
6410_usbfn.def文件導出了哪些接口函數:
LIBRARY S3C6410_USBFN
EXPORTS
UFN_Init
UFN_Deinit
UFN_Open
UFN_Close
UFN_PowerDown
UFN_PowerUp
UFN_IOControl
在目錄WINCE600\PUBLIC\COMMON\OAK\DRIVERS\USBFN\CONTROLLER\MDD下面的ufnmdd.cpp文件裏,實現了流接口的入口函數DllEntry()函數,不過該函數並無具體的操做內容。
接着來看看UFN_Init()函數。在初始化函數中首先建立PUFN_MDD_CONTEXT結構體,用來記錄驅動MDD層的一些信息,包括一些MDD層的接口函數。該信息將會在驅動接口之間經過參數進行傳遞。以後建立了CUfnBus類的一個實例,經過該類能夠加載Client層驅動,而且處理USB function controller驅動的IOCTLS。建立以後便調用CUfnBus::Init()函數完成總線的相關初始化。最後調用PDD層的初始化函數UfnPdd_Init(),完成硬件控制器的一些初始化設置,將PDD層的硬件操做函數封裝成函數列表結構體傳遞給MDD層。
從上述的過程當中,始終沒有發現如何調用Client驅動的,從參考資料中發現,在建立CUfnBus類以後,會調用該類的成員函數PostInit(),而CUfnBus類是從DefaultBusDriver類繼承過來的,在這個裏面找到了啓動Client驅動的方式。
PostInit()函數主要調用了四個函數:
函數CUfnBus::GetDefaultClientName用來獲取默認的Client名稱; 而CUfnBus::CreateChild和DefaultBusDriver::InsertChild用來建立一個usb bus的child,並添加到相應的list列表中;CUfnBus::ActivateChild則是用來啓動一個Client驅動的。
在註冊表platform.reg中有一個默認的Client名稱選項,以下:
[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers]
"DefaultClientDriver"=- ; erase previous default
IF BSP_USBFNCLASS == SERIAL
[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers]
"DefaultClientDriver"="Serial_Class"
ENDIF BSP_USBFNCLASS
IF BSP_USBFNCLASS == MASS_STORAGE
[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers]
"DefaultClientDriver"="Mass_Storage_Class"
ENDIF BSP_USBFNCLASS
本文的硬件平臺是Android6410開發板,從註冊表中能夠看出,在該平臺下支持WinCE設備爲串口或者大容量存儲器兩種狀態,而微軟提供的能夠支持四種狀態。另外上面有一個環境變量BSP_USBFNCLASS決定了默認的Client驅動是哪一個?而平臺的環境變量定義在文件WINCE600\PLATFORM\SMDK6410\ SMDK6410.bat中,
在CUfnBus::ActivateChild函數當中調用了父類的函數DefaultBusDriver::ActivateChild。在文件WINCE600\PUBLIC\COMMON\OAK\DRIVERS\BUSENUM\BUSDEF\defbus.cpp中有類DefaultBusDriver的實現。在父類的ActivateChild()函數中,又調用了類DeviceFolder的成員函數LoadDevice()。類DeviceFolder和類DefaultBusDriver在同一個文件中實現。在DeviceFolder::LoadDevice函數中根據驅動DLL的不一樣類型,調用::LoadLibrary(DevDll)或者::LoadDriver(DevDll),其中DevDll爲驅動的名稱。以後經過GetProcAddress()函數獲取到相應驅動的入口函數地址,並調用驅動的入口初始化函數。
今天就先分析一下加載流程,之後再進一步分析數據傳輸的流程。
參考資料:
Windows CE USB Function Driver驅動簡析(1)
WINCE6.0+S
3C
2443下的usb function(功能)驅動