X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=osd-batt.c;h=33ec7216fb403bb5e5b5b9a0d1c40abfe4db4352;hb=refs%2Fheads%2Fmaster;hp=56bf5b916ed558164e3efd00548f14846552114a;hpb=0ab80500fd3a7e262417c707022dffbcd8655ba6;p=osdd.git diff --git a/osd-batt.c b/osd-batt.c index 56bf5b9..33ec721 100644 --- a/osd-batt.c +++ b/osd-batt.c @@ -1,15 +1,18 @@ /* * A Simple Battery Status Display via OSD * - * (c) 2007--2010 Martin Mares + * (c) 2007--2012 Martin Mares */ +#undef DEBUG + #include #include #include #include #include #include +#include #include "osd.h" @@ -17,66 +20,112 @@ static int check_mode; static int check_every; static int warn_threshold = 600; -static int total_full, total_capa, discharge_rate; +static int total_now, total_full, discharge_rate; static int charge_time, discharge_time; static int ac_online; static unsigned int present_mask, charge_mask, discharge_mask; -static char *parse_line(char *line) +static unsigned int last_charge_mask, last_discharge_mask; +static int last_ac_online = -1; + +#define MAX_BATTS 4 +#define BATT_NAME_LEN 32 +static char batt_names[MAX_BATTS][BATT_NAME_LEN]; + +static char sys_dir[256]; +#define BUFSIZE 256 + +static int sys_read(char *buf, char *attribute) { - 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; + char name[256]; + snprintf(name, sizeof(name), "%s/%s", sys_dir, attribute); + + int fd = open(name, O_RDONLY); + if (fd < 0) + return 0; + + int n = read(fd, buf, BUFSIZE); + close(fd); + if (n < 0) + return 0; + + buf[BUFSIZE-1] = 0; + char *nl = strchr(buf, '\n'); + if (nl) + *nl = 0; + DBG("\t%s=%s\n", attribute, buf); + return 1; } -static void scan_ac(void) +static int sys_read_int(char *attribute, int default_value) { - ac_online = 0; + char buf[BUFSIZE]; + if (!sys_read(buf, attribute) || !buf[0]) + return default_value; + else + return atoi(buf); +} - const char dir[] = "/proc/acpi/ac_adapter"; - DIR *d = opendir(dir); - if (!d) - return; +static void parse_ac(void) +{ + ac_online = sys_read_int("online", 0); +} - struct dirent *e; - while (e = readdir(d)) +static int get_batt_id(char *batt_name) +{ + for (int i=0; id_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)) + if (!strcmp(batt_names[i], batt_name)) + return i; + if (!batt_names[i][0]) { - char *val = parse_line(line); - if (!val) - continue; - if (!strcmp(line, "state") && !strcmp(val, "on-line")) - ac_online = 1; + snprintf(batt_names[i], BATT_NAME_LEN, "%s", batt_name); + return i; } - fclose(f); } - closedir(d); + return MAX_BATTS; } -static void scan_batt(void) +static void parse_batt(char *batt_name) { + int batt_id = get_batt_id(batt_name); + DBG("\t-> id %d\n", batt_id); + + if (!sys_read_int("present", 1)) + return; + + char status[BUFSIZE]; + int charging = sys_read(status, "status") && !strcmp(status, "Charging"); + int charge_full = sys_read_int("charge_full", 0); + int charge_now = sys_read_int("charge_now", 0); + int current_now = sys_read_int("current_now", 0); + + present_mask |= 1 << batt_id; + total_now += charge_now; + total_full += charge_full; + if (charging && current_now > 0) + { + charge_mask |= 1 << batt_id; + int ch = (long long)(charge_full - charge_now)*3600 / current_now; + if (ch > charge_time) + charge_time = ch; + } + else if (current_now > 0) + { + discharge_mask |= 1 << batt_id; + discharge_rate += current_now; + } +} + +static void scan(void) +{ + ac_online = 0; charge_time = discharge_time = 0; - total_full = total_capa = 0; + total_now = total_full = 0; discharge_rate = 0; present_mask = charge_mask = discharge_mask = 0; - const char dir[] = "/proc/acpi/battery"; + const char dir[] = "/sys/class/power_supply"; DIR *d = opendir(dir); if (!d) return; @@ -85,76 +134,28 @@ static void scan_batt(void) while (e = readdir(d)) { if (e->d_name[0] == '.') - continue; - char n[sizeof(dir) + 1 + strlen(e->d_name) + 6]; - const char * const names[] = { "state", "info" }; - int present = 0; - int rate = 0; - 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]); - 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; - // printf("<%s> <%s>\n", line, val); - if (!strcmp(line, "present")) - present = !strcmp(val, "yes"); - else if (!strcmp(line, "charging state")) - charging = !strcmp(val, "charging"); - else if (!strcmp(line, "present rate")) - rate = atol(val); - else if (!strcmp(line, "remaining capacity")) - 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 > charge_time) - charge_time = ch; - } - else if (rate > 0) - { - discharge_mask |= 1 << batt_id; - discharge_rate += rate; - } - } + continue; + snprintf(sys_dir, sizeof(sys_dir), "%s/%s", dir, e->d_name); + DBG("%s\n", sys_dir); + + char type[BUFSIZE]; + if (!sys_read(type, "type")) + continue; + + if (!strcmp(type, "Mains")) + parse_ac(); + else if (!strcmp(type, "Battery")) + parse_batt(e->d_name); } if (discharge_rate) - discharge_time = total_full*3600 / discharge_rate; + discharge_time = (long long) total_now*3600 / discharge_rate; else discharge_time = 1000000; closedir(d); -} - -static void scan(void) -{ - scan_ac(); - scan_batt(); + DBG("=> Capacity: now=%d full=%d\n", total_now, total_full); + DBG("=> Charge: mask=%d time=%d\n", charge_mask, charge_time); + DBG("=> Discharge: mask=%d rate=%d time=%d\n", discharge_mask, discharge_rate, discharge_time); } static char *batt_mask(char *p, unsigned int mask) @@ -178,8 +179,8 @@ static void show(void) { char status[256]; char *p = status; - if (total_capa) - p += sprintf(p, "%d%%", 100*total_full/total_capa); + if (total_full) + p += sprintf(p, "%d%%", (int)((long long)100*total_now/total_full)); else p += sprintf(p, "??%%"); if (discharge_mask && discharge_time < 1000000) @@ -204,8 +205,16 @@ static void show(void) static void show_if_warn(void) { - if (discharge_mask && discharge_time < warn_threshold) + if (discharge_mask && discharge_time < warn_threshold || + last_ac_online >= 0 && ( + charge_mask != last_charge_mask || + discharge_mask != last_discharge_mask || + ac_online != last_ac_online)) show(); + + last_charge_mask = charge_mask; + last_discharge_mask = discharge_mask; + last_ac_online = ac_online; } static void NONRET