|
@@ -36,8 +36,10 @@ |
|
|
static const char *proc_apm_path = "/proc/apm"; |
|
|
static const char *proc_acpi_battery_path = "/proc/acpi/battery"; |
|
|
static const char *proc_acpi_ac_adapter_path = "/proc/acpi/ac_adapter"; |
|
|
static const char *sys_class_power_supply_path = "/sys/class/power_supply"; |
|
|
|
|
|
static int open_acpi_file(const char *base, const char *node, const char *key) |
|
|
static int |
|
|
open_power_file(const char *base, const char *node, const char *key) |
|
|
{ |
|
|
const size_t pathlen = strlen(base) + strlen(node) + strlen(key) + 3; |
|
|
char *path = (char *) alloca(pathlen); |
|
@@ -51,11 +53,11 @@ static int open_acpi_file(const char *base, const char *node, const char *key) |
|
|
|
|
|
|
|
|
static SDL_bool |
|
|
load_acpi_file(const char *base, const char *node, const char *key, |
|
|
char *buf, size_t buflen) |
|
|
read_power_file(const char *base, const char *node, const char *key, |
|
|
char *buf, size_t buflen) |
|
|
{ |
|
|
ssize_t br = 0; |
|
|
const int fd = open_acpi_file(base, node, key); |
|
|
const int fd = open_power_file(base, node, key); |
|
|
if (fd == -1) { |
|
|
return SDL_FALSE; |
|
|
} |
|
@@ -133,9 +135,9 @@ check_proc_acpi_battery(const char * node, SDL_bool * have_battery, |
|
|
int secs = -1; |
|
|
int pct = -1; |
|
|
|
|
|
if (!load_acpi_file(base, node, "state", state, sizeof (state))) { |
|
|
if (!read_power_file(base, node, "state", state, sizeof (state))) { |
|
|
return; |
|
|
} else if (!load_acpi_file(base, node, "info", info, sizeof (info))) { |
|
|
} else if (!read_power_file(base, node, "info", info, sizeof (info))) { |
|
|
return; |
|
|
} |
|
|
|
|
@@ -214,7 +216,7 @@ check_proc_acpi_ac_adapter(const char * node, SDL_bool * have_ac) |
|
|
char *key = NULL; |
|
|
char *val = NULL; |
|
|
|
|
|
if (!load_acpi_file(base, node, "state", state, sizeof (state))) { |
|
|
if (!read_power_file(base, node, "state", state, sizeof (state))) { |
|
|
return; |
|
|
} |
|
|
|
|
@@ -423,6 +425,94 @@ SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState * state, |
|
|
return SDL_TRUE; |
|
|
} |
|
|
|
|
|
/* !!! FIXME: implement d-bus queries to org.freedesktop.UPower. */ |
|
|
|
|
|
SDL_bool |
|
|
SDL_GetPowerInfo_Linux_sys_class_power_supply(SDL_PowerState *state, int *seconds, int *percent) |
|
|
{ |
|
|
const char *base = sys_class_power_supply_path; |
|
|
struct dirent *dent; |
|
|
DIR *dirp; |
|
|
|
|
|
dirp = opendir(base); |
|
|
if (!dirp) { |
|
|
return SDL_FALSE; |
|
|
} |
|
|
|
|
|
*state = SDL_POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */ |
|
|
*seconds = -1; |
|
|
*percent = -1; |
|
|
|
|
|
while ((dent = readdir(dirp)) != NULL) { |
|
|
const char *name = dent->d_name; |
|
|
SDL_bool choose = SDL_FALSE; |
|
|
char str[64]; |
|
|
SDL_PowerState st; |
|
|
int secs; |
|
|
int pct; |
|
|
|
|
|
if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) { |
|
|
continue; /* skip these, of course. */ |
|
|
} else if (!read_power_file(base, name, "type", str, sizeof (str))) { |
|
|
continue; /* Don't know _what_ we're looking at. Give up on it. */ |
|
|
} else if (SDL_strcmp(str, "Battery\n") != 0) { |
|
|
continue; /* we don't care about UPS and such. */ |
|
|
} |
|
|
|
|
|
/* some drivers don't offer this, so if it's not explicitly reported assume it's present. */ |
|
|
if (read_power_file(base, name, "present", str, sizeof (str)) && (SDL_strcmp(str, "0\n") == 0)) { |
|
|
st = SDL_POWERSTATE_NO_BATTERY; |
|
|
} else if (!read_power_file(base, name, "status", str, sizeof (str))) { |
|
|
st = SDL_POWERSTATE_UNKNOWN; /* uh oh */ |
|
|
} else if (SDL_strcmp(str, "Charging\n") == 0) { |
|
|
st = SDL_POWERSTATE_CHARGING; |
|
|
} else if (SDL_strcmp(str, "Discharging\n") == 0) { |
|
|
st = SDL_POWERSTATE_ON_BATTERY; |
|
|
} else if ((SDL_strcmp(str, "Full\n") == 0) || (SDL_strcmp(str, "Not charging\n") == 0)) { |
|
|
st = SDL_POWERSTATE_CHARGED; |
|
|
} else { |
|
|
st = SDL_POWERSTATE_UNKNOWN; /* uh oh */ |
|
|
} |
|
|
|
|
|
if (!read_power_file(base, name, "capacity", str, sizeof (str))) { |
|
|
pct = -1; |
|
|
} else { |
|
|
pct = SDL_atoi(str); |
|
|
pct = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */ |
|
|
} |
|
|
|
|
|
if (!read_power_file(base, name, "time_to_empty_now", str, sizeof (str))) { |
|
|
secs = -1; |
|
|
} else { |
|
|
secs = SDL_atoi(str); |
|
|
secs = (secs <= 0) ? -1 : secs; /* 0 == unknown */ |
|
|
} |
|
|
|
|
|
/* |
|
|
* We pick the battery that claims to have the most minutes left. |
|
|
* (failing a report of minutes, we'll take the highest percent.) |
|
|
*/ |
|
|
if ((secs < 0) && (*seconds < 0)) { |
|
|
if ((pct < 0) && (*percent < 0)) { |
|
|
choose = SDL_TRUE; /* at least we know there's a battery. */ |
|
|
} else if (pct > *percent) { |
|
|
choose = SDL_TRUE; |
|
|
} |
|
|
} else if (secs > *seconds) { |
|
|
choose = SDL_TRUE; |
|
|
} |
|
|
|
|
|
if (choose) { |
|
|
*seconds = secs; |
|
|
*percent = pct; |
|
|
*state = st; |
|
|
} |
|
|
} |
|
|
|
|
|
closedir(dirp); |
|
|
return SDL_TRUE; /* don't look any further. */ |
|
|
} |
|
|
|
|
|
#endif /* SDL_POWER_LINUX */ |
|
|
#endif /* SDL_POWER_DISABLED */ |
|
|
|
|
|