summaryrefslogtreecommitdiffstats
path: root/src/detection/battery/battery_bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/battery/battery_bsd.c')
-rw-r--r--src/detection/battery/battery_bsd.c90
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;
+}