Battery: refactors status field from string to bit-fields

This commit is contained in:
Carter Li
2026-04-09 16:21:36 +08:00
committed by 李通洲
parent f6a363f7ad
commit b3603391eb
10 changed files with 179 additions and 124 deletions
+12 -1
View File
@@ -5,13 +5,24 @@
#define FF_BATTERY_TEMP_UNSET (-DBL_MAX)
typedef enum FFBatteryStatus {
FF_BATTERY_STATUS_NONE = 0,
FF_BATTERY_STATUS_UNKNOWN = 1 << 0,
FF_BATTERY_STATUS_AC_CONNECTED = 1 << 1,
FF_BATTERY_STATUS_USB_CONNECTED = 1 << 2,
FF_BATTERY_STATUS_WIRELESS_CONNECTED = 1 << 3,
FF_BATTERY_STATUS_CHARGING = 1 << 4,
FF_BATTERY_STATUS_DISCHARGING = 1 << 5,
FF_BATTERY_STATUS_CRITICAL = 1 << 6,
} FFBatteryStatus;
typedef struct FFBatteryResult {
FFstrbuf manufacturer;
FFstrbuf manufactureDate;
FFstrbuf modelName;
FFstrbuf technology;
FFstrbuf status;
FFstrbuf serial;
FFBatteryStatus status;
double capacity;
double temperature;
uint32_t cycleCount;
+10 -18
View File
@@ -35,9 +35,9 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) {
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
battery->timeRemaining = -1;
battery->status = FF_BATTERY_STATUS_NONE;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
@@ -46,23 +46,21 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) {
const char* acStatus = yyjson_get_str(yyjson_obj_get(root, "plugged"));
if (acStatus) {
if (ffStrEquals(acStatus, "PLUGGED_AC")) {
ffStrbufAppendS(&battery->status, "AC Connected, ");
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
} else if (ffStrEquals(acStatus, "PLUGGED_USB")) {
ffStrbufAppendS(&battery->status, "USB Connected, ");
battery->status |= FF_BATTERY_STATUS_USB_CONNECTED;
} else if (ffStrEquals(acStatus, "PLUGGED_WIRELESS")) {
ffStrbufAppendS(&battery->status, "Wireless Connected, ");
battery->status |= FF_BATTERY_STATUS_WIRELESS_CONNECTED;
}
}
const char* status = yyjson_get_str(yyjson_obj_get(root, "status"));
if (status) {
if (ffStrEquals(status, "CHARGING")) {
ffStrbufAppendS(&battery->status, "Charging");
battery->status |= FF_BATTERY_STATUS_CHARGING;
} else if (ffStrEquals(status, "DISCHARGING")) {
ffStrbufAppendS(&battery->status, "Discharging");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
if (options->temp) {
battery->temperature = yyjson_get_num(yyjson_obj_get(root, "temperature"));
@@ -99,31 +97,25 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) {
battery->cycleCount = 0;
battery->timeRemaining = -1;
battery->capacity = 0;
battery->status = FF_BATTERY_STATUS_NONE;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
ffStrbufAppendS(&battery->status, "AC powered");
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
ffStrbufClear(&temp);
if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
ffStrbufAppendS(&battery->status, "USB powered");
battery->status |= FF_BATTERY_STATUS_USB_CONNECTED;
}
ffStrbufClear(&temp);
if (ffParsePropLines(start, "Wireless powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
ffStrbufAppendS(&battery->status, "Wireless powered");
battery->status |= FF_BATTERY_STATUS_WIRELESS_CONNECTED;
}
ffStrbufClear(&temp);
+7 -7
View File
@@ -38,9 +38,11 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->manufactureDate);
battery->status = FF_BATTERY_STATUS_NONE;
battery->capacity = currentCapacity * 100.0 / maxCapacity;
battery->cycleCount = 0;
battery->timeRemaining = -1;
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
@@ -63,9 +65,9 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
battery->timeRemaining = -1;
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) == NULL) {
if (boolValue) {
ffStrbufAppendS(&battery->status, "AC connected, ");
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
} else {
ffStrbufAppendS(&battery->status, "Discharging, ");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
ffCfDictGetInt(properties, CFSTR("AvgTimeToEmpty"), &battery->timeRemaining); // in minutes
if (battery->timeRemaining < 0 || battery->timeRemaining >= 0xFFFF) {
battery->timeRemaining = -1;
@@ -75,13 +77,11 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
}
}
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) == NULL && boolValue) {
ffStrbufAppendS(&battery->status, "Charging, ");
battery->status |= FF_BATTERY_STATUS_CHARGING;
}
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) == NULL && boolValue) {
ffStrbufAppendS(&battery->status, "Critical, ");
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
int sbdsManufactureDate = 0;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL) {
+8 -10
View File
@@ -39,34 +39,32 @@ const char* ffDetectBattery(FF_A_UNUSED FFBatteryOptions* options, FFlist* resul
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->status = FF_BATTERY_STATUS_NONE;
battery->timeRemaining = -1;
if (battio.battinfo.min > 0) {
battery->timeRemaining = battio.battinfo.min * 60;
}
battery->capacity = battio.battinfo.cap;
if (battio.battinfo.state == ACPI_BATT_STAT_INVALID) {
ffStrbufAppendS(&battery->status, "Unknown, ");
battery->status |= FF_BATTERY_STATUS_UNKNOWN;
} else {
if (battio.battinfo.state & ACPI_BATT_STAT_DISCHARG) {
ffStrbufAppendS(&battery->status, "Discharging, ");
} else if (battio.battinfo.state & ACPI_BATT_STAT_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
if (battio.battinfo.state & ACPI_BATT_STAT_CHARGING) {
battery->status |= FF_BATTERY_STATUS_CHARGING;
}
if (battio.battinfo.state & ACPI_BATT_STAT_CRITICAL) {
ffStrbufAppendS(&battery->status, "Critical, ");
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
}
int acadStatus;
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus) {
ffStrbufAppendS(&battery->status, "AC Connected");
} else {
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
#ifdef ACPIIO_BATT_GET_BIX
+6 -8
View File
@@ -30,27 +30,25 @@ const char* parseBattery(int dfd, const char* battId, FFlist* results) {
ffStrbufInitS(&battery->manufacturer, extended.oem_info);
ffStrbufInit(&battery->manufactureDate);
ffStrbufInitS(&battery->technology, extended.type); // extended.technology?
ffStrbufInit(&battery->status);
ffStrbufInitS(&battery->serial, extended.serial_number);
battery->status = FF_BATTERY_STATUS_NONE;
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = extended.cycles;
battery->timeRemaining = -1;
battery->capacity = (double) basic.capacity * 100. / (double) extended.last_full_charge;
if (basic.state & BATTERY_DISCHARGING) {
ffStrbufAppendS(&battery->status, "Discharging, ");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
if (basic.state & BATTERY_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
battery->status |= FF_BATTERY_STATUS_CHARGING;
}
if (basic.state & BATTERY_CRITICAL_STATE) {
ffStrbufAppendS(&battery->status, "Critical, ");
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
if (basic.state & BATTERY_NOT_CHARGING) {
ffStrbufAppendS(&battery->status, "AC Connected, ");
if (basic.state & BATTERY_NOT_CHARGING || basic.state & BATTERY_CHARGING) {
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
return NULL;
}
+20 -25
View File
@@ -64,9 +64,9 @@ static bool parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
ffStrbufInit(&result->manufacturer);
ffStrbufInit(&result->modelName);
ffStrbufInit(&result->technology);
ffStrbufInit(&result->status);
ffStrbufInit(&result->serial);
ffStrbufInit(&result->manufactureDate);
result->status = FF_BATTERY_STATUS_NONE;
result->capacity = ffStrbufToDouble(&tmpBuffer, 0);
result->cycleCount = 0;
result->temperature = FF_BATTERY_TEMP_UNSET;
@@ -88,21 +88,23 @@ static bool parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
ffStrbufTrimRightSpace(&result->technology);
}
if (ffReadFileBufferRelative(dfd, "status", &result->status)) {
ffStrbufTrimRightSpace(&result->status);
if (ffReadFileBufferRelative(dfd, "status", &tmpBuffer)) {
ffStrbufTrimRightSpace(&tmpBuffer);
}
// Unknown, Charging, Discharging, Not charging, Full
if (ffStrbufEqualS(&result->status, "Discharging")) {
if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &tmpBuffer)) {
result->timeRemaining = (int32_t) ffStrbufToSInt(&tmpBuffer, 0);
if (ffStrbufEqualS(&tmpBuffer, "Discharging")) {
result->status |= FF_BATTERY_STATUS_DISCHARGING;
FF_STRBUF_AUTO_DESTROY now = ffStrbufCreate();
if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &now)) {
result->timeRemaining = (int32_t) ffStrbufToSInt(&now, 0);
} else {
if (ffReadFileBufferRelative(dfd, "charge_now", &tmpBuffer)) {
int64_t chargeNow = ffStrbufToSInt(&tmpBuffer, 0);
if (ffReadFileBufferRelative(dfd, "charge_now", &now)) {
int64_t chargeNow = ffStrbufToSInt(&now, 0);
if (chargeNow > 0) {
if (ffReadFileBufferRelative(dfd, "current_now", &tmpBuffer)) {
int64_t currentNow = ffStrbufToSInt(&tmpBuffer, INT64_MIN);
if (ffReadFileBufferRelative(dfd, "current_now", &now)) {
int64_t currentNow = ffStrbufToSInt(&now, INT64_MIN);
if (currentNow < 0) {
currentNow = -currentNow;
}
@@ -113,19 +115,16 @@ static bool parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
}
}
}
} else if (ffStrbufEqualS(&result->status, "Not charging") ||
ffStrbufEqualS(&result->status, "Full")) {
ffStrbufClear(&result->status);
} else if (ffStrbufEqualS(&tmpBuffer, "Charging")) {
result->status |= FF_BATTERY_STATUS_CHARGING;
} else if (ffStrbufEqualS(&tmpBuffer, "Unknown")) {
result->status |= FF_BATTERY_STATUS_UNKNOWN;
}
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer)) {
ffStrbufTrimRightSpace(&tmpBuffer);
if (ffStrbufEqualS(&tmpBuffer, "Critical")) {
if (result->status.length) {
ffStrbufAppendS(&result->status, ", Critical");
} else {
ffStrbufSetStatic(&result->status, "Critical");
}
result->status |= FF_BATTERY_STATUS_CRITICAL;
}
}
@@ -164,8 +163,8 @@ static bool parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
}
}
FF_DEBUG("Battery \"%s\": Capacity: %.2f%%, Status: \"%s\", Time Remaining: %d seconds, Temperature: %.1f°C, Cycle Count: %u",
id, result->capacity, result->status.chars, result->timeRemaining, result->temperature, result->cycleCount);
FF_DEBUG("Battery \"%s\": Capacity: %.2f%%, Status: \"%x\", Time Remaining: %d seconds, Temperature: %.1f°C, Cycle Count: %u",
id, result->capacity, result->status, result->timeRemaining, result->temperature, result->cycleCount);
return true;
}
@@ -191,11 +190,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
if (acConnected) {
FF_LIST_FOR_EACH(FFBatteryResult, batt, *results) {
if (batt->status.length) {
ffStrbufAppendS(&batt->status, ", AC Connected");
} else {
ffStrbufSetStatic(&batt->status, "AC Connected");
}
batt->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
}
+5 -7
View File
@@ -79,27 +79,25 @@ const char* ffDetectBattery(FF_A_UNUSED FFBatteryOptions* options, FFlist* resul
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->status = FF_BATTERY_STATUS_NONE;
battery->timeRemaining = -1;
battery->capacity = (double) curr / (double) max * 100.;
if (charging) {
ffStrbufAppendS(&battery->status, "Charging, ");
battery->status |= FF_BATTERY_STATUS_CHARGING;
} else if (dischargeRate) {
ffStrbufAppendS(&battery->status, "Discharging, ");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
battery->timeRemaining = (int32_t) ((double) curr / dischargeRate * 3600);
}
if (critical) {
ffStrbufAppendS(&battery->status, "Critical, ");
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
if (acConnected) {
ffStrbufAppendS(&battery->status, "AC Connected");
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
prop_object_iterator_release(iter);
+7 -12
View File
@@ -30,33 +30,28 @@ const char* ffDetectBattery(FF_A_UNUSED FFBatteryOptions* options, FFlist* resul
battery->capacity = info.battery_life;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->status = FF_BATTERY_STATUS_NONE;
if (info.ac_state == APM_AC_ON) {
ffStrbufAppendS(&battery->status, "AC Connected");
} else if (info.ac_state == APM_AC_BACKUP) {
ffStrbufAppendS(&battery->status, "Backup In Use");
if (info.ac_state == APM_AC_ON || info.ac_state == APM_AC_BACKUP) {
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
} else if (info.ac_state == APM_AC_OFF) {
battery->timeRemaining = (int) info.minutes_left * 60;
ffStrbufAppendS(&battery->status, "Discharging");
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING || info.battery_state == APM_BATT_UNKNOWN) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
switch (info.battery_state) {
case APM_BATT_UNKNOWN:
ffStrbufAppendS(&battery->status, "Unknown");
battery->status |= FF_BATTERY_STATUS_UNKNOWN;
break;
case APM_BATT_CHARGING:
ffStrbufAppendS(&battery->status, "Charging");
battery->status |= FF_BATTERY_STATUS_CHARGING;
break;
case APM_BATT_CRITICAL:
ffStrbufAppendS(&battery->status, "Critical");
battery->status |= FF_BATTERY_STATUS_CRITICAL;
break;
}
}
+28 -24
View File
@@ -141,25 +141,24 @@ static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results) {
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 && bi.FullChargedCapacity != 0) {
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
battery->status = FF_BATTERY_STATUS_NONE;
if (bs.PowerState & BATTERY_POWER_ON_LINE) {
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
if (bs.PowerState & BATTERY_DISCHARGING) {
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
if (bs.PowerState & BATTERY_CHARGING) {
battery->status |= FF_BATTERY_STATUS_CHARGING;
}
if (bs.PowerState & BATTERY_CRITICAL) {
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
} else {
battery->status = FF_BATTERY_STATUS_UNKNOWN;
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_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
}
if (bs.PowerState & BATTERY_CRITICAL) {
ffStrbufAppendS(&battery->status, "Critical, ");
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
return NULL;
@@ -258,26 +257,31 @@ static const char* detectBySmbios(FFBatteryResult* battery) {
static const char* detectWithNtApi(FF_A_UNUSED FFBatteryOptions* options, FFlist* results) {
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) {
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) &&
info.BatteryPresent) {
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->manufactureDate);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->serial);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
battery->timeRemaining = info.EstimatedTime == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) info.EstimatedTime;
battery->status = FF_BATTERY_STATUS_NONE;
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if (info.AcOnLine) {
ffStrbufAppendS(&battery->status, "AC Connected");
if (info.Charging) {
ffStrbufAppendS(&battery->status, ", Charging");
}
} else if (info.Discharging) {
ffStrbufAppendS(&battery->status, "Discharging");
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
if (info.Charging) {
battery->status |= FF_BATTERY_STATUS_CHARGING;
}
if (info.Discharging) {
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
}
if (info.DefaultAlert1 > 0 && info.RemainingCapacity <= info.DefaultAlert1) {
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
detectBySmbios(battery);