master ohmu/fastfetch-openbsd / src / detection / battery / battery_haiku.c
ohmu  ·  2026-10-15
 1#include "fastfetch.h"
 2#include "battery.h"
 3#include "common/debug.h"
 4#include "common/io.h"
 5
 6#include <private/device/power_managment.h>
 7#include <sys/ioctl.h>
 8#include <fcntl.h>
 9#include <string.h>
10
11const char* parseBattery(int dfd, const char* battId, FFlist* results) {
12    FF_AUTO_CLOSE_FD int fd = openat(dfd, battId, O_RDWR);
13    if (fd < 0) {
14        FF_DEBUG("openat(%s) failed: %s", battId, strerror(errno));
15        return "openat() failed";
16    }
17
18    acpi_battery_info basic = {};
19    if (ioctl(fd, GET_BATTERY_INFO, &basic, sizeof(basic)) != 0) {
20        FF_DEBUG("ioctl(GET_BATTERY_INFO) failed");
21        return "ioctl(GET_BATTERY_INFO) failed";
22    }
23    acpi_extended_battery_info extended = {};
24    if (ioctl(fd, GET_EXTENDED_BATTERY_INFO, &extended, sizeof(extended)) != 0) {
25        FF_DEBUG("ioctl(GET_EXTENDED_BATTERY_INFO) failed");
26        return "ioctl(GET_EXTENDED_BATTERY_INFO) failed";
27    }
28
29    if (extended.last_full_charge == (uint32) -1) {
30        return "Skipped";
31    }
32
33    FFBatteryResult* battery = FF_LIST_ADD(FFBatteryResult, *results);
34    ffStrbufInitS(&battery->modelName, extended.model_number);
35    ffStrbufInitS(&battery->manufacturer, extended.oem_info);
36    ffStrbufInit(&battery->manufactureDate);
37    ffStrbufInitS(&battery->technology, extended.type); // extended.technology?
38    ffStrbufInitS(&battery->serial, extended.serial_number);
39    battery->status = FF_BATTERY_STATUS_NONE;
40    battery->temperature = FF_BATTERY_TEMP_UNSET;
41    battery->cycleCount = extended.cycles;
42    battery->timeRemaining = -1;
43    battery->capacity = (double) basic.capacity * 100. / (double) extended.last_full_charge;
44
45    if (basic.state & BATTERY_DISCHARGING) {
46        battery->status |= FF_BATTERY_STATUS_DISCHARGING;
47    }
48    if (basic.state & BATTERY_CHARGING) {
49        battery->status |= FF_BATTERY_STATUS_CHARGING;
50    }
51    if (basic.state & BATTERY_CRITICAL_STATE) {
52        battery->status |= FF_BATTERY_STATUS_CRITICAL;
53    }
54    if (basic.state & BATTERY_NOT_CHARGING || basic.state & BATTERY_CHARGING) {
55        battery->status |= FF_BATTERY_STATUS_AC_CONNECTED;
56    }
57
58    return nullptr;
59}
60
61const char* ffDetectBattery([[maybe_unused]] FFBatteryOptions* options, FFlist* results) {
62    FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/power/acpi_battery/");
63    if (!dir) {
64        FF_DEBUG("opendir(\"/dev/power/acpi_battery/\") failed: %s", strerror(errno));
65        return "opendir(/dev/power/acpi_battery) failed";
66    }
67
68    struct dirent* entry;
69    while ((entry = readdir(dir))) {
70        if (entry->d_name[0] == '.') {
71            continue;
72        }
73        parseBattery(dirfd(dir), entry->d_name, results);
74    }
75
76    return nullptr;
77}