src/power/linux/SDL_syspower.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 07 Jun 2009 06:06:35 +0000
changeset 3170 b7a48f533966
child 3174 c8b9c6d27476
permissions -rw-r--r--
Initial work on power subsystem for SDL 1.3.
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
icculus@3170
    30
#include "SDL_power.h"
icculus@3170
    31
icculus@3170
    32
SDL_bool
icculus@3170
    33
SDL_GetPowerInfo_Linux_sys_power(SDL_PowerState *state,
icculus@3170
    34
                                 int *seconds, int *percent)
icculus@3170
    35
{
icculus@3170
    36
    return SDL_FALSE;  /* !!! FIXME: write me. */
icculus@3170
    37
#if 0
icculus@3170
    38
    const int fd = open("/sys/power", O_RDONLY);
icculus@3170
    39
    if (fd == -1) {
icculus@3170
    40
        return SDL_FALSE;  /* can't use this interface. */
icculus@3170
    41
    }
icculus@3170
    42
    return SDL_TRUE;
icculus@3170
    43
#endif
icculus@3170
    44
}
icculus@3170
    45
icculus@3170
    46
SDL_bool
icculus@3170
    47
SDL_GetPowerInfo_Linux_sys_proc_acpi(SDL_PowerState *state,
icculus@3170
    48
                                     int *seconds, int *percent)
icculus@3170
    49
{
icculus@3170
    50
    return SDL_FALSE;  /* !!! FIXME: write me. */
icculus@3170
    51
#if 0
icculus@3170
    52
    const int fd = open("/proc/acpi", O_RDONLY);
icculus@3170
    53
    if (fd == -1) {
icculus@3170
    54
        return SDL_FALSE;  /* can't use this interface. */
icculus@3170
    55
    }
icculus@3170
    56
    return SDL_TRUE;
icculus@3170
    57
#endif
icculus@3170
    58
}
icculus@3170
    59
icculus@3170
    60
static SDL_bool
icculus@3170
    61
next_string(char **_ptr, char **_str)
icculus@3170
    62
{
icculus@3170
    63
    char *ptr = *_ptr;
icculus@3170
    64
    char *str = *_str;
icculus@3170
    65
icculus@3170
    66
    while (*ptr == ' ') {  /* skip any spaces... */
icculus@3170
    67
        ptr++;
icculus@3170
    68
    }
icculus@3170
    69
icculus@3170
    70
    if (*ptr == '\0') {
icculus@3170
    71
        return SDL_FALSE;
icculus@3170
    72
    }
icculus@3170
    73
icculus@3170
    74
    str = ptr;
icculus@3170
    75
    while ((*ptr != ' ') && (*ptr != '\0'))
icculus@3170
    76
        ptr++;
icculus@3170
    77
icculus@3170
    78
    if (*ptr != '\0')
icculus@3170
    79
        *(ptr++) = '\0';
icculus@3170
    80
icculus@3170
    81
    *_str = str;
icculus@3170
    82
    *_ptr = ptr;
icculus@3170
    83
    return SDL_TRUE;
icculus@3170
    84
}
icculus@3170
    85
icculus@3170
    86
static SDL_bool
icculus@3170
    87
int_string(char *str, int *val)
icculus@3170
    88
{
icculus@3170
    89
    char *endptr = NULL;
icculus@3170
    90
    *val = (int) strtol(str+2, &endptr, 16);
icculus@3170
    91
    return ((*str != '\0') && (*endptr == '\0'));
icculus@3170
    92
}
icculus@3170
    93
icculus@3170
    94
/* http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c */
icculus@3170
    95
SDL_bool
icculus@3170
    96
SDL_GetPowerInfo_Linux_sys_proc_apm(SDL_PowerState *state,
icculus@3170
    97
                                    int *seconds, int *percent)
