mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 16:45:50 +00:00
[CMBATT]: Implement CmBattQueryInformation and CmBattQueryStatus.
svn path=/trunk/; revision=46288
This commit is contained in:
parent
84d900acb3
commit
9f21a824cb
2 changed files with 242 additions and 24 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue