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: */
+