diff options
Diffstat (limited to 'src/detection/battery/battery_bsd.c')
| -rw-r--r-- | src/detection/battery/battery_bsd.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c new file mode 100644 index 0000000..336a17e --- /dev/null +++ b/src/detection/battery/battery_bsd.c @@ -0,0 +1,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; +} |