diff --git a/wmacpi/ChangeLog b/wmacpi/ChangeLog index 1a079a1..b54f1e4 100644 --- a/wmacpi/ChangeLog +++ b/wmacpi/ChangeLog @@ -1,3 +1,14 @@ +2004 September 28 2.0rc1 + Added support for switching to capacity mode automatically, on + detecting dodgy reports from the battery. + + Added support for capacity mode on charging, with automatic + enabling as per discharging. + + Various cleanups. + + Hopefully last release before the final 2.0. + 2004 August 18 1.99r7 Implemented the libdockapp port - this seems to close Debian bug #227819, but it hasn't received sufficient testing. diff --git a/wmacpi/acpi.c b/wmacpi/acpi.c index c56b15e..fd3ddda 100644 --- a/wmacpi/acpi.c +++ b/wmacpi/acpi.c @@ -26,7 +26,7 @@ #include "libacpi.h" -#define ACPI_VER "1.99" +#define ACPI_VER "2.0" global_t *globals; diff --git a/wmacpi/libacpi.c b/wmacpi/libacpi.c index ac54326..28557a2 100644 --- a/wmacpi/libacpi.c +++ b/wmacpi/libacpi.c @@ -408,13 +408,48 @@ static int calc_remaining_percentage(int batt) return retval; } +/* check to see if we've been getting bad data from the batteries - if + * we get more than some limit we swith to using the remaining capacity + * for the calculations. */ +static enum rtime_mode check_rt_mode(global_t *globals) +{ + int i; + int bad_limit = 5; + battery_t *binfo; + + /* if we were told what to do, we should keep doing it */ + if(globals->rt_forced) + return globals->rt_mode; + + for(i = 0; i < MAXBATT; i++) { + binfo = &batteries[i]; + if(binfo->present && globals->adapter.power == BATT) { + if(binfo->present_rate <= 0) { + pdebug("Bad report from %s\n", binfo->name); + binfo->bad_count++; + } + } + } + for(i = 0; i < MAXBATT; i++) { + binfo = &batteries[i]; + if(binfo->bad_count > bad_limit) { + if(globals->rt_mode != RT_CAP) + pinfo("More than %d bad reports from %s; " + "Switching to remaining capacity mode\n", + bad_limit, binfo->name); + return RT_CAP; + } + } + return RT_RATE; +} + /* calculate remaining time until the battery is charged. * when charging, the battery state file reports the * current being used to charge the battery. We can use * this and the remaining capacity to work out how long * until it reaches the last full capacity of the battery. * XXX: make sure this is actually portable . . . */ -static int calc_charge_time(int batt) +static int calc_charge_time_rate(int batt) { float rcap, lfcap; battery_t *binfo; @@ -438,6 +473,78 @@ static int calc_charge_time(int batt) return charge_time; } +/* we need to calculate the present rate the same way we do in rt_cap + * mode, and then use that to estimate charge time. This will + * necessarily be even less accurate than it is for remaining time, but + * it's just as neessary . . . */ +#define CAP_SAMPLES (SAMPLES*10) +static int calc_charge_time_cap(int batt) +{ + static float cap_samples[CAP_SAMPLES]; + static int time_samples[CAP_SAMPLES]; + static int sample_count = 0; + static int current = 0; + static int old = 1; + int rtime; + int tdiff; + float cdiff; + float current_rate; + battery_t *binfo = &batteries[batt]; + + cap_samples[current] = (float) binfo->remaining_cap; + time_samples[current] = time(NULL); + + if (sample_count == 0) { + /* we can't do much if we don't have any data . . . */ + current_rate = 0; + } else if (sample_count < CAP_SAMPLES) { + /* if we have less than SAMPLES samples so far, we use the first + * sample and the current one */ + cdiff = cap_samples[current] - cap_samples[0]; + tdiff = time_samples[current] - time_samples[0]; + current_rate = cdiff/tdiff; + } else { + /* if we have more than SAMPLES samples, we use the oldest + * current one, which at this point is current + 1. This will + * wrap the same way that current will wrap, but one cycle + * ahead */ + cdiff = cap_samples[current] - cap_samples[old]; + tdiff = time_samples[current] - time_samples[old]; + current_rate = cdiff/(float)tdiff; + } + if (current_rate == 0) + rtime = 0; + else { + float cap_left = (float)(binfo->last_full_cap - binfo->remaining_cap); + rtime = (int)(cap_left/(current_rate * 60.0)); + } + sample_count++, current++, old++; + if (current >= CAP_SAMPLES) + current = 0; + if (old >= CAP_SAMPLES) + old = 0; + + pdebug("cap charge time rem: %d\n", rtime); + return rtime; +} + +static int calc_charge_time(global_t *globals, int batt) +{ + int ctime = 0; + + globals->rt_mode = check_rt_mode(globals); + + switch(globals->rt_mode) { + case RT_RATE: + ctime = calc_charge_time_rate(batt); + break; + case RT_CAP: + ctime = calc_charge_time_cap(batt); + break; + } + return ctime; +} + void acquire_batt_info(global_t *globals, int batt) { battery_t *binfo; @@ -485,7 +592,7 @@ void acquire_batt_info(global_t *globals, int batt) } } - binfo->charge_time = calc_charge_time(batt); + binfo->charge_time = calc_charge_time(globals, batt); /* and finally, we tell anyone who wants to use this information * that it's now valid . . .*/ @@ -582,7 +689,7 @@ int calc_time_remaining_rate(global_t *globals) if(rtime <= 0) rtime = 0; out: - pdebug("time rem: %d\n", rtime); + pdebug("discharge time rem: %d\n", rtime); return rtime; } @@ -604,8 +711,8 @@ int calc_time_remaining_rate(global_t *globals) */ int calc_time_remaining_cap(global_t *globals) { - static float cap_samples[SAMPLES]; - static int time_samples[SAMPLES]; + static float cap_samples[CAP_SAMPLES]; + static int time_samples[CAP_SAMPLES]; static int sample_count = 0; static int current = 0; static int old = 1; @@ -625,9 +732,12 @@ int calc_time_remaining_cap(global_t *globals) cap_samples[current] = cap; time_samples[current] = time(NULL); - /* if we have less than SAMPLES samples so far, we use the first - * sample and the current one */ - if (sample_count < SAMPLES) { + if (sample_count == 0) { + /* we can't do much if we don't have any data . . . */ + current_rate = 0; + } else if (sample_count < CAP_SAMPLES) { + /* if we have less than SAMPLES samples so far, we use the first + * sample and the current one */ cdiff = cap_samples[0] - cap_samples[current]; tdiff = time_samples[current] - time_samples[0]; current_rate = cdiff/tdiff; @@ -646,12 +756,12 @@ int calc_time_remaining_cap(global_t *globals) rtime = (int)(cap_samples[current]/(current_rate * 60.0)); sample_count++, current++, old++; - if (current >= SAMPLES) + if (current >= CAP_SAMPLES) current = 0; - if (old >= SAMPLES) + if (old >= CAP_SAMPLES) old = 0; - pdebug("time rem: %d\n", rtime); + pdebug("cap discharge time rem: %d\n", rtime); return rtime; } @@ -659,6 +769,8 @@ void acquire_global_info(global_t *globals) { adapter_t *ap = &globals->adapter; + globals->rt_mode = check_rt_mode(globals); + switch(globals->rt_mode) { case RT_RATE: globals->rtime = calc_time_remaining_rate(globals); diff --git a/wmacpi/libacpi.h b/wmacpi/libacpi.h index b28687a..e98dee3 100644 --- a/wmacpi/libacpi.h +++ b/wmacpi/libacpi.h @@ -2,7 +2,7 @@ #define _LIBACPI_H_ -#define LIBACPI_VER "0.91" +#define LIBACPI_VER "0.92" /* Here because we need it for definitions in this file . . . */ #define MAX_NAME 128 @@ -63,6 +63,8 @@ typedef struct { int charge_time; /* time left to charge this battery */ /* and a flag to indicate that this is valid . . . */ int valid; + /* number of times we've gotten bad info on this battery's present rate */ + int bad_count; } battery_t; typedef struct { @@ -82,7 +84,8 @@ typedef struct { int timer; /* how long been on battery? */ int crit_level; /* anything below this is critical low */ int battery_count; /* number of batteries found */ - enum rtime_mode rt_mode; + enum rtime_mode rt_mode; /* remaining time mode */ + int rt_forced; /* was our rt_mode forced? if so, we do what we were told */ battery_t *binfo; /* pointer to the battery being monitored */ adapter_t adapter; } global_t; diff --git a/wmacpi/wmacpi.c b/wmacpi/wmacpi.c index 3473541..07cd80d 100644 --- a/wmacpi/wmacpi.c +++ b/wmacpi/wmacpi.c @@ -37,7 +37,7 @@ #include "libacpi.h" #include "wmacpi.h" -#define WMACPI_VER "1.99r7" +#define WMACPI_VER "2.0rc1" /* main pixmap */ #ifdef LOW_COLOR @@ -541,11 +541,9 @@ static void set_message(global_t *globals) void set_time_display(global_t *globals) { - battery_t *binfo = &batteries[battery_no]; - - if (binfo->charge_state == CHARGE) - display_time(binfo->charge_time); - else if (binfo->charge_state == DISCHARGE) + if (globals->binfo->charge_state == CHARGE) + display_time(globals->binfo->charge_time); + else if (globals->binfo->charge_state == DISCHARGE) display_time(globals->rtime); else invalid_time_display(); @@ -596,7 +594,7 @@ void cli_wmacpi(global_t *globals, int samples) battery_t *binfo; adapter_t *ap; - printf("%d\n", samples); + pdebug("samples: %d\n", samples); if(samples > 1) sleep_time = 1000000/samples; @@ -653,6 +651,7 @@ int main(int argc, char **argv) int sleep_time = 1000000/sleep_rate; int scroll_count = 0; enum rtime_mode rt_mode = RT_RATE; + int rt_forced = 0; battery_t *binfo; global_t *globals; @@ -715,6 +714,7 @@ int main(int argc, char **argv) break; case 'f': rt_mode = RT_CAP; + rt_forced = 1; break; case 'h': usage(argv[0]); @@ -758,6 +758,7 @@ int main(int argc, char **argv) exit(1); globals->rt_mode = rt_mode; + globals->rt_forced = rt_forced; if (battery_no > globals->battery_count) { pfatal("Battery %d not available for monitoring.\n", battery_no); @@ -769,6 +770,13 @@ int main(int argc, char **argv) cli_wmacpi(globals, samples); exit(0); } + /* check to see if we've got a valid DISPLAY env variable, as a simple check to see if + * we're running under X */ + if (!getenv("DISPLAY")) { + pdebug("Not running under X - using cli mode\n"); + cli_wmacpi(globals, samples); + exit(0); + } battery_no--; @@ -812,7 +820,7 @@ int main(int argc, char **argv) battery_no = battery_no % globals->battery_count; globals->binfo = &batteries[battery_no]; binfo = globals->binfo; - pinfo("changing to monitor battery %d\n", battery_no + 1); + pinfo("changing to monitor battery %s\n", binfo->name); set_batt_id_area(battery_no); dockapp->update = 1; break;