#define BATTERYCLASS 1 #ifndef FAR #define FAR #endif #include #include #include #include // // 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 );