NTSTATUS
NTAPI
-CmBattVerifyStaticInfo(ULONG StaData,
+CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension,
ULONG BatteryTag)
{
UNIMPLEMENTED;
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
{
/* 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;
/* No callback, fail */
CmBattPowerCallBackObject = 0;
if (CmBattDebug & CMBATT_GENERIC_WARNING)
- {
DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status);
- }
}
else
{
{
ObfDereferenceObject(CmBattPowerCallBackObject);
if (CmBattDebug & CMBATT_GENERIC_WARNING)
- {
DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
- }
}
/* All good */