Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Linux /proc/acpi: check for ac_adapter states, other cleanup.
Still not tested, though!
  • Loading branch information
icculus committed Jun 30, 2009
1 parent 3684f69 commit 3eceea4
Showing 1 changed file with 66 additions and 28 deletions.
94 changes: 66 additions & 28 deletions src/power/linux/SDL_syspower.c
Expand Up @@ -34,26 +34,28 @@

#include "SDL_power.h"

static const char *proc_acpi_path = "/proc/acpi/battery";
static const char *proc_acpi_battery_path = "/proc/acpi/battery";
static const char *proc_acpi_ac_adapter_path = "/proc/acpi/ac_adapter";

static int open_acpi_file(const char *node, const char *key)
static int open_acpi_file(const char *base, const char *node, const char *key)
{
const size_t pathlen = strlen(proc_acpi_path)+strlen(node)+strlen(key)+3;
const size_t pathlen = strlen(base) + strlen(node) + strlen(key) + 3;
char *path = (char *) alloca(pathlen);
if (path == NULL) {
return -1; /* oh well. */
}

snprintf(path, pathlen, "%s/%s/%s", proc_acpi_path, node, key);
snprintf(path, pathlen, "%s/%s/%s", base, node, key);
return open(path, O_RDONLY);
}


static SDL_bool
load_acpi_file(const char *node, const char *key, char *buf, size_t buflen)
load_acpi_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(node, key);
const int fd = open_acpi_file(base, node, key);
if (fd == -1) {
return SDL_FALSE;
}
Expand All @@ -66,8 +68,9 @@ load_acpi_file(const char *node, const char *key, char *buf, size_t buflen)
return SDL_TRUE;
}


static SDL_bool
make_acpi_key_val(char **_ptr, char **_key, char **_val)
make_proc_acpi_key_val(char **_ptr, char **_key, char **_val)
{
char *ptr = *_ptr;

Expand Down Expand Up @@ -114,13 +117,12 @@ make_acpi_key_val(char **_ptr, char **_key, char **_val)
}

static void
check_acpi(const char * fname, SDL_bool * have_ac, SDL_bool * have_battery,
SDL_bool * charging, int *seconds, int *percent)
check_proc_acpi_battery(const char * node, SDL_bool * have_battery,
SDL_bool * charging, int *seconds, int *percent)
{
int fd = -1;
const char *base = proc_acpi_battery_path;
char info[1024];
char state[1024];
ssize_t br = 0;
char *ptr = NULL;
char *key = NULL;
char *val = NULL;
Expand All @@ -132,30 +134,23 @@ check_acpi(const char * fname, SDL_bool * have_ac, SDL_bool * have_battery,
int secs = -1;
int pct = -1;

if (!load_acpi_file(fname, "state", state, sizeof (state))) {
if (!load_acpi_file(base, node, "state", state, sizeof (state))) {
return;
} else if (!load_acpi_file(fname, "info", info, sizeof (info))) {
} else if (!load_acpi_file(base, node, "info", info, sizeof (info))) {
return;
}

ptr = &state[0];
while (make_acpi_key_val(&ptr, &key, &val)) {
while (make_proc_acpi_key_val(&ptr, &key, &val)) {
if (strcmp(key, "present") == 0) {
if (strcmp(val, "yes") == 0) {
*have_battery = SDL_TRUE;
}
} else if (strcmp(key, "charging state") == 0) {
/* !!! FIXME: what exactly _does_ charging/discharging mean? */
if (strcmp(val, "charging/discharging") == 0) {
*have_ac = is_ac = SDL_TRUE;
charge = SDL_TRUE;
} else if (strcmp(val, "charging") == 0) {
*have_ac = is_ac = SDL_TRUE;
charge = SDL_TRUE;
} else if (strcmp(val, "charged") == 0) {
/* !!! FIXME: maybe another battery is discharging,
!!! FIXME: instead of AC connection. */
*have_ac = is_ac = SDL_TRUE;
charge = SDL_TRUE;
}
} else if (strcmp(key, "remaining capacity") == 0) {
Expand All @@ -166,9 +161,9 @@ check_acpi(const char * fname, SDL_bool * have_ac, SDL_bool * have_battery,
}
}
}

ptr = &info[0];
while (make_acpi_key_val(&ptr, &key, &val)) {
while (make_proc_acpi_key_val(&ptr, &key, &val)) {
if (strcmp(key, "design capacity") == 0) {
char *endptr = NULL;
const int cvt = (int) strtol(val, &endptr, 10);
Expand Down Expand Up @@ -209,31 +204,74 @@ check_acpi(const char * fname, SDL_bool * have_ac, SDL_bool * have_battery,
*percent = pct;
*charging = charge;
}
}

static void
check_proc_acpi_ac_adapter(const char * node, SDL_bool * have_ac)
{
const char *base = proc_acpi_ac_adapter_path;
char state[256];
char *ptr = NULL;
char *key = NULL;
char *val = NULL;
SDL_bool charge = SDL_FALSE;
SDL_bool choose = SDL_FALSE;
SDL_bool is_ac = SDL_FALSE;
int maximum = -1;
int remaining = -1;
int secs = -1;
int pct = -1;

if (!load_acpi_file(base, node, "state", state, sizeof (state))) {
return;
}

ptr = &state[0];
while (make_proc_acpi_key_val(&ptr, &key, &val)) {
if (strcmp(key, "state") == 0) {
if (strcmp(val, "on-line") == 0) {
*have_ac = SDL_TRUE;
}
}
}
}


SDL_bool
SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState * state,
int *seconds, int *percent)
{
struct dirent *dent = NULL;
DIR *dirp = NULL;
SDL_bool have_ac = SDL_FALSE;
SDL_bool have_battery = SDL_FALSE;
SDL_bool have_ac = SDL_FALSE;
SDL_bool charging = SDL_FALSE;

*seconds = -1;
*percent = -1;
*state = SDL_POWERSTATE_UNKNOWN;

dirp = opendir(proc_acpi_path);
dirp = opendir(proc_acpi_battery_path);
if (dirp == NULL) {
return SDL_FALSE; /* can't use this interface. */
} else {
while ((dent = readdir(dirp)) != NULL) {
const char *node = dent->d_name;
check_proc_acpi_battery(node, &have_battery, &charging,
seconds, percent);
}
closedir(dirp);
}

while ((dent = readdir(dirp)) != NULL) {
const char *name = dent->d_name;
check_acpi(name, &have_ac, &have_battery, &charging, seconds, percent);
dirp = opendir(proc_acpi_ac_adapter_path);
if (dirp == NULL) {
return SDL_FALSE; /* can't use this interface. */
} else {
while ((dent = readdir(dirp)) != NULL) {
const char *node = dent->d_name;
check_proc_acpi_ac_adapter(node, &have_ac);
}
closedir(dirp);
}

if (!have_battery) {
Expand Down

0 comments on commit 3eceea4

Please sign in to comment.