2 * A Simple Battery Status Display via OSD
4 * (c) 2007--2010 Martin Mares <mj@ucw.cz>
17 static int check_mode;
18 static int warn_threshold = 600;
20 static int total_full, total_capa, discharge_rate;
21 static int charge_time, discharge_time;
23 static unsigned int present_mask, charge_mask, discharge_mask;
25 static char *parse_line(char *line)
27 char *t = strchr(line, '\n');
30 char *val = strchr(line, ':');
34 while (*val == ' ' || *val == '\t')
39 static void scan_ac(void)
43 const char dir[] = "/proc/acpi/ac_adapter";
44 DIR *d = opendir(dir);
49 while (e = readdir(d))
51 if (e->d_name[0] == '.')
53 char n[sizeof(dir) + 1 + strlen(e->d_name) + 6];
54 sprintf(n, "%s/%s/state", dir, e->d_name);
55 FILE *f = fopen(n, "r");
59 while (fgets(line, sizeof(line)-1, f))
61 char *val = parse_line(line);
64 if (!strcmp(line, "state") && !strcmp(val, "on-line"))
72 static void scan_batt(void)
74 charge_time = discharge_time = 0;
75 total_full = total_capa = 0;
77 present_mask = charge_mask = discharge_mask = 0;
79 const char dir[] = "/proc/acpi/battery";
80 DIR *d = opendir(dir);
85 while (e = readdir(d))
87 if (e->d_name[0] == '.')
89 char n[sizeof(dir) + 1 + strlen(e->d_name) + 6];
90 const char * const names[] = { "state", "info" };
97 for (int i=0; i<2; i++)
99 sprintf(n, "%s/%s/%s", dir, e->d_name, names[i]);
100 FILE *f = fopen(n, "r");
104 while (fgets(line, sizeof(line)-1, f))
106 char *val = parse_line(line);
109 // printf("<%s> <%s>\n", line, val);
110 if (!strcmp(line, "present"))
111 present = !strcmp(val, "yes");
112 else if (!strcmp(line, "charging state"))
113 charging = !strcmp(val, "charging");
114 else if (!strcmp(line, "present rate"))
116 else if (!strcmp(line, "remaining capacity"))
118 else if (!strcmp(line, "last full capacity"))
119 last_full = atol(val);
120 else if (!strcmp(line, "serial number"))
127 if (batt_id < 0 || batt_id > 31)
129 present_mask |= 1 << batt_id;
130 total_full += remains;
131 total_capa += last_full;
134 charge_mask |= 1 << batt_id;
135 int ch = (last_full - remains)*3600 / rate;
136 if (ch > charge_time)
141 discharge_mask |= 1 << batt_id;
142 discharge_rate += rate;
147 discharge_time = total_full*3600 / discharge_rate;
149 discharge_time = 1000000;
154 static void scan(void)
160 static char *batt_mask(char *p, unsigned int mask)
162 if (present_mask & (present_mask-1))
165 for (int i=0; mask; i++)
168 *p = (p == p0) ? ' ' : '+';
170 p += sprintf(p, "B%d", i);
177 static void show(void)
182 p += sprintf(p, "%d%%", 100*total_full/total_capa);
184 p += sprintf(p, "??%%");
185 if (discharge_mask && discharge_time < 1000000)
187 p += sprintf(p, " %d:%02d remains", discharge_time/3600, (discharge_time/60)%60);
188 batt_mask(p, discharge_mask);
190 else if (charge_mask)
192 p += sprintf(p, " %d:%02d charging", charge_time/3600, (charge_time/60)%60);
193 batt_mask(p, charge_mask);
196 p += sprintf(p, " AC");
198 p += sprintf(p, " BATT");
200 struct osd_msg *msg = osd_new_msg();
201 osd_add_line(msg, NULL, status);
209 Usage: osd-batt <options>\n\
212 -c, --check\t\tDisplay status only if battery is low\n\
213 -w, --warn=<sec>\tBattery is low if less than <sec> seconds remain (default: 600)\n\
218 static const char short_opts[] = "cw:";
220 static const struct option long_opts[] = {
221 { "check", no_argument, NULL, 'c' },
222 { "warn", required_argument, NULL, 'w' },
223 { NULL, 0, NULL, 0 },
226 int main(int argc, char **argv)
229 while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0)
236 warn_threshold = atoi(optarg);
245 if (!check_mode || (discharge_mask && discharge_time < warn_threshold))