seems to be behaving now.

SVN revision: 33906
This commit is contained in:
Carsten Haitzler 2008-03-03 14:35:26 +00:00
parent 29ccce4f86
commit 55b40f3d3b
2 changed files with 233 additions and 189 deletions

View File

@ -411,10 +411,24 @@ static void linux_sys_class_power_supply_init(void);
static void linux_sys_class_power_supply_check(void); static void linux_sys_class_power_supply_check(void);
typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent; typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent;
#define BASIS_CHARGE 1
#define BASIS_ENERGY 2
#define BASIS_VOLTAGE 3
struct _Sys_Class_Power_Supply_Uevent struct _Sys_Class_Power_Supply_Uevent
{ {
char *name;
int fd; int fd;
Ecore_Fd_Handler *fd_handler; Ecore_Fd_Handler *fd_handler;
int present;
int basis;
int basis_empty;
int basis_full;
unsigned char have_current_avg : 1;
unsigned char have_current_now : 1;
}; };
static Ecore_List *events = NULL; static Ecore_List *events = NULL;
@ -457,8 +471,11 @@ linux_sys_class_power_supply_cb_event_fd_active(void *data, Ecore_Fd_Handler *fd
{ {
ecore_list_goto(events, sysev); ecore_list_goto(events, sysev);
ecore_list_remove(events); ecore_list_remove(events);
ecore_main_fd_handler_del(sysev->fd_handler);
close(sysev->fd); if (sysev->fd_handler)
ecore_main_fd_handler_del(sysev->fd_handler);
if (sysev->fd >= 0) close(sysev->fd);
free(sysev->name);
free(sysev); free(sysev);
} }
else else
@ -471,59 +488,139 @@ linux_sys_class_power_supply_cb_event_fd_active(void *data, Ecore_Fd_Handler *fd
} }
static void static void
linux_sys_class_power_supply_init(void) linux_sys_class_power_supply_sysev_init(Sys_Class_Power_Supply_Uevent *sysev)
{ {
Ecore_List *bats;
char *name; char *name;
char buf[4096]; char buf[4096];
sysev->basis = 0;
sysev->have_current_avg = 0;
sysev->have_current_now = 0;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/present", sysev->name);
sysev->present = int_file_get(buf);
if (!sysev->present) return;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_avg", sysev->name);
if (ecore_file_exists(buf)) sysev->have_current_avg = 1;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", sysev->name);
if (ecore_file_exists(buf)) sysev->have_current_now = 1;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full_design", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full_design", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", sysev->name);
if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
if (sysev->basis == BASIS_CHARGE)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", sysev->name);
sysev->basis_full = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty", sysev->name);
sysev->basis_empty = int_file_get(buf);
if (sysev->basis_full < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", sysev->name);
sysev->basis_full = int_file_get(buf);
}
if (sysev->basis_empty < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty_design", sysev->name);
sysev->basis_empty = int_file_get(buf);
}
}
else if (sysev->basis == BASIS_ENERGY)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full", sysev->name);
sysev->basis_full = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty", sysev->name);
sysev->basis_empty = int_file_get(buf);
if (sysev->basis_full < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full_design", sysev->name);
sysev->basis_full = int_file_get(buf);
}
if (sysev->basis_empty < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty_design", sysev->name);
sysev->basis_empty = int_file_get(buf);
}
}
else if (sysev->basis == BASIS_VOLTAGE)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full", sysev->name);
sysev->basis_full = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty", sysev->name);
sysev->basis_empty = int_file_get(buf);
if (sysev->basis_full < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full_design", sysev->name);
sysev->basis_full = int_file_get(buf);
}
if (sysev->basis_empty < 0)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty_design", sysev->name);
sysev->basis_empty = int_file_get(buf);
}
}
}
static void
linux_sys_class_power_supply_init(void)
{
if (events) if (events)
{ {
while (!ecore_list_empty_is(events)) Sys_Class_Power_Supply_Uevent *sysev;
{
Sys_Class_Power_Supply_Uevent *sysev;
ecore_list_first_goto(events); ecore_list_first_goto(events);
sysev = ecore_list_remove(events); while ((sysev = ecore_list_next(events)))
ecore_main_fd_handler_del(sysev->fd_handler); linux_sys_class_power_supply_sysev_init(sysev);
close(sysev->fd);
free(sysev);
}
ecore_list_destroy(events);
events = NULL;
} }
bats = ecore_file_ls("/sys/class/power_supply/"); else
if (bats)
{ {
events = ecore_list_new(); Ecore_List *bats;
while ((name = ecore_list_next(bats))) char *name;
char buf[4096];
bats = ecore_file_ls("/sys/class/power_supply/");
if (bats)
{ {
int fd; events = ecore_list_new();
while ((name = ecore_list_next(bats)))
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/uevent", name);
fd = open(buf, O_RDONLY);
if (fd >= 0)
{ {
Sys_Class_Power_Supply_Uevent *sysev; Sys_Class_Power_Supply_Uevent *sysev;
if (strncasecmp("bat", name, 3)) continue;
sysev = E_NEW(Sys_Class_Power_Supply_Uevent, 1); sysev = E_NEW(Sys_Class_Power_Supply_Uevent, 1);
sysev->fd = fd; sysev->name = strdup(name);
sysev->fd_handler = ecore_main_fd_handler_add(sysev->fd, snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/uevent", name);
ECORE_FD_READ, sysev->fd = open(buf, O_RDONLY);
linux_sys_class_power_supply_cb_event_fd_active, if (sysev->fd >= 0)
sysev, sysev->fd_handler = ecore_main_fd_handler_add(sysev->fd,
NULL, NULL); ECORE_FD_READ,
linux_sys_class_power_supply_cb_event_fd_active,
sysev,
NULL, NULL);
ecore_list_append(events, sysev); ecore_list_append(events, sysev);
linux_sys_class_power_supply_sysev_init(sysev);
} }
ecore_list_destroy(bats);
} }
ecore_list_destroy(bats);
} }
} }
static void static void
linux_sys_class_power_supply_check(void) linux_sys_class_power_supply_check(void)
{ {
Ecore_List *bats;
char *name; char *name;
char buf[4096]; char buf[4096];
@ -531,66 +628,59 @@ linux_sys_class_power_supply_check(void)
time_left = -1; time_left = -1;
have_battery = 0; have_battery = 0;
have_power = 0; have_power = 0;
bats = ecore_file_ls("/sys/class/power_supply/"); if (events)
if (bats)
{ {
int total_pwr_now = 0; Sys_Class_Power_Supply_Uevent *sysev;
int total_pwr_max = 0; int total_pwr_now;
int total_pwr_max;
total_pwr_now = 0;
total_pwr_max = 0;
time_left = 0; time_left = 0;
ecore_list_first_goto(events);
while ((name = ecore_list_next(bats))) while ((sysev = ecore_list_next(events)))
{ {
char *tmp; char *tmp;
int present = 0; int present = 0;
int charging = -1; int charging = -1;
int capacity = -1; int capacity = -1;
int current_avg = -1; int current = -1;
int current_now = -1;
int time_to_full = -1; int time_to_full = -1;
int time_to_empty = -1; int time_to_empty = -1;
int full = -1; int full = -1;
int charge_now = -1;
int charge_empty = -1;
int charge_full = -1;
int charge_empty_design = -1;
int charge_full_design = -1;
int energy_now = -1;
int energy_empty = -1;
int energy_full = -1;
int energy_empty_design = -1;
int energy_full_design = -1;
int voltage_now = -1;
int voltage_empty = -1;
int voltage_full = -1;
int voltage_empty_design = -1;
int voltage_full_design = -1;
int pwr_now = -1; int pwr_now = -1;
int pwr_empty = -1; int pwr_empty = -1;
int pwr_full = -1; int pwr_full = -1;
int pwr; int pwr = 0;
if (strncasecmp("bat", name, 3)) continue; name = sysev->name;
/* FIXME: this is not hyper-efficient. we try and find all sorts
* of entries. they may or may not exist. we don't remember that
* and should figure this out during init. i have tried to make
* this handle as many cases as possible */
/* fetch more generic info */ /* fetch more generic info */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/present", name); // init
present = int_file_get(buf); present = sysev->present;
if (!present) continue;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/capacity", name); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/capacity", name);
capacity = int_file_get(buf); capacity = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_avg", name); if (sysev->have_current_avg)
current_avg = int_file_get(buf); {
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", name); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_avg", name);
current_now = int_file_get(buf); current = int_file_get(buf);
}
else if (sysev->have_current_now)
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", name);
current = int_file_get(buf);
}
/* FIXME: do we get a uevent on going from charging to full?
* if so, move this to init */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/status", name); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/status", name);
tmp = str_file_get(buf); tmp = str_file_get(buf);
if (tmp) if (tmp)
{ {
full = 0;
if (!strncasecmp("discharging", tmp, 11)) charging = 0; if (!strncasecmp("discharging", tmp, 11)) charging = 0;
else if (!strncasecmp("charging", tmp, 8)) charging = 1; else if (!strncasecmp("charging", tmp, 8)) charging = 1;
else if (!strncasecmp("full", tmp, 4)) else if (!strncasecmp("full", tmp, 4))
@ -600,91 +690,48 @@ linux_sys_class_power_supply_check(void)
} }
free(tmp); free(tmp);
} }
/* some batteries cna/will/want to predict how long they will /* some batteries can/will/want to predict how long they will
* last. if so - take what the battery says. too bad if it's * last. if so - take what the battery says. too bad if it's
* wrong. that's a buggy battery or driver */ * wrong. that's a buggy battery or driver */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_full_now", name); if (!full)
time_to_full = int_file_get(buf); {
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_empty_now", name); if (charging)
time_to_empty = int_file_get(buf); {
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_full_now", name);
time_to_full = int_file_get(buf);
}
else
{
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_empty_now", name);
time_to_empty = int_file_get(buf);
}
}
/* now get charge, energy and voltage. take the one that provides /* now get charge, energy and voltage. take the one that provides
* the best info (charge first, then energy, then voltage */ * the best info (charge first, then energy, then voltage */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_now", name); if (sysev->basis == BASIS_CHARGE)
charge_now = int_file_get(buf); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_now", name);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", name); else if (sysev->basis == BASIS_ENERGY)
charge_full = int_file_get(buf); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_now", name);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty", name); else if (sysev->basis == BASIS_VOLTAGE)
charge_empty = int_file_get(buf); snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_now", name);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", name); pwr_now = int_file_get(buf);
charge_full_design = int_file_get(buf); pwr_empty = sysev->basis_empty;
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty_design", name); pwr_full = sysev->basis_full;
charge_empty_design = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_now", name);
energy_now = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full", name);
energy_full = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty", name);
energy_empty = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full_design", name);
energy_full_design = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty_design", name);
energy_empty_design = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_now", name);
voltage_now = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full", name);
voltage_full = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty", name);
voltage_empty = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full_design", name);
voltage_full_design = int_file_get(buf);
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty_design", name);
voltage_empty_design = int_file_get(buf);
/* now the logic of figuring this out */
if (charge_empty < 0) charge_empty = charge_empty_design;
if (charge_full < 0) charge_full = charge_full_design;
if (energy_empty < 0) energy_empty = energy_empty_design;
if (energy_full < 0) energy_full = energy_full_design;
if (voltage_empty < 0) voltage_empty = voltage_empty_design;
if (voltage_full < 0) voltage_full = voltage_full_design;
if (charge_full >= 0)
{
pwr_now = charge_now;
pwr_empty = charge_empty;
pwr_full = charge_full;
}
else if (energy_full >= 0)
{
pwr_now = energy_now;
pwr_empty = energy_empty;
pwr_full = energy_full;
}
else if (voltage_full >= 0)
{
pwr_now = voltage_now;
pwr_empty = voltage_empty;
pwr_full = voltage_full;
}
if (pwr_empty < 0) pwr_empty = 0; if (pwr_empty < 0) pwr_empty = 0;
if (full)
{ if (full) pwr_now = pwr_full;
pwr_now = pwr_full;
}
else else
{ {
if (pwr_now < 0) if (pwr_now < 0)
pwr_now = ((capacity * (pwr_full - pwr_empty)) / 100) + pwr_empty; pwr_now = ((capacity * (pwr_full - pwr_empty)) / 100) + pwr_empty;
} }
if (present) have_battery = 1; if (sysev->present) have_battery = 1;
if (current_avg < 0) current_avg = current_now;
if (charging) if (charging)
{ {
pwr_now = pwr_now;
have_power = 1; have_power = 1;
if (time_to_full >= 0) if (time_to_full >= 0)
{ {
@ -693,31 +740,26 @@ linux_sys_class_power_supply_check(void)
} }
else else
{ {
if (current_avg == 0) if (current == 0) time_left = 0;
time_left = 0; else if (current < 0) time_left = -1;
else if (current_avg < 0)
time_left = -1;
else else
{ {
pwr = ((pwr_full - pwr_now) * 3600) / current_avg; pwr = ((pwr_full - pwr_now) * 3600) / -current;
if (pwr > time_left) if (pwr > time_left) time_left = pwr;
time_left = pwr;
} }
} }
} }
else else
{ {
if (time_to_empty >= 0) have_power = 0;
{ if (time_to_empty >= 0) time_left += time_to_empty;
time_left += time_to_empty;
}
else else
{ {
if (time_to_full < 0) if (time_to_empty < 0)
{ {
if (current_avg > 0) if (current > 0)
{ {
pwr = ((pwr_now - pwr_empty) * 3600) / current_avg; pwr = ((pwr_now - pwr_empty) * 3600) / current;
time_left += pwr; time_left += pwr;
} }
} }
@ -729,7 +771,6 @@ linux_sys_class_power_supply_check(void)
} }
if (total_pwr_max > 0) if (total_pwr_max > 0)
battery_full = (total_pwr_now * 100) / total_pwr_max; battery_full = (total_pwr_now * 100) / total_pwr_max;
ecore_list_destroy(bats);
} }
} }

View File

@ -357,48 +357,51 @@ _battery_cb_exe_data(void *data, int type, void *event)
int have_power = 0; int have_power = 0;
Evas_List *l; Evas_List *l;
sscanf(ev->lines[i].line, "%i %i %i %i", if (sscanf(ev->lines[i].line, "%i %i %i %i",
&full, &time_left, &have_battery, &have_power); &full, &time_left, &have_battery, &have_power)
for (l = battery_config->instances; l; l = l->next) == 4)
{ {
Instance *inst; for (l = battery_config->instances; l; l = l->next)
inst = l->data;
if (have_power != battery_config->have_power)
{ {
if (have_power) Instance *inst;
edje_object_signal_emit(inst->o_battery, "e,state,charging", "e");
inst = l->data;
if (have_power != battery_config->have_power)
{
if (have_power)
edje_object_signal_emit(inst->o_battery, "e,state,charging", "e");
else
edje_object_signal_emit(inst->o_battery, "e,state,discharging", "e");
}
if (have_battery)
{
if (battery_config->full != full)
{
char buf[256];
snprintf(buf, sizeof(buf), "%i%%", full);
edje_object_part_text_set(inst->o_battery, "e.text.reading", buf);
_battery_face_level_set(inst, (double)full / 100.0);
}
}
else else
edje_object_signal_emit(inst->o_battery, "e,state,discharging", "e"); {
} edje_object_part_text_set(inst->o_battery, "e.text.reading", _("N/A"));
if (have_battery) _battery_face_level_set(inst, 0.0);
{ }
if (battery_config->full != full) if (time_left != battery_config->time_left)
{ {
char buf[256]; char buf[256];
int mins, hrs;
snprintf(buf, sizeof(buf), "%i%%", full); hrs = time_left / 3600;
edje_object_part_text_set(inst->o_battery, "e.text.reading", buf); mins = (time_left) / 60 - (hrs * 60);
_battery_face_level_set(inst, (double)full / 100.0); snprintf(buf, sizeof(buf), "%i:%02i", hrs, mins);
if (hrs < 0) hrs = 0;
if (mins < 0) mins = 0;
edje_object_part_text_set(inst->o_battery, "e.text.time", buf);
} }
} }
else
{
edje_object_part_text_set(inst->o_battery, "e.text.reading", _("N/A"));
_battery_face_level_set(inst, 0.0);
}
if (time_left != battery_config->time_left)
{
char buf[256];
int mins, hrs;
hrs = time_left / 3600;
mins = (time_left) / 60 - (hrs * 60);
snprintf(buf, sizeof(buf), "%i:%02i", hrs, mins);
if (hrs < 0) hrs = 0;
if (mins < 0) mins = 0;
edje_object_part_text_set(inst->o_battery, "e.text.time", buf);
}
} }
battery_config->full = full; battery_config->full = full;
battery_config->time_left = time_left; battery_config->time_left = time_left;