wince5.0电池驱动样本分析

来源:互联网 发布:linux bluetooth 测试 编辑:程序博客网 时间:2024/05/20 11:23

       battdrvr驱动是分层驱动,battdrvr.cMDD层的,微软已经为我们搭好了构架,我们一般不需要修改,我们要实现的是PDD层的代码,PPD层的代码在sbattif.c里面实现。

       首先分析MDD层的代码。首先定义了一个BATTERY_CONTEXT结构来存储电池信息,其中,dwPollTimeout是循环更新电池信息线程的最大阻塞时间,iPriority是这个线程的优先级,st存储系统电源状态信息,它是一个SYSTEM_POWER_STATUS_EX2结构体,可以在MSDN里面查到它的原型。然后声明一些全局变量,gcsBattery是临界区,然后定义了一个PFN_BATTERY_PDD_IOCONTROL函数,这个函数的参数说明也可以在MSDN里面查阅,声明一个句柄ghevResume来控制BatteryThreadProc的阻塞,而ghtBattery句柄是用来指示

BatteryThreadProc创建是否成功的,接下来声明一个BOOL类型的变量gfExiting判断是否卸载驱动,最后声明一个代表电池的信息的变量gBatteryContext

       我们开始分析第一个流接口函数Init,在battdrvr.reg中有这样一句:"Flags"=dword:8        ; DEVFLAGS_NAKEDENTRIES

所以,这几个流接口函数前面都省略了前缀BAT

Init函数首先判断ghevResume是否为空,如果为空则代表驱动尚未被加载过,我们在if语句里面需要做一些初始化的工作。如果需要使用battery函数,就要SYSTEM/BatteryAPIsReady事件信号被激活,这个事件在Battery.h里面被定义为BATTERY_API_EVENT_NAME。所以Init调用OpenEvent打开这个事件,并返回这个事件的句柄给hevReady。然后函数InitializeCriticalSection初始化临界区gcsBatterygpfnBatteryPddIOControl被定义为NULL表示MDD层不负责初始化这个变量,交给PDD层完成这个工作。然后创建事件初始化ghevResume。接着把Context传递给PDD层函数BatteryPDDInitialize,由BatteryPDDInitialize来做进一步的和硬件相关的初始化工作。接着初始化代表电池信息的gBatteryContext。然后调用OpenDeviceKey函数获得Context注册表键值的句柄,接下来依次获得线程的优先级及其阻塞时间。再调用BatteryAPIGetSystemPowerStatusEx2函数初始化电池更新。在if的最后调用CreateThread函数开始BatteryThreadProc线程并将gBatteryContext传递给它,同时激活SYSTEM/BatteryAPIsReady事件信号。在done里面有这样一句:

WaitForSingleObject(ghtBattery, INFINITE);

也许意思是让定时更新电池信息的线程即BatteryThreadProc执行完毕。

       接下来我们就来分析一下这个定时更新电池信息的线程BatteryThreadProcInit传给pvParam的参数BATTERY_CONTEXT类型的指针,所以我们需要把pvParam转换为PBATTERY_CONTEXT。调用函数CeSetThreadPriority来设置当前进程的优先级。PowerPolicyNotify函数的头文件是pmpolicy.h,第一个参数决定了第二个参数必须设置为0,这个函数通知电源管理器更新电池状态。接下来调用WaitForSingleObject函数定时循环这个线程,如果dwStatusWAIT_TIMEOUT,即到时间需要更新电池信息了,LOCKBATTERYUNLOCKBATTERYsbattif.c里面定义的,保证了两者时间的代码是CPU独占的,在这个独占的时间内,BatteryThreadProc调用BatteryAPIGetSystemPowerStatusEx2更新电池信息,然后判断是不是有更新,有则更新pbc并通知电源管理器更新电池状态;如果dwStatusWAIT_OBJECT_0,说明系统继续了这个线程,那么我们就重新启动这个这个时间表,BatteryAPIStopwatch函数在battapi.c里面实现,BatteryPDDResume用于调试,我们不用关心。

       下面还有一个重要的流接口函数IOControl,我们简单对其分析。

       如果IOControl的第二个参数为IOCTL_BATTERY_GETSYSTEMPOWERSTATUSEX2,判断是否有写数据,如果有则调用BatteryAPIGetSystemPowerStatusEx2函数更新电池信息;如果IoctlIOCTL_BATTERY_GETSYSTEMPOWERSTATUSEX,操作与前面相似;如果IoctlIOCTL_BATTERY_GETLIFETIMEINFOIOControl函数调用BatteryAPIGetLifeTimeInfo来获取PBATTERYLIFETIMEINFO信息,这个函数在battapi.c里面定义;如果ioctlIOCTL_BATTERY_GETLEVELSIOControl调用BatteryPDDGetLevels来获取level值;如果ioctlIOCTL_BATTERY_SUPPORTSCHANGENOTIFICATIONIOControl调用BatteryPDDSupportsChangeNotification来获知电源信息更新与否;如果ioctlIOCTL_BATTERY_NOTIFYOFTIMECHANGEIOControl调用BatteryAPINotifyOfTimeChange函数。

       为了防止编译器关于为引用参数的警告,我们可以使用宏UNREFERENCED_PARAMETER来展开传递参数,没有实际作用,所以我们不用再分析其他流接口函数。

       至此,wince5.0电池样本驱动的MDD层就分析完了,下面简单分析PDD层代码。首先定义了由ghMutex互斥信号量决定的两个函数LockBatteryUnlockBattery。我们主要分析下BatteryPDDInitialize函数,这个函数先初始化电池状态结构体SYSTEM_POWER_STATUS_EX2变量sps。然后打开注册表,查询各种信息并保存。接着,创建信号量,获取文件映射的指针。最后完成文件映射工作。其他函数都比较容易读懂了。

      

原创粉丝点击