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