mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 10:52:08 +02:00
Battery: improve performance (Windows)
This commit is contained in:
+1
-1
@@ -421,7 +421,7 @@ elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/detection/battery/battery_windows.cpp
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "battery.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <setupapi.h>
|
||||
#include <batclass.h>
|
||||
#include <devguid.h>
|
||||
|
||||
static inline void wrapFree(SP_DEVICE_INTERFACE_DETAIL_DATA_W** ptr)
|
||||
{
|
||||
free(*ptr);
|
||||
}
|
||||
static inline void wrapCloseHandle(HANDLE* handle)
|
||||
{
|
||||
if(*handle)
|
||||
CloseHandle(*handle);
|
||||
}
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
{
|
||||
if(*hdev)
|
||||
SetupDiDestroyDeviceInfoList(*hdev);
|
||||
}
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY) failed";
|
||||
|
||||
for(DWORD idev = 0;; idev++)
|
||||
{
|
||||
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||
if(!SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did))
|
||||
break;
|
||||
|
||||
DWORD cbRequired = 0;
|
||||
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_W* __attribute__((__cleanup__(wrapFree))) pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||
if(!pdidd)
|
||||
break; //Out of memory
|
||||
|
||||
pdidd->cbSize = sizeof(*pdidd);
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
|
||||
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
|
||||
|
||||
DWORD dwWait = 0;
|
||||
DWORD dwOut;
|
||||
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
|
||||
continue;
|
||||
|
||||
BATTERY_INFORMATION bi = {0};
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
|
||||
continue;
|
||||
|
||||
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
|
||||
continue;
|
||||
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
|
||||
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lithium Ion");
|
||||
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
|
||||
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
|
||||
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Zinc");
|
||||
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||
else
|
||||
ffStrbufInitS(&battery->technology, "Unknown");
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->modelName);
|
||||
bqi.InformationLevel = BatteryDeviceName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffWcharToUtf8(name, &battery->modelName);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
bqi.InformationLevel = BatteryManufactureName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffWcharToUtf8(name, &battery->manufacturer);
|
||||
}
|
||||
|
||||
battery->temperature = 0.0/0.0;
|
||||
if(instance->config.batteryTemp)
|
||||
{
|
||||
bqi.InformationLevel = BatteryTemperature;
|
||||
ULONG temp;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
|
||||
battery->temperature = temp;
|
||||
}
|
||||
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||
else
|
||||
battery->capacity = 0;
|
||||
|
||||
ffStrbufInit(&battery->status);
|
||||
if(bs.PowerState & BATTERY_POWER_ON_LINE)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
if(bs.PowerState & BATTERY_DISCHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if(bs.PowerState & BATTERY_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
if(bs.PowerState & BATTERY_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
extern "C" {
|
||||
#include "battery.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery
|
||||
FFWmiQuery query(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery");
|
||||
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
while(FFWmiRecord record = query.next())
|
||||
{
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
record.getString(L"SystemName", &battery->manufacturer);
|
||||
|
||||
ffStrbufInit(&battery->modelName);
|
||||
record.getString(L"Name", &battery->modelName);
|
||||
|
||||
uint64_t chemistry = 0;
|
||||
record.getUnsigned(L"Chemistry", &chemistry);
|
||||
switch(chemistry)
|
||||
{
|
||||
case 1: ffStrbufInitS(&battery->technology, "Other"); break;
|
||||
case 2: ffStrbufInitS(&battery->technology, "Unknown"); break;
|
||||
case 3: ffStrbufInitS(&battery->technology, "Lead Acid"); break;
|
||||
case 4: ffStrbufInitS(&battery->technology, "Nickel Cadmium"); break;
|
||||
case 5: ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); break;
|
||||
case 6: ffStrbufInitS(&battery->technology, "Lithium-ion"); break;
|
||||
case 7: ffStrbufInitS(&battery->technology, "Zinc air"); break;
|
||||
case 8: ffStrbufInitS(&battery->technology, "Lithium Polymer"); break;
|
||||
default: ffStrbufInit(&battery->technology); break;
|
||||
}
|
||||
|
||||
record.getReal(L"EstimatedChargeRemaining", &battery->capacity);
|
||||
|
||||
uint64_t batteryStatus;
|
||||
record.getUnsigned(L"BatteryStatus", &batteryStatus);
|
||||
switch(batteryStatus)
|
||||
{
|
||||
case 1: ffStrbufInitS(&battery->status, "Discharging"); break;
|
||||
case 2: ffStrbufInitS(&battery->status, "AC Connected"); break;
|
||||
case 3: ffStrbufInitS(&battery->status, "Fully Charged"); break;
|
||||
case 4: ffStrbufInitS(&battery->status, "Low"); break;
|
||||
case 5: ffStrbufInitS(&battery->status, "Critical"); break;
|
||||
case 6: ffStrbufInitS(&battery->status, "Charging"); break;
|
||||
case 7: ffStrbufInitS(&battery->status, "Charging and High"); break;
|
||||
case 8: ffStrbufInitS(&battery->status, "Charging and Low"); break;
|
||||
case 9: ffStrbufInitS(&battery->status, "Charging and Critical"); break;
|
||||
case 10: ffStrbufInitS(&battery->status, "Undefined"); break;
|
||||
case 11: ffStrbufInitS(&battery->status, "Partially Charged"); break;
|
||||
default: ffStrbufInit(&battery->status); break;
|
||||
}
|
||||
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user