[CMBATT]: Implement CmBattQueryInformation and CmBattQueryStatus.
authorSir Richard <sir_richard@svn.reactos.org>
Sat, 20 Mar 2010 21:25:40 +0000 (21:25 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sat, 20 Mar 2010 21:25:40 +0000 (21:25 +0000)
svn path=/trunk/; revision=46288

reactos/drivers/bus/acpi/cmbatt/cmbatt.c
reactos/drivers/bus/acpi/cmbatt/cmbatt.h

index b8c5973..4ff43f3 100644 (file)
@@ -74,7 +74,7 @@ CmBattUnload(IN PDRIVER_OBJECT DriverObject)
 
 NTSTATUS
 NTAPI
 
 NTSTATUS
 NTAPI
-CmBattVerifyStaticInfo(ULONG StaData,
+CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension,
                        ULONG BatteryTag)
 {
     UNIMPLEMENTED;
                        ULONG BatteryTag)
 {
     UNIMPLEMENTED;
@@ -191,26 +191,246 @@ CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
 
 NTSTATUS
 NTAPI
 
 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
 }
 
 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
 }
 
 NTSTATUS
@@ -233,20 +453,16 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
     {
         /* Fail if we're out of memory this early */
         if (CmBattDebug & CMBATT_GENERIC_WARNING)
     {
         /* Fail if we're out of memory this early */
         if (CmBattDebug & CMBATT_GENERIC_WARNING)
-        {
             DbgPrint("CmBatt: Couldn't allocate pool for registry path.");
             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)
         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);
         DbgPrint("CmBatt DriverEntry - Obj (%08x) Path \"%ws\"\n",
                  DriverObject,
                  RegistryPath->Buffer);
-    }
     
     /* Setup the major dispatchers */
     DriverObject->MajorFunction[0] = CmBattOpenClose;
     
     /* 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)
         /* No callback, fail */
         CmBattPowerCallBackObject = 0;
         if (CmBattDebug & CMBATT_GENERIC_WARNING)
-        {
             DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status);
             DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status);
-        }
     }
     else
     {
     }
     else
     {
@@ -296,9 +510,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
         {
             ObfDereferenceObject(CmBattPowerCallBackObject);
             if (CmBattDebug & CMBATT_GENERIC_WARNING)
         {
             ObfDereferenceObject(CmBattPowerCallBackObject);
             if (CmBattDebug & CMBATT_GENERIC_WARNING)
-            {
                 DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
                 DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
-            }
         }
         
         /* All good */
         }
         
         /* All good */
index f3583f8..913f785 100644 (file)
@@ -29,6 +29,12 @@ typedef enum _CMBATT_EXTENSION_TYPE
     CmBattBattery
 } 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;
 typedef struct _ACPI_BST_DATA
 {
     ULONG State;
@@ -93,7 +99,7 @@ typedef struct _CMBATT_DEVICE_EXTENSION
     ULONG RemainingCapacity;
     ULONG PresentVoltage;
     ULONG Rate;
     ULONG RemainingCapacity;
     ULONG PresentVoltage;
     ULONG Rate;
-    BATTERY_INFORMATION StaticBatteryInformation;
+    BATTERY_INFORMATION BatteryInformation;
     ULONG BatteryCapacityGranularity1;
     ULONG BatteryCapacityGranularity2;
     BOOLEAN TripPointSet;
     ULONG BatteryCapacityGranularity1;
     ULONG BatteryCapacityGranularity2;
     BOOLEAN TripPointSet;