summaryrefslogtreecommitdiff
path: root/src/print_battery_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/print_battery_info.c')
-rw-r--r--src/print_battery_info.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/print_battery_info.c b/src/print_battery_info.c
new file mode 100644
index 0000000..eb1f6bb
--- /dev/null
+++ b/src/print_battery_info.c
@@ -0,0 +1,149 @@
+// vim:ts=8:expandtab
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "i3status.h"
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+/*
+ * Get battery information from /sys. Note that it uses the design capacity to
+ * calculate the percentage, not the last full capacity, so you can see how
+ * worn off your battery is.
+ *
+ */
+void print_battery_info(int number, const char *format) {
+ char buf[1024];
+ char *walk, *last;
+ int full_design = -1,
+ remaining = -1,
+ present_rate = -1;
+ charging_status_t status = CS_DISCHARGING;
+
+#if defined(LINUX)
+ static char batpath[512];
+ sprintf(batpath, "/sys/class/power_supply/BAT%d/uevent", number);
+ if (!slurp(batpath, buf, sizeof(buf))) {
+ printf("No battery");
+ return;
+ }
+
+ for (walk = buf, last = buf; (walk-buf) < 1024; walk++) {
+ if (*walk == '\n') {
+ last = walk+1;
+ continue;
+ }
+
+ if (*walk != '=')
+ continue;
+
+ if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") ||
+ BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW"))
+ remaining = atoi(walk+1);
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW"))
+ present_rate = atoi(walk+1);
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging"))
+ status = CS_CHARGING;
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full"))
+ status = CS_FULL;
+ else {
+ /* The only thing left is the full capacity */
+#if 0
+ if (bat->use_last_full) {
+ if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
+ !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
+ continue;
+ } else {
+#endif
+ if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
+ !BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
+ continue;
+ //}
+
+ full_design = atoi(walk+1);
+ }
+ }
+
+ if ((full_design == 1) || (remaining == -1))
+ return;
+
+ if (present_rate > 0) {
+ float remaining_time;
+ int seconds, hours, minutes;
+ if (status == CS_CHARGING)
+ remaining_time = ((float)full_design - (float)remaining) / (float)present_rate;
+ else if (status == CS_DISCHARGING)
+ remaining_time = ((float)remaining / (float)present_rate);
+ else remaining_time = 0;
+
+ seconds = (int)(remaining_time * 3600.0);
+ hours = seconds / 3600;
+ seconds -= (hours * 3600);
+ minutes = seconds / 60;
+ seconds -= (minutes * 60);
+
+ (void)printf("%s %.02f%% %02d:%02d:%02d",
+ (status == CS_CHARGING ? "CHR" :
+ (status == CS_DISCHARGING ? "BAT" : "FULL")),
+ (((float)remaining / (float)full_design) * 100),
+ max(hours, 0), max(minutes, 0), max(seconds, 0));
+ } else {
+ (void)printf("%s %.02f%%",
+ (status == CS_CHARGING ? "CHR" :
+ (status == CS_DISCHARGING ? "BAT" : "FULL")),
+ (((float)remaining / (float)full_design) * 100));
+ }
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ int state;
+ int sysctl_rslt;
+ size_t sysctl_size = sizeof(sysctl_rslt);
+
+ if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
+ printf("No battery");
+ return;
+ }
+
+ present_rate = sysctl_rslt;
+ if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
+ printf("No battery");
+ return;
+ }
+
+ remaining = sysctl_rslt;
+ if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) {
+ printf("No battery");
+ return;
+ }
+
+ state = sysctl_rslt;
+ if (state == 0 && present_rate == 100)
+ status = CS_FULL;
+ else if (state == 0 && present_rate < 100)
+ status = CS_CHARGING;
+ else
+ status = CS_DISCHARGING;
+
+ full_design = sysctl_rslt;
+
+ if (state == 1) {
+ int hours, minutes;
+ minutes = remaining;
+ hours = minutes / 60;
+ minutes -= (hours * 60);
+ (void)printf("%s %02d%% %02dh%02d",
+ (status == CS_CHARGING ? "CHR" :
+ (status == CS_DISCHARGING ? "BAT" : "FULL")),
+ present_rate,
+ max(hours, 0), max(minutes, 0));
+ } else {
+ (void)printf("%s %02d%%",
+ (status == CS_CHARGING ? "CHR" :
+ (status == CS_DISCHARGING ? "BAT" : "FULL")),
+ present_rate);
+ }
+#endif
+}