1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#include "fastfetch.h"
#include "common/sysctl.h"
#include "common/io.h"
#include "battery.h"
#include <dev/acpica/acpiio.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <unistd.h>
const char* ffDetectBattery(FF_A_UNUSED FFBatteryOptions* options, FFlist* results) {
// https://www.freebsd.org/cgi/man.cgi?acpi_battery(4)
// https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c
int units = ffSysctlGetInt("hw.acpi.battery.units", -100);
if (units < 0) {
return "sysctlbyname(\"hw.acpi.battery.units\") failed";
}
if (units == 0) {
return NULL;
}
FF_AUTO_CLOSE_FD int acpifd = open("/dev/acpi", O_RDONLY | O_CLOEXEC);
if (acpifd < 0) {
return "open(\"/dev/acpi\", O_RDONLY | O_CLOEXEC) failed";
}
for (int i = 0; i < units; ++i) {
union acpi_battery_ioctl_arg battio;
battio.unit = i;
if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT)) {
continue;
}
FFBatteryResult* battery = FF_LIST_ADD(FFBatteryResult, *results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
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) {
battery->status |= FF_BATTERY_STATUS_UNKNOWN;
} else {
if (battio.battinfo.state & ACPI_BATT_STAT_DISCHARG) {
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) {
battery->status |= FF_BATTERY_STATUS_CRITICAL;
}
}
int acadStatus;
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus) {
battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
}
#ifdef ACPIIO_BATT_GET_BIX
battio.unit = i;
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) >= 0) {
ffStrbufAppendS(&battery->manufacturer, battio.bix.oeminfo);
ffStrbufAppendS(&battery->modelName, battio.bix.model);
ffStrbufAppendS(&battery->technology, battio.bix.type);
ffStrbufAppendS(&battery->serial, battio.bix.serial);
battery->cycleCount = battio.bix.cycles;
}
#elif defined(ACPIIO_BATT_GET_BIF)
battio.unit = i;
if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) >= 0) {
ffStrbufAppendS(&battery->manufacturer, battio.bif.oeminfo);
ffStrbufAppendS(&battery->modelName, battio.bif.model);
ffStrbufAppendS(&battery->technology, battio.bif.type);
ffStrbufAppendS(&battery->serial, battio.bif.serial);
}
#endif
}
return NULL;
}
|