summaryrefslogtreecommitdiffstats
path: root/src/detection/battery/battery_nbsd.c
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/battery/battery_nbsd.c
Add the files
Diffstat (limited to 'src/detection/battery/battery_nbsd.c')
-rw-r--r--src/detection/battery/battery_nbsd.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/detection/battery/battery_nbsd.c b/src/detection/battery/battery_nbsd.c
new file mode 100644
index 0000000..2e8b426
--- /dev/null
+++ b/src/detection/battery/battery_nbsd.c
@@ -0,0 +1,109 @@
+#include "battery.h"
+#include "common/io.h"
+#include "common/FFstrbuf.h"
+#include "common/strutil.h"
+
+#include <prop/prop_array.h>
+#include <prop/prop_bool.h>
+#include <prop/prop_dictionary.h>
+#include <prop/prop_object.h>
+#include <sys/envsys.h>
+#include <prop/proplib.h>
+#include <paths.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+const char* ffDetectBattery(FF_A_UNUSED FFBatteryOptions* options, FFlist* results) {
+ FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
+ }
+
+ prop_dictionary_t root = NULL;
+ if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0) {
+ return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
+ }
+
+ bool acConnected = false;
+ {
+ prop_array_t acad = prop_dictionary_get(root, "acpiacad0");
+ if (acad) {
+ prop_dictionary_t dict = prop_array_get(acad, 0);
+ prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &acConnected);
+ }
+ }
+
+ prop_object_iterator_t itKey = prop_dictionary_iterator(root);
+ for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL;) {
+ if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) {
+ continue;
+ }
+
+ prop_array_t bat = prop_dictionary_get_keysym(root, key);
+ uint32_t max = 0, curr = 0, dischargeRate = 0;
+ bool charging = false, critical = false;
+ prop_object_iterator_t iter = prop_array_iterator(bat);
+ for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;) {
+ if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) {
+ continue;
+ }
+
+ const char* desc = NULL;
+ if (!prop_dictionary_get_string(dict, "description", &desc)) {
+ continue;
+ }
+
+ if (ffStrEquals(desc, "present")) {
+ int value = 0;
+ if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0) {
+ continue;
+ }
+ } else if (ffStrEquals(desc, "charging")) {
+ prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &charging);
+ } else if (ffStrEquals(desc, "charge")) {
+ prop_dictionary_get_uint32(dict, "max-value", &max);
+ prop_dictionary_get_uint32(dict, "cur-value", &curr);
+ const char* state = NULL;
+ if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical")) {
+ critical = true;
+ }
+ } else if (ffStrEquals(desc, "discharge rate")) {
+ prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
+ }
+ }
+
+ if (max > 0) {
+ 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;
+
+ battery->capacity = (double) curr / (double) max * 100.;
+ if (charging) {
+ battery->status |= FF_BATTERY_STATUS_CHARGING;
+ } else if (dischargeRate) {
+ battery->status |= FF_BATTERY_STATUS_DISCHARGING;
+ battery->timeRemaining = (int32_t) ((double) curr / dischargeRate * 3600);
+ }
+ if (critical) {
+ battery->status |= FF_BATTERY_STATUS_CRITICAL;
+ }
+ if (acConnected) {
+ battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
+ }
+ }
+
+ prop_object_iterator_release(iter);
+ }
+ prop_object_iterator_release(itKey);
+ prop_object_release(root);
+
+ return NULL;
+}