icculus@3170
    98
{
icculus@3170
    99
    SDL_bool need_details = SDL_FALSE;
icculus@3170
   100
    int ac_status = 0;
icculus@3170
   101
    int battery_status = 0;
icculus@3170
   102
    int battery_flag = 0;
icculus@3170
   103
    int battery_percent = 0;
icculus@3170
   104
    int battery_time = 0;
icculus@3170
   105
    const int fd = open("/proc/apm", O_RDONLY);
icculus@3170
   106
    char buf[128];
icculus@3170
   107
    char *ptr = &buf[0];
icculus@3170
   108
    char *str = NULL;
icculus@3170
   109
    ssize_t br;
icculus@3170
   110
icculus@3170
   111
    if (fd == -1) {
icculus@3170
   112
        return SDL_FALSE;  /* can't use this interface. */
icculus@3170
   113
    }
icculus@3170
   114
icculus@3170
   115
    br = read(fd, buf, sizeof (buf) - 1);
icculus@3170
   116
    close(fd);
icculus@3170
   117
icculus@3170
   118
    if (br < 0) {
icculus@3170
   119
        return SDL_FALSE;
icculus@3170
   120
    }
icculus@3170
   121
icculus@3170
   122
    buf[br] = '\0';  // null-terminate the string.
icculus@3170
   123
    if (!next_string(&ptr, &str)) {  /* driver version */
icculus@3170
   124
        return SDL_FALSE;
icculus@3170
   125
    }
icculus@3170
   126
    if (!next_string(&ptr, &str)) {  /* BIOS version */
icculus@3170
   127
        return SDL_FALSE;
icculus@3170
   128
    }
icculus@3170
   129
    if (!next_string(&ptr, &str)) {  /* APM flags */
icculus@3170
   130
        return SDL_FALSE;
icculus@3170
   131
    }
icculus@3170
   132
icculus@3170
   133
    if (!next_string(&ptr, &str)) {  /* AC line status */
icculus@3170
   134
        return SDL_FALSE;
icculus@3170
   135
    } else if (!int_string(str, &ac_status)) {
icculus@3170
   136
        return SDL_FALSE;
icculus@3170
   137
    }
icculus@3170
   138
icculus@3170
   139
    if (!next_string(&ptr, &str)) {  /* battery status */
icculus@3170
   140
        return SDL_FALSE;
icculus@3170
   141
    } else if (!int_string(str, &battery_status)) {
icculus@3170
   142
        return SDL_FALSE;
icculus@3170
   143
    }
icculus@3170
   144
    if (!next_string(&ptr, &str)) {  /* battery flag */
icculus@3170
   145
        return SDL_FALSE;
icculus@3170
   146
    } else if (!int_string(str, &battery_flag)) {
icculus@3170
   147
        return SDL_FALSE;
icculus@3170
   148
    }
icculus@3170
   149
    if (!next_string(&ptr, &str)) {  /* remaining battery life percent */
icculus@3170
   150
        return SDL_FALSE;
icculus@3170
   151
    }
icculus@3170
   152
    if (str[strlen(str) - 1] == '%') {
icculus@3170
   153
        str[strlen(str) - 1] = '\0';
icculus@3170
   154
    }
icculus@3170
   155
    if (!int_string(str, &battery_percent)) {
icculus@3170
   156
        return SDL_FALSE;
icculus@3170
   157
    }
icculus@3170
   158
icculus@3170
   159
    if (!next_string(&ptr, &str)) {  /* remaining battery life time */
icculus@3170
   160
        return SDL_FALSE;
icculus@3170
   161
    } else if (!int_string(str, &battery_time)) {
icculus@3170
   162
        return SDL_FALSE;
icculus@3170
   163
    }
icculus@3170
   164
icculus@3170
   165
    if (!next_string(&ptr, &str)) {  /* remaining battery life time units */
icculus@3170
   166
        return SDL_FALSE;
icculus@3170
   167
    } else if (strcmp(str, "min") == 0) {
icculus@3170
   168
        battery_time *= 60;
icculus@3170
   169
    }
icculus@3170
   170
icculus@3170
   171
    if (battery_flag == 0xFF) {  /* unknown state */
icculus@3170
   172
        *state = SDL_POWERSTATE_UNKNOWN;
icculus@3170
   173
    } else if (battery_flag & (1 << 7)) {  /* no battery */
icculus@3170
   174
        *state = SDL_POWERSTATE_NO_BATTERY;
icculus@3170
   175
    } else if (battery_flag & (1 << 3)) {  /* charging */
icculus@3170
   176
        *state = SDL_POWERSTATE_CHARGING;
icculus@3170
   177
        need_details = SDL_TRUE;
icculus@3170
   178
    } else if (ac_status == 1) {
icculus@3170
   179
        *state = SDL_POWERSTATE_CHARGED;  /* on AC, not charging. */
icculus@3170
   180
        need_details = SDL_TRUE;
icculus@3170
   181
    } else {
icculus@3170
   182
        *state = SDL_POWERSTATE_ON_BATTERY;
icculus@3170
   183
        need_details = SDL_TRUE;
icculus@3170
   184
    }
icculus@3170
   185
icculus@3170
   186
    *percent = -1;
icculus@3170
   187
    *seconds = -1;
icculus@3170
   188
    if (need_details) {
icculus@3170
   189
        const int pct = battery_percent;
icculus@3170
   190
        const int secs = battery_time;
icculus@3170
   191
icculus@3170
   192
        if (pct >= 0) {  /* -1 == unknown */
icculus@3170
   193
            *percent = (pct > 100) ? 100 : pct;  /* clamp between 0%, 100% */
icculus@3170
   194
        }
icculus@3170
   195
        if (secs >= 0) {  /* -1 == unknown */
icculus@3170
   196
            *seconds = secs;
icculus@3170
   197
        }
icculus@3170
   198
    }
icculus@3170
   199
icculus@3170
   200
    return SDL_TRUE;
icculus@3170
   201
}
icculus@3170
   202
icculus@3170
   203
#endif /* SDL_POWER_LINUX */
icculus@3170
   204
#endif /* SDL_POWER_DISABLED */
icculus@3170
   205
icculus@3170
   206
/* vi: set ts=4 sw=4 expandtab: */
icculus@3170
   207