|
|
#define BATTERYCLASS 1
#ifndef FAR
#define FAR
#endif
#include <wdm.h>
#include <wmistr.h>
#include <wmilib.h>
#include <batclass.h>
//
// Debug
//
#define DEBUG DBG
#if DEBUG
extern ULONG BattDebug; extern ULONG NextDeviceNum; #define BattPrint(l,m) if(l & BattDebug) DbgPrint m
#else
#define BattPrint(l,m)
#endif
#define BATT_LOW 0x00000001
#define BATT_NOTE 0x00000002
#define BATT_WARN 0x00000004
#define BATT_ERROR 0x00000008
#define BATT_TRACE 0x00000010
#define BATT_MP_ERROR 0x00000100
#define BATT_MP_DATA 0x00000200
#define BATT_IOCTL 0x00001000
#define BATT_IOCTL_DATA 0x00002000
#define BATT_IOCTL_QUEUE 0x00004000
#define BATT_WMI 0x00008000
#define BATT_LOCK 0x00010000
#define BATT_DEBUG 0x80000000
//
// Battery class info
//
#define NTMS 10000L // 1 millisecond is ten thousand 100ns
#define NTSEC (NTMS * 1000L)
#define NTMIN ((ULONGLONG) 60 * NTSEC)
#define SEC 1000
#define MIN (60 * SEC)
#define MIN_STATUS_POLL_RATE (3L * NTMIN)
// This is the slowest rate at which we should ever poll
// the battery when doing polling.
#define MAX_STATUS_POLL_RATE (20 * NTSEC)
// This is in general the fastest we should ever poll the battery.
#define INVALID_DATA_POLL_RATE (1 * NTSEC)
// If the battery returned invalid information, we want to poll
// it more frequesntly, since invalid information generally
// indicates that the battery was in a transition state. The user
// will not want to wait 20 seconds for the UI to update, but we don't
// want to poll too fast and hurt the performance of a machine with a
// poorly designed battery too much.
#define INVALID_DATA_MAX_RETRY 10
// Only retry 20 time before giving up.
// This should be reset on any notifiation from the battery.
#define STATUS_VALID_TIME (2 * NTSEC)
// If a request is received within STATUS_VALID_TIME of the last request
// time information was read, and there hasn't been a notification from
// the battery, the driver will assume that the cached values are good enough.
//
// WMI info
//
#define MOFRESOURCENAME L"BATTCWMI"
#define MOFREGISTRYPATH L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\BattC"
//#define MOFREGISTRYPATH L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{72631E54-78A4-11D0-BCF7-00AA00B7B32A}"
typedef enum { BattWmiStatusId, BattWmiRuntimeId, BattWmiTemperatureId, BattWmiFullChargedCapacityId, BattWmiCycleCountId, BattWmiStaticDataId, BattWmiStatusChangeId, BattWmiTagChangeId, BattWmiTotalGuids } BATT_WMI_GUID_INDEX;
//
// Non-paged battery class information
//
typedef struct {
//
// Pointer to paged information
//
struct _BATT_INFO *BattInfo; // Pointer to paged portion
//
// General
//
KTIMER WorkerTimer; // Timer to get worker thread
KDPC WorkerDpc; // DPC to get worker thread
KTIMER TagTimer; // Timer for query tag requests
KDPC TagDpc; WORK_QUEUE_ITEM WorkerThread; // WORK_QUEUE to get worker thread
ULONG WorkerActive; ULONG CheckStatus; // Worker to check status
ULONG CheckTag; // Worker to check for battery tag
ULONG StatusNotified; // Notification has occured (must re-read)
ULONG TagNotified;
FAST_MUTEX Mutex; // Synchorize with worker thread
BOOLEAN WantToRemove; // Syncronize device removal
LONG InUseCount; KEVENT ReadyToRemove;
#if DEBUG
ULONG DeviceNum; // Device number for debug prints
#endif
} BATT_NP_INFO, *PBATT_NP_INFO;
//
// Paged battery class information
//
typedef struct _BATT_INFO {
WMILIB_CONTEXT WmiLibContext; ULONG WmiGuidIndex; // Used to ignore miniclass WMI
// GUIDs
//
// IO
//
ULONG Tag; // Current battery tag
LIST_ENTRY IoQueue; // IRPs waiting to be processed
LIST_ENTRY StatusQueue; // Waiting status requests
LIST_ENTRY TagQueue; // Waiting battery tag requests
LIST_ENTRY WmiQueue;
ULONGLONG TagTime; // Time when tag was read
ULONGLONG StatusTime; // Time when status was read
BATTERY_STATUS Status; // The status
ULONG InvalidRetryCount; // How many times ni a row has the battery returned invalid data?
#if DEBUG
ULONG FullChargedCap; PBATT_NP_INFO BattNPInfo; #endif
ULONG NotifyTimeout; // LCD timeout of wat
BATTERY_MINIPORT_INFO Mp; // Miniport Info
UNICODE_STRING SymbolicLinkName; // Name returned by IoRegisterDeviceInterface
} BATT_INFO, *PBATT_INFO;
//
// WmiQueue entry
//
typedef struct _BATT_WMI_REQUEST { LIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject; PIRP Irp; BATT_WMI_GUID_INDEX GuidIndex; IN OUT PULONG InstanceLengthArray; IN ULONG OutBufferSize; OUT PUCHAR Buffer;
} BATT_WMI_REQUEST, *PBATT_WMI_REQUEST;
//
// Prototypes
//
VOID BattCWorkerDpc ( IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
VOID BattCWorkerThread ( IN PVOID Context );
VOID BattCQueueWorker ( IN PBATT_NP_INFO BattNPInfo, IN BOOLEAN CheckStatus );
NTSTATUS BatteryIoctl( IN ULONG Ioctl, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN PrivateIoctl );
VOID BattCTagDpc ( IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
VOID BattCCancelTag ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
|