src/power/linux/SDL_syspower.c
changeset 3170 b7a48f533966
child 3174 c8b9c6d27476
equal deleted inserted replaced
3169:f294338ca6eb 3170:b7a48f533966
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2009 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Lesser General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2.1 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Lesser General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Lesser General Public
       
    16     License along with this library; if not, write to the Free Software
       
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 #include "SDL_config.h"
       
    23 
       
    24 #ifndef SDL_POWER_DISABLED
       
    25 #ifdef SDL_POWER_LINUX
       
    26 
       
    27 #include <stdio.h>
       
    28 #include <unistd.h>
       
    29 
       
    30 #include "SDL_power.h"
       
    31 
       
    32 SDL_bool
       
    33 SDL_GetPowerInfo_Linux_sys_power(SDL_PowerState *state,
       
    34                                  int *seconds, int *percent)
       
    35 {
       
    36     return SDL_FALSE;  /* !!! FIXME: write me. */
       
    37 #if 0
       
    38     const int fd = open("/sys/power", O_RDONLY);
       
    39     if (fd == -1) {
       
    40         return SDL_FALSE;  /* can't use this interface. */
       
    41     }
       
    42     return SDL_TRUE;
       
    43 #endif
       
    44 }
       
    45 
       
    46 SDL_bool
       
    47 SDL_GetPowerInfo_Linux_sys_proc_acpi(SDL_PowerState *state,
       
    48                                      int *seconds, int *percent)
       
    49 {
       
    50     return SDL_FALSE;  /* !!! FIXME: write me. */
       
    51 #if 0
       
    52     const int fd = open("/proc/acpi", O_RDONLY);
       
    53     if (fd == -1) {
       
    54         return SDL_FALSE;  /* can't use this interface. */
       
    55     }
       
    56     return SDL_TRUE;
       
    57 #endif
       
    58 }
       
    59 
       
    60 static SDL_bool
       
    61 next_string(char **_ptr, char **_str)
       
    62 {
       
    63     char *ptr = *_ptr;
       
    64     char *str = *_str;
       
    65 
       
    66     while (*ptr == ' ') {  /* skip any spaces... */
       
    67         ptr++;
       
    68     }
       
    69 
       
    70     if (*ptr == '\0') {
       
    71         return SDL_FALSE;
       
    72     }
       
    73 
       
    74     str = ptr;
       
    75     while ((*ptr != ' ') && (*ptr != '\0'))
       
    76         ptr++;
       
    77 
       
    78     if (*ptr != '\0')
       
    79         *(ptr++) = '\0';
       
    80 
       
    81     *_str = str;
       
    82     *_ptr = ptr;
       
    83     return SDL_TRUE;
       
    84 }
       
    85 
       
    86 static SDL_bool
       
    87 int_string(char *str, int *val)
       
    88 {
       
    89     char *endptr = NULL;
       
    90     *val = (int) strtol(str+2, &endptr, 16);
       
    91     return ((*str != '\0') && (*endptr == '\0'));
       
    92 }
       
    93 
       
    94 /* http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c */
       
    95 SDL_bool
       
    96 SDL_GetPowerInfo_Linux_sys_proc_apm(SDL_PowerState *state,
       
    97                                     int *seconds, int *percent)
       
    98 {
       
    99     SDL_bool need_details = SDL_FALSE;
       
   100     int ac_status = 0;
       
   101     int battery_status = 0;
       
   102     int battery_flag = 0;
       
   103     int battery_percent = 0;
       
   104     int battery_time = 0;
       
   105     const int fd = open("/proc/apm", O_RDONLY);
       
   106     char buf[128];
       
   107     char *ptr = &buf[0];
       
   108     char *str = NULL;
       
   109     ssize_t br;
       
   110 
       
   111     if (fd == -1) {
       
   112         return SDL_FALSE;  /* can't use this interface. */
       
   113     }
       
   114 
       
   115     br = read(fd, buf, sizeof (buf) - 1);
       
   116     close(fd);
       
   117 
       
   118     if (br < 0) {
       
   119         return SDL_FALSE;
       
   120     }
       
   121 
       
   122     buf[br] = '\0';  // null-terminate the string.
       
   123     if (!next_string(&ptr, &str)) {  /* driver version */
       
   124         return SDL_FALSE;
       
   125     }
       
   126     if (!next_string(&ptr, &str)) {  /* BIOS version */
       
   127         return SDL_FALSE;
       
   128     }
       
   129     if (!next_string(&ptr, &str)) {  /* APM flags */
       
   130         return SDL_FALSE;
       
   131     }
       
   132 
       
   133     if (!next_string(&ptr, &str)) {  /* AC line status */
       
   134         return SDL_FALSE;
       
   135     } else if (!int_string(str, &ac_status)) {
       
   136         return SDL_FALSE;
       
   137     }
       
   138 
       
   139     if (!next_string(&ptr, &str)) {  /* battery status */
       
   140         return SDL_FALSE;
       
   141     } else if (!int_string(str, &battery_status)) {
       
   142         return SDL_FALSE;
       
   143     }
       
   144     if (!next_string(&ptr, &str)) {  /* battery flag */
       
   145         return SDL_FALSE;
       
   146     } else if (!int_string(str, &battery_flag)) {
       
   147         return SDL_FALSE;
       
   148     }
       
   149     if (!next_string(&ptr, &str)) {  /* remaining battery life percent */
       
   150         return SDL_FALSE;
       
   151     }
       
   152     if (str[strlen(str) - 1] == '%') {
       
   153         str[strlen(str) - 1] = '\0';
       
   154     }
       
   155     if (!int_string(str, &battery_percent)) {
       
   156         return SDL_FALSE;
       
   157     }
       
   158 
       
   159     if (!next_string(&ptr, &str)) {  /* remaining battery life time */
       
   160         return SDL_FALSE;
       
   161     } else if (!int_string(str, &battery_time)) {
       
   162         return SDL_FALSE;
       
   163     }
       
   164 
       
   165     if (!next_string(&ptr, &str)) {  /* remaining battery life time units */
       
   166         return SDL_FALSE;
       
   167     } else if (strcmp(str, "min") == 0) {
       
   168         battery_time *= 60;
       
   169     }
       
   170 
       
   171     if (battery_flag == 0xFF) {  /* unknown state */
       
   172         *state = SDL_POWERSTATE_UNKNOWN;
       
   173     } else if (battery_flag & (1 << 7)) {  /* no battery */
       
   174         *state = SDL_POWERSTATE_NO_BATTERY;
       
   175     } else if (battery_flag & (1 << 3)) {  /* charging */
       
   176         *state = SDL_POWERSTATE_CHARGING;
       
   177         need_details = SDL_TRUE;
       
   178     } else if (ac_status == 1) {
       
   179         *state = SDL_POWERSTATE_CHARGED;  /* on AC, not charging. */
       
   180         need_details = SDL_TRUE;
       
   181     } else {
       
   182         *state = SDL_POWERSTATE_ON_BATTERY;
       
   183         need_details = SDL_TRUE;
       
   184     }
       
   185 
       
   186     *percent = -1;
       
   187     *seconds = -1;
       
   188     if (need_details) {
       
   189         const int pct = battery_percent;
       
   190         const int secs = battery_time;
       
   191 
       
   192         if (pct >= 0) {  /* -1 == unknown */
       
   193             *percent = (pct > 100) ? 100 : pct;  /* clamp between 0%, 100% */
       
   194         }
       
   195         if (secs >= 0) {  /* -1 == unknown */
       
   196             *seconds = secs;
       
   197         }
       
   198     }
       
   199 
       
   200     return SDL_TRUE;
       
   201 }
       
   202 
       
   203 #endif /* SDL_POWER_LINUX */
       
   204 #endif /* SDL_POWER_DISABLED */
       
   205 
       
   206 /* vi: set ts=4 sw=4 expandtab: */
       
   207