241 lines
6.4 KiB
C
241 lines
6.4 KiB
C
|
|
#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
|
|
);
|
|
|
|
|
|
|