402 lines
9.2 KiB
C
402 lines
9.2 KiB
C
|
|
||
|
#include <wdm.h>
|
||
|
#include <batclass.h>
|
||
|
|
||
|
|
||
|
#ifndef FAR
|
||
|
#define FAR
|
||
|
#endif
|
||
|
|
||
|
|
||
|
//
|
||
|
// Debug
|
||
|
//
|
||
|
|
||
|
#define DEBUG DBG
|
||
|
|
||
|
#if DEBUG
|
||
|
extern ULONG CompBattDebug;
|
||
|
|
||
|
#define BattPrint(l,m) if(l & CompBattDebug) 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_ERRORS (BATT_ERROR | BATT_WARN)
|
||
|
#define BATT_MP 0x00000010
|
||
|
#define BATT_DEBUG 0x00000020
|
||
|
#define BATT_TRACE 0x00000100
|
||
|
#define BATT_DATA 0x00000200
|
||
|
|
||
|
|
||
|
//
|
||
|
// 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)
|
||
|
|
||
|
//
|
||
|
// Poll rates for when a notification alarm cannot be set
|
||
|
//
|
||
|
#define MIN_STATUS_POLL_RATE (3L * NTMIN)
|
||
|
#define MAX_STATUS_POLL_RATE (20 * NTSEC)
|
||
|
#define STATUS_VALID_TIME (2 * NTSEC)
|
||
|
|
||
|
#define MAX_HIGH_CAPACITY 0x7fffffff
|
||
|
#define MIN_LOW_CAPACITY 0x0
|
||
|
|
||
|
//
|
||
|
// Charge/Discharge policy values (in percent)
|
||
|
//
|
||
|
#define BATTERY_MIN_SAFE_CAPACITY 2 // Min we will attempt to run on
|
||
|
#define BATTERY_MAX_CHARGE_CAPACITY 90 // Max we will attempt to charge
|
||
|
|
||
|
//
|
||
|
// Cache expiration timeouts -- when the cached battery status/info expires.
|
||
|
//
|
||
|
#define CACHE_STATUS_TIMEOUT (4 * NTSEC)
|
||
|
#define CACHE_INFO_TIMEOUT (4 * NTSEC)
|
||
|
|
||
|
//
|
||
|
// Cached battery info
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
ULONG Tag;
|
||
|
ULONG Valid;
|
||
|
BATTERY_INFORMATION Info;
|
||
|
ULONGLONG InfoTimeStamp;
|
||
|
UCHAR ManufacturerNameLength;
|
||
|
UCHAR ManufacturerName[MAX_BATTERY_STRING_SIZE];
|
||
|
UCHAR DeviceNameLength;
|
||
|
UCHAR DeviceName[MAX_BATTERY_STRING_SIZE];
|
||
|
BATTERY_MANUFACTURE_DATE ManufacturerDate;
|
||
|
ULONG SerialNumber;
|
||
|
BATTERY_STATUS Status;
|
||
|
ULONGLONG StatusTimeStamp;
|
||
|
} STATIC_BAT_INFO, *PSTATIC_BAT_INFO;
|
||
|
|
||
|
|
||
|
#define VALID_TAG_DATA 0x01 // manufacturer, device, serial #
|
||
|
#define VALID_MODE 0x02
|
||
|
#define VALID_INFO 0x04
|
||
|
#define VALID_CYCLE_COUNT 0x08
|
||
|
#define VALID_SANITY_CHECK 0x10
|
||
|
|
||
|
#define VALID_TAG 0x80
|
||
|
#define VALID_NOTIFY 0x100
|
||
|
|
||
|
#define VALID_ALL 0x1F // (does not include tag)
|
||
|
|
||
|
//
|
||
|
// Locking mechanism for battery nodes so we don't delete out from under
|
||
|
// ourselves. I would just use an IO_REMOVE_LOCK, but that's NT not WDM...
|
||
|
//
|
||
|
|
||
|
typedef struct _COMPBATT_DELETE_LOCK {
|
||
|
BOOLEAN Deleted;
|
||
|
BOOLEAN Reserved [3];
|
||
|
LONG RefCount;
|
||
|
KEVENT DeleteEvent;
|
||
|
|
||
|
} COMPBATT_DELETE_LOCK, *PCOMPBATT_DELETE_LOCK;
|
||
|
|
||
|
VOID
|
||
|
CompbattInitializeDeleteLock (
|
||
|
IN PCOMPBATT_DELETE_LOCK Lock
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompbattAcquireDeleteLock (
|
||
|
IN PCOMPBATT_DELETE_LOCK Lock
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompbattReleaseDeleteLock (
|
||
|
IN PCOMPBATT_DELETE_LOCK Lock
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompbattReleaseDeleteLockAndWait (
|
||
|
IN PCOMPBATT_DELETE_LOCK Lock
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Battery node in the composite's list of batteries
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
LIST_ENTRY Batteries; // All batteries in composite
|
||
|
COMPBATT_DELETE_LOCK DeleteLock;
|
||
|
PDEVICE_OBJECT DeviceObject; // device object for the battery
|
||
|
PIRP StatusIrp; // current status irp at device
|
||
|
WORK_QUEUE_ITEM WorkItem; // Used for restarting status Irp
|
||
|
// if it is completed at DPC level
|
||
|
BOOLEAN NewBatt; // Is this a new battery on the list
|
||
|
|
||
|
|
||
|
UCHAR State;
|
||
|
BATTERY_WAIT_STATUS Wait;
|
||
|
|
||
|
union {
|
||
|
BATTERY_STATUS Status;
|
||
|
BATTERY_WAIT_STATUS Wait;
|
||
|
ULONG Tag;
|
||
|
} IrpBuffer;
|
||
|
|
||
|
//
|
||
|
// Keep some static information around so we don't have to go out to the
|
||
|
// batteries all the time.
|
||
|
//
|
||
|
|
||
|
STATIC_BAT_INFO Info;
|
||
|
|
||
|
//
|
||
|
// Symbolic link name for the battery. Since we calculate the length of this
|
||
|
// structure based on the structure size plus the length of this string, the
|
||
|
// string must be the last thing declared in the structure.
|
||
|
//
|
||
|
|
||
|
UNICODE_STRING BattName;
|
||
|
|
||
|
} COMPOSITE_ENTRY, *PCOMPOSITE_ENTRY;
|
||
|
|
||
|
|
||
|
#define CB_ST_GET_TAG 0
|
||
|
#define CB_ST_GET_STATUS 1
|
||
|
|
||
|
//
|
||
|
// Composite battery device extension
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
PVOID Class; // Class information
|
||
|
// ULONG Tag; // Current tag of composite battery
|
||
|
ULONG NextTag; // Next tag
|
||
|
|
||
|
LIST_ENTRY Batteries; // All batteries
|
||
|
FAST_MUTEX ListMutex; // List synchronization
|
||
|
|
||
|
//
|
||
|
// Keep some static information around so we don't have to go out to the
|
||
|
// batteries all the time.
|
||
|
//
|
||
|
|
||
|
STATIC_BAT_INFO Info;
|
||
|
BATTERY_WAIT_STATUS Wait;
|
||
|
|
||
|
|
||
|
PDEVICE_OBJECT LowerDevice; // PDO
|
||
|
PDEVICE_OBJECT DeviceObject; // Compbatt Device
|
||
|
PVOID NotificationEntry; // PnP registration handle
|
||
|
} COMPOSITE_BATTERY, *PCOMPOSITE_BATTERY;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Prototypes
|
||
|
//
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry (
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattIoctl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattSystemControl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattQueryTag (
|
||
|
IN PVOID Context,
|
||
|
OUT PULONG BatteryTag
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattQueryInformation (
|
||
|
IN PVOID Context,
|
||
|
IN ULONG BatteryTag,
|
||
|
IN BATTERY_QUERY_INFORMATION_LEVEL Level,
|
||
|
IN LONG AtRate,
|
||
|
OUT PVOID Buffer,
|
||
|
IN ULONG BufferLength,
|
||
|
OUT PULONG ReturnedLength
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattQueryStatus (
|
||
|
IN PVOID Context,
|
||
|
IN ULONG BatteryTag,
|
||
|
OUT PBATTERY_STATUS BatteryStatus
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattSetStatusNotify (
|
||
|
IN PVOID Context,
|
||
|
IN ULONG BatteryTag,
|
||
|
IN PBATTERY_NOTIFY BatteryNotify
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattDisableStatusNotify (
|
||
|
IN PVOID Context
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattDriverEntry (
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattGetBatteryInformation (
|
||
|
IN PBATTERY_INFORMATION TotalBattInfo,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattGetBatteryGranularity (
|
||
|
IN PBATTERY_REPORTING_SCALE GranularityBuffer,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattPrivateIoctl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattGetEstimatedTime (
|
||
|
IN PULONG TimeBuffer,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattAddDevice (
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PDEVICE_OBJECT PDO
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattPowerDispatch(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattPnpDispatch(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompBattUnload(
|
||
|
IN PDRIVER_OBJECT DriverObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattOpenClose(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
BatteryIoctl(
|
||
|
IN ULONG Ioctl,
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PVOID InputBuffer,
|
||
|
IN ULONG InputBufferLength,
|
||
|
IN PVOID OutputBuffer,
|
||
|
IN ULONG OutputBufferLength,
|
||
|
IN BOOLEAN PrivateIoctl
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattPnpEventHandler(
|
||
|
IN PVOID NotificationStructure,
|
||
|
IN PVOID Context
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattAddNewBattery(
|
||
|
IN PUNICODE_STRING SymbolicLinkName,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattRemoveBattery(
|
||
|
IN PUNICODE_STRING SymbolicLinkName,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
IsBatteryAlreadyOnList(
|
||
|
IN PUNICODE_STRING SymbolicLinkName,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
PCOMPOSITE_ENTRY
|
||
|
RemoveBatteryFromList(
|
||
|
IN PUNICODE_STRING SymbolicLinkName,
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattGetBatteries(
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
CompBattVerifyStaticInfo (
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
VOID CompBattMonitorIrpCompleteWorker (
|
||
|
IN PVOID Context
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattMonitorIrpComplete (
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN PVOID Context
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompBattRecalculateTag (
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompBattChargeDischarge (
|
||
|
IN PCOMPOSITE_BATTERY CompBatt
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
CompBattGetDeviceObjectPointer(
|
||
|
IN PUNICODE_STRING ObjectName,
|
||
|
IN ACCESS_MASK DesiredAccess,
|
||
|
OUT PFILE_OBJECT *FileObject,
|
||
|
OUT PDEVICE_OBJECT *DeviceObject
|
||
|
);
|
||
|
|