From 570093db0fe650646f58f7d247e2adf42a3477ec Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 27 Dec 2007 17:42:23 +0100 Subject: [PATCH] Handle multiple batteries better. Check AC state as well. --- batt.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 24 deletions(-) diff --git a/batt.c b/batt.c index f70f5e1..fa6ff10 100644 --- a/batt.c +++ b/batt.c @@ -1,3 +1,9 @@ +/* + * A Simple Battery Status Display + * + * (c) 2007 Martin Mares + */ + #include #include #include @@ -9,16 +15,68 @@ #include static xosd *osd; -static int total_discharge, total_charge, total_full, total_capa; +static int total_full, total_capa, discharge_rate; +static int charge_time, discharge_time; +static int ac_online; +static unsigned int present_mask, charge_mask, discharge_mask; #define CHECK_PERIOD 60 #define SHOW_DURATION 2 #define WARN_THRESHOLD 600 +static char *parse_line(char *line) +{ + char *t = strchr(line, '\n'); + if (t) + *t = 0; + char *val = strchr(line, ':'); + if (!val) + return NULL; + *val++ = 0; + while (*val == ' ' || *val == '\t') + *val++ = 0; + return val; +} + +static void scan_ac(void) +{ + ac_online = 0; + + const char dir[] = "/proc/acpi/ac_adapter"; + DIR *d = opendir(dir); + if (!d) + return; + + struct dirent *e; + while (e = readdir(d)) + { + if (e->d_name[0] == '.') + continue; + char n[sizeof(dir) + 1 + strlen(e->d_name) + 6]; + sprintf(n, "%s/%s/state", dir, e->d_name); + FILE *f = fopen(n, "r"); + if (!f) + continue; + char line[1024]; + while (fgets(line, sizeof(line)-1, f)) + { + char *val = parse_line(line); + if (!val) + continue; + if (!strcmp(line, "state") && !strcmp(val, "on-line")) + ac_online = 1; + } + fclose(f); + } + closedir(d); +} + static void scan_batt(void) { - total_discharge = total_charge = 0; + charge_time = discharge_time = 0; total_full = total_capa = 0; + discharge_rate = 0; + present_mask = charge_mask = discharge_mask = 0; const char dir[] = "/proc/acpi/battery"; DIR *d = opendir(dir); @@ -37,6 +95,7 @@ static void scan_batt(void) int charging = 0; int remains = 0; int last_full = 0; + int batt_id = -1; for (int i=0; i<2; i++) { sprintf(n, "%s/%s/%s", dir, e->d_name, names[i]); @@ -46,15 +105,9 @@ static void scan_batt(void) char line[1024]; while (fgets(line, sizeof(line)-1, f)) { - char *t = strchr(line, '\n'); - if (t) - *t = 0; - char *val = strchr(line, ':'); + char *val = parse_line(line); if (!val) continue; - *val++ = 0; - while (*val == ' ' || *val == '\t') - *val++ = 0; // printf("<%s> <%s>\n", line, val); if (!strcmp(line, "present")) present = !strcmp(val, "yes"); @@ -66,32 +119,63 @@ static void scan_batt(void) remains = atol(val); else if (!strcmp(line, "last full capacity")) last_full = atol(val); + else if (!strcmp(line, "serial number")) + batt_id = atol(val); } fclose(f); } if (present) { + if (batt_id < 0 || batt_id > 31) + batt_id = 0; + present_mask |= 1 << batt_id; total_full += remains; total_capa += last_full; if (charging) { + charge_mask |= 1 << batt_id; int ch = (last_full - remains)*3600 / rate; - if (ch > total_charge) - total_charge = ch; + if (ch > charge_time) + charge_time = ch; } - else + else if (rate > 0) { - if (rate <= 0) - total_discharge += 1000000; - else - total_discharge += remains*3600 / rate; + discharge_mask |= 1 << batt_id; + discharge_rate += rate; } } } + if (discharge_rate) + discharge_time = total_full*3600 / discharge_rate; + else + discharge_time = 1000000; closedir(d); } +static void scan(void) +{ + scan_ac(); + scan_batt(); +} + +static char *batt_mask(char *p, unsigned int mask) +{ + if (present_mask & (present_mask-1)) + { + char *p0 = p; + for (int i=0; mask; i++) + if (mask & (1 << i)) + { + *p = (p == p0) ? ' ' : '+'; + p++; + p += sprintf(p, "B%d", i); + mask &= ~(1 << i); + } + } + return p; +} + static void show(void) { char status[256]; @@ -100,10 +184,20 @@ static void show(void) p += sprintf(p, "%d%%", 100*total_full/total_capa); else p += sprintf(p, "??%%"); - if (total_discharge && total_discharge < 1000000) - p += sprintf(p, " %d:%02d remains", total_discharge/3600, (total_discharge/60)%60); - else if (total_charge) - p += sprintf(p, " %d:%02d charging", total_charge/3600, (total_charge/60)%60); + if (discharge_mask && discharge_time < 1000000) + { + p += sprintf(p, " %d:%02d remains", discharge_time/3600, (discharge_time/60)%60); + batt_mask(p, discharge_mask); + } + else if (charge_mask) + { + p += sprintf(p, " %d:%02d charging", charge_time/3600, (charge_time/60)%60); + batt_mask(p, charge_mask); + } + else if (ac_online) + p += sprintf(p, " AC"); + else + p += sprintf(p, " BATT"); xosd_display(osd, 0, XOSD_string, status); } @@ -116,7 +210,7 @@ static void my_sleep(int sec) static void sig_show(int sig) { alarm(0); - scan_batt(); + scan(); show(); my_sleep(SHOW_DURATION); xosd_hide(osd); @@ -139,8 +233,8 @@ static void sig_time(int sig) static void sig_check(int sig) { - scan_batt(); - if (total_discharge && total_discharge < WARN_THRESHOLD) + scan(); + if (discharge_mask && discharge_time < WARN_THRESHOLD) { show(); my_sleep(SHOW_DURATION); @@ -190,7 +284,7 @@ int main(int argc, char **argv) if (!watcher) { - scan_batt(); + scan(); show(); my_sleep(SHOW_DURATION); xosd_destroy(osd); -- 2.39.2