WinCE6.0 USB Fubction驱动加载流程

     今天来看看 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)
http://blog.csdn.net/shevsten/archive/2010/07/15/5736889.aspx
WINCE6.0+S 3C 2443 下的 usb function( 功能 ) 驱动
http://blog.csdn.net/loongembedded/article/details/6253770


你可能感兴趣的:(function,休闲,USB驱动,WinCE6.0,驱动加载流程)