现在的位置: 首页 > 综合 > 正文

电池驱动介绍

2012年03月13日 ⁄ 综合 ⁄ 共 4987字 ⁄ 字号 评论关闭

 

电池驱动介绍

一.整体框架

         电池驱动代码量很小,可是麻雀虽小,五脏俱全。与其他的很多Driver一样,分为PDD+MDD层,双层之间通过PDD的如下导出接口相联系。    

Programming element

Description

BatteryDrvrGetLevels

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.

BatteryDrvrSupportsChangeNotification

This function indicates whether the battery driver can report whether the batteries were changed.

BatteryGetLifeTimeInfo

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.

BatteryNotifyOfTimeChange

This function adjusts times to account for the user changing the real time.

BatteryPDDDeinitialize

This function allows the battery PDD to perform hardware-specific cleanup.

BatteryPDDGetLevels

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.

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.

BatteryPDDInitialize

This function allows the battery PDD to perform hardware-specific initialization.

BatteryPDDPowerHandler

This power callback performs hardware-specific processing for the battery driver.

BatteryPDDResume

This function performs hardware-specific battery processing in a thread context following system resume.

BatteryPDDSupportsChangeNotification

This function indicates whether the battery driver can report whether the batteries were changed.

PFN_BATTERY_PDD_IOCONTROL

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”的值配置成8DEVFLAGS_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

抱歉!评论已关闭.