Add support for the new sysfs acpi power interface. With 2.6.24 kernels, the procfs inteface has been marked deprecated. Few people have tested without issues.

SVN revision: 33644
This commit is contained in:
Nicholas Hughart 2008-01-28 20:37:00 +00:00
parent 6de51f5ec4
commit e6acbda91b
2 changed files with 263 additions and 5 deletions

View File

@ -62,6 +62,7 @@ static void _menu_cb_post(void *data, E_Menu *m);
static Status *_battery_linux_acpi_check(void);
static Status *_battery_linux_apm_check(void);
static Status *_battery_linux_powerbook_check(void);
static Status *_battery_linux_sys_acpi_check(void);
#ifdef __FreeBSD__
static Status *_battery_bsd_acpi_check(void);
static Status *_battery_bsd_apm_check(void);
@ -250,8 +251,10 @@ _battery_cb_check(void *data)
#else
if (battery_config->battery_check_mode == 0)
{
if (ecore_file_is_dir("/proc/acpi"))
if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */
battery_config->battery_check_mode = CHECK_ACPI;
else if (ecore_file_is_dir("/sys/class/power_supply")) /* >= 2.6.24 */
battery_config->battery_check_mode = CHECK_SYS_ACPI;
else if (ecore_file_exists("/proc/apm"))
battery_config->battery_check_mode = CHECK_APM;
else if (ecore_file_is_dir("/proc/pmu"))
@ -268,6 +271,9 @@ _battery_cb_check(void *data)
case CHECK_PMU:
ret = _battery_linux_powerbook_check();
break;
case CHECK_SYS_ACPI:
ret = _battery_linux_sys_acpi_check();
break;
default:
break;
}
@ -368,6 +374,257 @@ _battery_cb_check(void *data)
return 1;
}
static Status *
_battery_linux_sys_acpi_check(void)
{
Ecore_List *bats;
char buf[4096], buf2[4096];
char *name;
int bat_max = 0;
int bat_filled = 0;
int bat_level = 0;
int bat_drain = 1;
int bat_val = 0;
int discharging = 0;
int charging = 0;
int battery = 0;
int design_cap_unknown = 0;
int last_full_unknown = 0;
int rate_unknown = 0;
int level_unknown = 0;
int hours, minutes;
Status *stat;
static double last_poll_time = 0.0;
double poll_time, t;
stat = E_NEW(Status, 1);
if (!stat) return NULL;
t = ecore_time_get();
poll_time = t - last_poll_time;
last_poll_time = t;
/* Read some information on first run. */
bats = ecore_file_ls("/sys/class/power_supply/");
if (bats)
{
while ((name = ecore_list_next(bats)))
{
FILE *f;
int design_cap = 0;
int last_full = 0;
int present = 0;
char *charging_state = NULL;
int rate = 1;
int level = 0;
if (name && strncmp("BAT",name,3)) continue;
/* present */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/present", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
present = atoi(buf2);
fclose(f);
}
/* design capacity */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
design_cap = atoi(buf2);
if(!design_cap) design_cap_unknown++;
fclose(f);
}
/* last full capacity */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
last_full = atoi(buf2);
if(!last_full) last_full_unknown++;
fclose(f);
}
/* charging state */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/status", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
charging_state = strdup(buf2);
fclose(f);
}
/* present rate */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
rate = atoi(buf2);
fclose(f);
}
/* remaining capacity */
snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_now", name);
f = fopen(buf, "r");
if (f)
{
fgets(buf2, sizeof(buf2), f);
level = atoi(buf2);
if(!level) level_unknown++;
fclose(f);
}
if (present) battery++;
if (charging_state)
{
if (!strncmp(charging_state, "Discharging", strlen("Discharging")))
{
discharging++;
if ((rate == 0) && (rate_unknown == 0)) rate_unknown++;
}
else if (!strncmp(charging_state, "Charging", strlen("Charging")))
{
charging++;
if ((rate == 0) && (rate_unknown == 0)) rate_unknown++;
}
else if (!strncmp(charging_state, "Full", strlen("Full")))
{
rate_unknown--;
}
free(charging_state);
}
bat_drain += rate;
bat_level += level;
bat_max += design_cap;
bat_filled += last_full;
}
ecore_list_destroy(bats);
}
if ((rate_unknown) && (bat_level != battery_config->battery_prev_level) &&
(battery_config->battery_prev_level >= 0) && (poll_time > 0.0))
{
bat_drain =
((bat_level - battery_config->battery_prev_level) * 60 * 60) /
poll_time;
if (bat_drain < 0) bat_drain = -bat_drain;
if (bat_drain == 0) bat_drain = 1;
rate_unknown = 0;
}
else
{
if (battery_config->battery_prev_drain < 1)
battery_config->battery_prev_drain = 1;
if (bat_drain < 1)
bat_drain = battery_config->battery_prev_drain;
battery_config->battery_prev_drain = bat_drain;
}
if (bat_filled > 0) bat_val = (100 * bat_level) / bat_filled;
else bat_val = 100;
battery_config->battery_prev_level = bat_level;
if (discharging) minutes = (60 * bat_level) / bat_drain;
else
{
/* FIXME: Batteries charge in paralell! */
if (bat_filled > 0)
minutes = (60 * (bat_filled - bat_level)) / bat_drain;
else
minutes = 0;
}
hours = minutes / 60;
minutes -= (hours * 60);
if (hours < 0) hours = 0;
if (minutes < 0) minutes = 0;
if (!battery)
{
stat->has_battery = 0;
stat->state = BATTERY_STATE_NONE;
stat->reading = strdup(_("N/A"));
stat->time = strdup("--:--");
stat->level = 1.0;
}
else if ((charging) || (discharging))
{
battery_config->battery_prev_battery = 1;
stat->has_battery = 1;
if (charging)
{
stat->state = BATTERY_STATE_CHARGING;
battery_config->alarm_triggered = 0;
}
else if (discharging)
{
stat->state = BATTERY_STATE_DISCHARGING;
if (stat->level < 0.1)
{
if (((hours * 60) + minutes) <= battery_config->alarm)
stat->alarm = 1;
if (bat_val <= battery_config->alarm_p)
stat->alarm = 1;
}
}
if (level_unknown)
{
stat->reading = strdup(_("BAD DRIVER"));
stat->time = strdup("--:--");
stat->level = 0.0;
}
else if (rate_unknown)
{
snprintf(buf, sizeof(buf), "%i%%", bat_val);
stat->reading = strdup(buf);
stat->time = strdup("--:--");
stat->level = (double)bat_val / 100.0;
}
else
{
snprintf(buf, sizeof(buf), "%i%%", bat_val);
stat->reading = strdup(buf);
snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes);
stat->time = strdup(buf);
stat->level = (double)bat_val / 100.0;
}
}
else
{
stat->has_battery = 1;
stat->state = BATTERY_STATE_NONE;
stat->reading = strdup(_("FULL"));
stat->time = strdup("--:--");
stat->level = 1.0;
}
return stat;
}
static Status *
_battery_linux_acpi_check(void)
{

View File

@ -11,6 +11,7 @@ typedef struct _Status Status;
#define CHECK_ACPI 1
#define CHECK_APM 2
#define CHECK_PMU 3
#define CHECK_SYS_ACPI 4
struct _Config
{