[CMBATT]: Implement CmBattQueryInformation and CmBattQueryStatus.

svn path=/trunk/; revision=46288
This commit is contained in:
Sir Richard 2010-03-20 21:25:40 +00:00
parent 84d900acb3
commit 9f21a824cb
2 changed files with 242 additions and 24 deletions

View file

@ -74,7 +74,7 @@ CmBattUnload(IN PDRIVER_OBJECT DriverObject)
NTSTATUS
NTAPI
CmBattVerifyStaticInfo(ULONG StaData,
CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension,
ULONG BatteryTag)
{
UNIMPLEMENTED;
@ -191,26 +191,246 @@ CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
NTSTATUS
NTAPI
CmBattQueryInformation(PCMBATT_DEVICE_EXTENSION DeviceExtension,
ULONG BatteryTag,
BATTERY_QUERY_INFORMATION_LEVEL Level,
OPTIONAL LONG AtRate,
PVOID Buffer,
ULONG BufferLength,
PULONG ReturnedLength)
CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION FdoExtension,
IN ULONG Tag,
IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel,
IN OPTIONAL LONG AtRate,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnedLength)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
PVOID QueryData = NULL;
ULONG QueryLength = 0;
ULONG RemainingTime = 0;
ANSI_STRING TempString;
UNICODE_STRING TempString2;
WCHAR InfoBuffer[256];
WCHAR TempBuffer[256];
UNICODE_STRING InfoString;
ULONG RemainingCapacity;
BATTERY_REPORTING_SCALE BatteryReportingScale[2];
LONG Rate;
PAGED_CODE();
if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
DbgPrint("CmBattQueryInformation - Tag (%d) Device %d, Informationlevel %d\n",
Tag,
FdoExtension->DeviceId,
InfoLevel);
/* Check ACPI Data */
Status = CmBattVerifyStaticInfo(FdoExtension, Tag);
if (!NT_SUCCESS(Status)) return Status;
/* Check what caller wants */
switch (InfoLevel)
{
case BatteryInformation:
/* Just return our static information */
QueryData = &FdoExtension->BatteryInformation;
QueryLength = sizeof(BATTERY_INFORMATION);
break;
case BatteryGranularityInformation:
/* Return our static information, we have two scales */
BatteryReportingScale[0].Granularity = FdoExtension->BatteryCapacityGranularity1;
BatteryReportingScale[0].Capacity = FdoExtension->BatteryInformation.DefaultAlert1;
BatteryReportingScale[1].Granularity = FdoExtension->BatteryCapacityGranularity2;
BatteryReportingScale[1].Capacity = FdoExtension->BatteryInformation.DesignedCapacity;
QueryData = BatteryReportingScale;
QueryLength = sizeof(BATTERY_REPORTING_SCALE) * 2;
break;
case BatteryEstimatedTime:
/* Check if it's been more than 2 1/2 minutes since the last change */
if ((KeQueryInterruptTime() - 150000000) > (FdoExtension->InterruptTime))
{
/* Get new battery status */
CmBattGetBatteryStatus(FdoExtension, FdoExtension->Tag);
/* If the caller didn't specify a rate, use our static one */
Rate = AtRate;
if (!Rate) Rate = FdoExtension->Rate;
/* If we don't have a valid negative rate, use unknown value */
if (Rate >= 0) Rate = BATTERY_UNKNOWN_RATE;
/* Grab the remaining capacity */
RemainingCapacity = FdoExtension->RemainingCapacity;
/* See if we don't know one or the other */
if ((Rate == BATTERY_UNKNOWN_RATE) ||
(RemainingCapacity == BATTERY_UNKNOWN_CAPACITY))
{
/* If the battery is discharging, we can't give out a time */
if ((FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG) &&
(CmBattDebug & CMBATT_GENERIC_WARNING))
DbgPrint("CmBattQueryInformation: Can't calculate EstimatedTime.\n");
/* Check if we don't have a rate and capacity is going down */
if ((FdoExtension->Rate == BATTERY_UNKNOWN_RATE) &&
(FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG))
{
/* We have to fail, since we lack data */
Status = STATUS_INVALID_DEVICE_REQUEST;
if (CmBattDebug & CMBATT_GENERIC_WARNING)
DbgPrint("---------------------- PresentRate = BATTERY_UNKNOWN_RATE\n");
}
/* If we don't have capacity, the rate is useless */
if (RemainingCapacity == BATTERY_UNKNOWN_CAPACITY)
{
/* We have to fail the request */
Status = STATUS_INVALID_DEVICE_REQUEST;
if (CmBattDebug & CMBATT_GENERIC_WARNING)
DbgPrint("---------------------- RemainingCapacity = BATTERY_UNKNOWN_CAPACITY\n");
}
}
else
{
/* We have data, but is it valid? */
if (RemainingCapacity > 0x123456)
{
/* The capacity seems bogus, so don't use it */
if (CmBattDebug & CMBATT_ACPI_WARNING)
DbgPrint("CmBattQueryInformation: Data Overflow in calculating Remaining Capacity.\n");
}
else
{
/* Compute the remaining time in seconds, based on rate */
RemainingTime = (RemainingCapacity * 3600) / -Rate;
}
}
}
/* Return the remaining time */
QueryData = &RemainingTime;
QueryLength = sizeof(ULONG);
break;
case BatteryDeviceName:
/* Build the model number string */
RtlInitAnsiString(&TempString, FdoExtension->ModelNumber);
/* Convert it to Unicode */
InfoString.Buffer = InfoBuffer;
InfoString.MaximumLength = sizeof(InfoBuffer);
Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);
/* Return the unicode buffer */
QueryData = InfoString.Buffer;
QueryLength = InfoString.Length;
break;
case BatteryTemperature:
case BatteryManufactureDate:
/* We don't support these */
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
case BatteryManufactureName:
/* Build the OEM info string */
RtlInitAnsiString(&TempString, FdoExtension->OemInfo);
/* Convert it to Unicode */
InfoString.Buffer = InfoBuffer;
InfoString.MaximumLength = sizeof(InfoBuffer);
Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);
/* Return the unicode buffer */
QueryData = InfoString.Buffer;
QueryLength = InfoString.Length;
break;
case BatteryUniqueID:
/* Build the serial number string */
RtlInitAnsiString(&TempString, FdoExtension->SerialNumber);
/* Convert it to Unicode */
InfoString.Buffer = InfoBuffer;
InfoString.MaximumLength = sizeof(InfoBuffer);
RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);
/* Setup a temporary string for concatenation */
TempString2.Buffer = TempBuffer;
TempString2.MaximumLength = sizeof(TempBuffer);
/* Check if there's an OEM string */
if (FdoExtension->OemInfo[0])
{
/* Build the OEM info string */
RtlInitAnsiString(&TempString, FdoExtension->OemInfo);
/* Convert it to Unicode and append it */
RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
RtlAppendUnicodeStringToString(&InfoString, &TempString2);
}
/* Build the model number string */
RtlInitAnsiString(&TempString, FdoExtension->ModelNumber);
/* Convert it to Unicode and append it */
RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
RtlAppendUnicodeStringToString(&InfoString, &TempString2);
/* Return the final appended string */
QueryData = InfoString.Buffer;
QueryLength = InfoString.Length;
break;
default:
/* Everything else is unknown */
Status = STATUS_INVALID_PARAMETER;
break;
}
/* Return the required length and check if the caller supplied enough */
*ReturnedLength = QueryLength;
if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL;
/* Copy the data if there's enough space and it exists */
if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength);
/* Return function result */
return Status;
}
NTSTATUS
NTAPI
CmBattQueryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
ULONG BatteryTag,
PBATTERY_STATUS BatteryStatus)
CmBattQueryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
IN ULONG Tag,
IN PBATTERY_STATUS BatteryStatus)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
PAGED_CODE();
if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
DbgPrint("CmBattQueryStatus - Tag (%d) Device %x\n", Tag, DeviceExtension->DeviceId);
/* Query ACPI information */
Status = CmBattGetBatteryStatus(DeviceExtension, Tag);
if (NT_SUCCESS(Status))
{
BatteryStatus->PowerState = DeviceExtension->State;
BatteryStatus->Capacity = DeviceExtension->RemainingCapacity;
BatteryStatus->Voltage = DeviceExtension->PresentVoltage;
BatteryStatus->Rate = DeviceExtension->Rate;
}
/* Return status */
if (CmBattDebug & (CMBATT_GENERIC_INFO))
DbgPrint("CmBattQueryStatus: Returning [%#08lx][%#08lx][%#08lx][%#08lx]\n",
BatteryStatus->PowerState,
BatteryStatus->Capacity,
BatteryStatus->Voltage,
BatteryStatus->Rate);
return Status;
}
NTSTATUS
@ -233,20 +453,16 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
{
/* Fail if we're out of memory this early */
if (CmBattDebug & CMBATT_GENERIC_WARNING)
{
DbgPrint("CmBatt: Couldn't allocate pool for registry path.");
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Buffer allocated, copy the string */
RtlCopyUnicodeString(&GlobalRegistryPath, RegistryPath);
if (CmBattDebug & CMBATT_GENERIC_INFO)
{
DbgPrint("CmBatt DriverEntry - Obj (%08x) Path \"%ws\"\n",
DriverObject,
RegistryPath->Buffer);
}
/* Setup the major dispatchers */
DriverObject->MajorFunction[0] = CmBattOpenClose;
@ -276,9 +492,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
/* No callback, fail */
CmBattPowerCallBackObject = 0;
if (CmBattDebug & CMBATT_GENERIC_WARNING)
{
DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status);
}
}
else
{
@ -296,9 +510,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
{
ObfDereferenceObject(CmBattPowerCallBackObject);
if (CmBattDebug & CMBATT_GENERIC_WARNING)
{
DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
}
}
/* All good */

View file

@ -29,6 +29,12 @@ typedef enum _CMBATT_EXTENSION_TYPE
CmBattBattery
} CMBATT_EXTENSION_TYPE;
#define ACPI_BATT_STAT_DISCHARG 0x0001
#define ACPI_BATT_STAT_CHARGING 0x0002
#define ACPI_BATT_STAT_CRITICAL 0x0004
#define ACPI_BATT_STAT_NOT_PRESENT 0x0007
#define ACPI_BATT_STAT_MAX 0x0007
typedef struct _ACPI_BST_DATA
{
ULONG State;
@ -93,7 +99,7 @@ typedef struct _CMBATT_DEVICE_EXTENSION
ULONG RemainingCapacity;
ULONG PresentVoltage;
ULONG Rate;
BATTERY_INFORMATION StaticBatteryInformation;
BATTERY_INFORMATION BatteryInformation;
ULONG BatteryCapacityGranularity1;
ULONG BatteryCapacityGranularity2;
BOOLEAN TripPointSet;