2009-07-21 18:26:53 +00:00
|
|
|
// vim:ts=8:expandtab
|
2009-07-21 17:07:30 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "i3status.h"
|
|
|
|
|
2009-08-31 17:34:57 +00:00
|
|
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
2009-07-23 16:40:49 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#endif
|
|
|
|
|
2009-07-21 17:07:30 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2009-10-16 18:37:41 +00:00
|
|
|
void print_battery_info(int number, const char *format, bool last_full_capacity) {
|
2009-07-21 17:07:30 +00:00
|
|
|
char buf[1024];
|
|
|
|
char *walk, *last;
|
|
|
|
int full_design = -1,
|
|
|
|
remaining = -1,
|
|
|
|
present_rate = -1;
|
|
|
|
charging_status_t status = CS_DISCHARGING;
|
|
|
|
|
2009-07-23 16:40:49 +00:00
|
|
|
#if defined(LINUX)
|
2009-10-11 20:11:09 +00:00
|
|
|
static char batpath[512];
|
|
|
|
sprintf(batpath, "/sys/class/power_supply/BAT%d/uevent", number);
|
|
|
|
if (!slurp(batpath, buf, sizeof(buf))) {
|
|
|
|
printf("No battery");
|
|
|
|
return;
|
|
|
|
}
|
2009-07-21 17:07:30 +00:00
|
|
|
|
|
|
|
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 */
|
2009-10-16 18:37:41 +00:00
|
|
|
if (last_full_capacity) {
|
2009-07-21 17:07:30 +00:00
|
|
|
if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
|
|
|
|
!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
|
|
|
|
!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
|
|
|
|
continue;
|
2009-10-16 18:37:41 +00:00
|
|
|
}
|
2009-07-21 17:07:30 +00:00
|
|
|
|
|
|
|
full_design = atoi(walk+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((full_design == 1) || (remaining == -1))
|
2009-10-11 20:11:09 +00:00
|
|
|
return;
|
2009-07-21 17:07:30 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2009-10-11 20:11:09 +00:00
|
|
|
(void)printf("%s %.02f%% %02d:%02d:%02d",
|
2009-07-21 17:07:30 +00:00
|
|
|
(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 {
|
2009-10-11 20:11:09 +00:00
|
|
|
(void)printf("%s %.02f%%",
|
2009-07-21 17:07:30 +00:00
|
|
|
(status == CS_CHARGING ? "CHR" :
|
|
|
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
|
|
|
(((float)remaining / (float)full_design) * 100));
|
|
|
|
}
|
2009-08-31 17:34:57 +00:00
|
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
2009-07-23 16:40:49 +00:00
|
|
|
int state;
|
|
|
|
int sysctl_rslt;
|
|
|
|
size_t sysctl_size = sizeof(sysctl_rslt);
|
|
|
|
|
2009-10-11 20:11:09 +00:00
|
|
|
if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
|
|
|
|
printf("No battery");
|
|
|
|
return;
|
|
|
|
}
|
2009-07-23 16:40:49 +00:00
|
|
|
|
|
|
|
present_rate = sysctl_rslt;
|
2009-10-11 20:11:09 +00:00
|
|
|
if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) {
|
|
|
|
printf("No battery");
|
|
|
|
return;
|
|
|
|
}
|
2009-07-23 16:40:49 +00:00
|
|
|
|
|
|
|
remaining = sysctl_rslt;
|
2009-10-11 20:11:09 +00:00
|
|
|
if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0) {
|
|
|
|
printf("No battery");
|
|
|
|
return;
|
|
|
|
}
|
2009-07-23 16:40:49 +00:00
|
|
|
|
|
|
|
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);
|
2009-10-11 20:11:09 +00:00
|
|
|
(void)printf("%s %02d%% %02dh%02d",
|
2009-07-23 16:40:49 +00:00
|
|
|
(status == CS_CHARGING ? "CHR" :
|
|
|
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
|
|
|
present_rate,
|
|
|
|
max(hours, 0), max(minutes, 0));
|
|
|
|
} else {
|
2009-10-11 20:11:09 +00:00
|
|
|
(void)printf("%s %02d%%",
|
2009-07-23 16:40:49 +00:00
|
|
|
(status == CS_CHARGING ? "CHR" :
|
|
|
|
(status == CS_DISCHARGING ? "BAT" : "FULL")),
|
|
|
|
present_rate);
|
|
|
|
}
|
|
|
|
#endif
|
2009-07-21 17:07:30 +00:00
|
|
|
}
|