Mercurial > sdl-ios-xcode
diff src/power/linux/SDL_syspower.c @ 3170:b7a48f533966
Initial work on power subsystem for SDL 1.3.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 07 Jun 2009 06:06:35 +0000 |
parents | |
children | c8b9c6d27476 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/power/linux/SDL_syspower.c Sun Jun 07 06:06:35 2009 +0000 @@ -0,0 +1,207 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_LINUX + +#include <stdio.h> +#include <unistd.h> + +#include "SDL_power.h" + +SDL_bool +SDL_GetPowerInfo_Linux_sys_power(SDL_PowerState *state, + int *seconds, int *percent) +{ + return SDL_FALSE; /* !!! FIXME: write me. */ +#if 0 + const int fd = open("/sys/power", O_RDONLY); + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + return SDL_TRUE; +#endif +} + +SDL_bool +SDL_GetPowerInfo_Linux_sys_proc_acpi(SDL_PowerState *state, + int *seconds, int *percent) +{ + return SDL_FALSE; /* !!! FIXME: write me. */ +#if 0 + const int fd = open("/proc/acpi", O_RDONLY); + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + return SDL_TRUE; +#endif +} + +static SDL_bool +next_string(char **_ptr, char **_str) +{ + char *ptr = *_ptr; + char *str = *_str; + + while (*ptr == ' ') { /* skip any spaces... */ + ptr++; + } + + if (*ptr == '\0') { + return SDL_FALSE; + } + + str = ptr; + while ((*ptr != ' ') && (*ptr != '\0')) + ptr++; + + if (*ptr != '\0') + *(ptr++) = '\0'; + + *_str = str; + *_ptr = ptr; + return SDL_TRUE; +} + +static SDL_bool +int_string(char *str, int *val) +{ + char *endptr = NULL; + *val = (int) strtol(str+2, &endptr, 16); + return ((*str != '\0') && (*endptr == '\0')); +} + +/* http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c */ +SDL_bool +SDL_GetPowerInfo_Linux_sys_proc_apm(SDL_PowerState *state, + int *seconds, int *percent) +{ + SDL_bool need_details = SDL_FALSE; + int ac_status = 0; + int battery_status = 0; + int battery_flag = 0; + int battery_percent = 0; + int battery_time = 0; + const int fd = open("/proc/apm", O_RDONLY); + char buf[128]; + char *ptr = &buf[0]; + char *str = NULL; + ssize_t br; + + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + + br = read(fd, buf, sizeof (buf) - 1); + close(fd); + + if (br < 0) { + return SDL_FALSE; + } + + buf[br] = '\0'; // null-terminate the string. + if (!next_string(&ptr, &str)) { /* driver version */ + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* BIOS version */ + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* APM flags */ + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* AC line status */ + return SDL_FALSE; + } else if (!int_string(str, &ac_status)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* battery status */ + return SDL_FALSE; + } else if (!int_string(str, &battery_status)) { + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* battery flag */ + return SDL_FALSE; + } else if (!int_string(str, &battery_flag)) { + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* remaining battery life percent */ + return SDL_FALSE; + } + if (str[strlen(str) - 1] == '%') { + str[strlen(str) - 1] = '\0'; + } + if (!int_string(str, &battery_percent)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* remaining battery life time */ + return SDL_FALSE; + } else if (!int_string(str, &battery_time)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* remaining battery life time units */ + return SDL_FALSE; + } else if (strcmp(str, "min") == 0) { + battery_time *= 60; + } + + if (battery_flag == 0xFF) { /* unknown state */ + *state = SDL_POWERSTATE_UNKNOWN; + } else if (battery_flag & (1 << 7)) { /* no battery */ + *state = SDL_POWERSTATE_NO_BATTERY; + } else if (battery_flag & (1 << 3)) { /* charging */ + *state = SDL_POWERSTATE_CHARGING; + need_details = SDL_TRUE; + } else if (ac_status == 1) { + *state = SDL_POWERSTATE_CHARGED; /* on AC, not charging. */ + need_details = SDL_TRUE; + } else { + *state = SDL_POWERSTATE_ON_BATTERY; + need_details = SDL_TRUE; + } + + *percent = -1; + *seconds = -1; + if (need_details) { + const int pct = battery_percent; + const int secs = battery_time; + + if (pct >= 0) { /* -1 == unknown */ + *percent = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */ + } + if (secs >= 0) { /* -1 == unknown */ + *seconds = secs; + } + } + + return SDL_TRUE; +} + +#endif /* SDL_POWER_LINUX */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ +