电池驱动介绍
一.整体框架
电池驱动代码量很小,可是麻雀虽小,五脏俱全。与其他的很多Driver一样,分为PDD+MDD层,双层之间通过PDD的如下导出接口相联系。
Programming element |
Description |
This function returns the number of levels that the battery driver is capable of returning in the BatteryFlag and BackupBatteryFlag members of the SYSTEM_POWER_STATUS_EX2 structure. |
|
This function indicates whether the battery driver can report whether the batteries were changed. |
|
This function retrieves the time the user changed the batteries, the amount of time they used the batteries, and the amount of time they used the batteries before replacing them. |
|
This function adjusts times to account for the user changing the real time. |
|
This function allows the battery PDD to perform hardware-specific cleanup. |
|
This function indicates how many battery levels are reported in the BatteryFlag and BackupBatteryFlag members of the SYSTEM_POWER_STATUS_EX2 structure filled in by BatteryPDDGetStatus. |
|
This function obtains the most current battery and power status available on the platform. It fills in the structures pointed to by its parameters. |
|
This function allows the battery PDD to perform hardware-specific initialization. |
|
This power callback performs hardware-specific processing for the battery driver. |
|
This function performs hardware-specific battery processing in a thread context following system resume. |
|
This function indicates whether the battery driver can report whether the batteries were changed. |
|
This function signature is for the battery driver custom IOCTL handler. It implements the optional PDD IOCTL interface. |
微软提供了电池驱动的Sample Code,从目录/WINCE600/PUBLIC/COMMON/OAK/DRIVERS
/BATTDRVR下可以找到。
注册表的配置如下:
IF BSP_NOBATTERY !
; HIVE BOOT SECTION
[HKEY_LOCAL_MACHINE/System/Events] "SYSTEM/BatteryAPIsReady"="Battery Interface APIs"
; END HIVE BOOT SECTION
; These registry entries load the battery driver. The IClass value must match ; the BATTERY_DRIVER_CLASS definition in battery.h -- this is how the system ; knows which device is the battery driver. Note that we are using ; DEVFLAGS_NAKEDENTRIES with this driver. This tells the device manager ; to instantiate the device with the prefix named in the registry but to look ; for DLL entry points without the prefix. For example, it will look for Init ; instead of BAT_Init. This allows the prefix to be changed in the registry (if ; desired) without editing the driver code. [HKEY_LOCAL_MACHINE/Drivers/BuiltIn/Battery] "Prefix"="BAT" "Dll"="battdrvr.dll" "Flags"=dword:8 ; DEVFLAGS_NAKEDENTRIES "Order"=dword:0 "IClass"="{DD176277-CD34-4980-91EE-67DBEF3D8913}"
ENDIF BSP_NOBATTERY ! |
PDD层基本上就是实现电池电量的采集和电池一些其它基本信息的获取,而MDD层主要是建立了一个线程BatteryThreadProc,该线程用来和控制面板中电源管理小工具进行通信。
二.值得一说的问题
电池驱动实在是太简单了,没啥可介绍的。
就说说常见的问题吧。
1.电池驱动的导出接口没有Prefix
一般的流接口驱动导出接口都会有一个前缀,即注册表中配置的Prefix的值,为三个字节的大写字母。
这是注册表中”Flags”的值配置成8(DEVFLAGS_NAKEDENTRIES)引起的,在这种情况下Device Manager操作流接口驱动程序的时候,就可以不需要Prefix前导符号。
详细的”Flags”的配置如下:
Flag |
Value |
Description |
DEVFLAGS_NONE |
0x00000000 |
No flags are defined. |
DEVFLAGS_UNLOAD |
0x00000001 |
Driver unloads after a call to the XXX_Init entry point or after the XXX_Init entry point returns. No error code is returned. Bus Enumerator typically runs with this flag. |
DEVFLAGS_LOADLIBRARY |
0x00000002 |
Driver is loaded with LoadLibrary instead of LoadDriver. |
DEVFLAGS_NOLOAD |
0x00000004 |
Driver is not loaded. |
DEVFLAGS_NAKEDENTRIES |
0x00000008 |
Driver entry points do not have a XXX Prefix prepended. |
DEVFLAGS_BOOTPHASE_1 |
0x00001000 |
Driver is loaded during boot phase one. By default, device drivers are loaded during boot phase two. Boot phase zero is before the Device Manager loads. Boot phase one is to find the registry. Boot phase two is when initial device drivers load. Boot phase three is after initial device drivers load. |
DEVFLAGS_IRQ_EXCLUSIVE |
0x00000100 |
Driver loads only when it has exclusive access to the IRQ. |
DEVFLAGS_TRUSTEDCALLERONLY |
0x00010000 |
Driver can only be opened by a trusted application. |
接下来,我们从Device Manager的代码中找到其原因。通常在应用程序或者一些Driver中尝试去动态加载流驱动的话,可以去调用API ActivateDeviceEx(),其实该函数最终调用的就是Device Manager中的函数I_ActivateDeviceEx()。
在文件/WINCE600/PRIVATE/WINCEOS/COREOS/DEVICE/DEVCORE/ devload.c中可以找到函数I_ActivateDeviceEx()的具体实现,该函数主要完成驱动程序对应的DLL的加载和初始化函数的调用,它首先会去调用函数CreateDevice()创建设备的一些结构体信息。在函数CreateDevice()中可以找到对”Flags”的一些判断处理。
代码如下:
// This routine allocates a device driver structure in memory and initializes it. // As part of this process, it loads the driver's DLL and obtains pointers to // its entry points. This routine returns a pointer to the new driver description // structure, or NULL if there's an error. static fsdev_t * CreateDevice( LPCWSTR lpszPrefix, DWORD dwIndex, DWORD dwLegacyIndex, DWORD dwId, LPCWSTR lpszLib, DWORD dwFlags, LPCWSTR lpszBusPrefix, LPCWSTR lpszBusName, LPCWSTR lpszDeviceKey, HANDLE hParent ) { fsdev_t *lpdev; DWORD dwSize; DWORD dwStatus = ERROR_SUCCESS; WCHAR szDeviceName[MAXDEVICENAME]; WCHAR szLegacyName[MAXDEVICENAME];
DEBUGCHK(lpszPrefix != NULL); DEBUGCHK(lpszLib != NULL); DEBUGCHK(wcslen(lpszPrefix) <= 3); DEBUGCHK(dwLegacyIndex == dwIndex || (dwLegacyIndex == 0 && dwIndex == 10)); DEBUGCHK(lpszBusName != NULL);
// figure out how much memory to allocate
|