src/power/beos/SDL_syspower.c
author Sam Lantinga
Sat, 19 Sep 2009 13:29:40 +0000
changeset 3280 00cace2d9080
parent 3186 51750b7a966f
child 3697 f7b03b6838cb
permissions -rw-r--r--
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
     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_BEOS
    26 
    27 #include <stdio.h>
    28 #include <stdlib.h>
    29 #include <unistd.h>
    30 #include <fcntl.h>
    31 #include <ctype.h>
    32 #include <drivers/Drivers.h>
    33 
    34 /* These values are from apm.h ... */
    35 #define APM_DEVICE_PATH "/dev/misc/apm"
    36 #define APM_FUNC_OFFSET 0x5300
    37 #define APM_FUNC_GET_POWER_STATUS 10
    38 #define APM_DEVICE_ALL 1
    39 #define APM_BIOS_CALL (B_DEVICE_OP_CODES_END + 3)
    40 
    41 #include "SDL_power.h"
    42 
    43 SDL_bool
    44 SDL_GetPowerInfo_BeOS(SDL_PowerState * state, int *seconds, int *percent)
    45 {
    46     const int fd = open("/dev/misc/apm", O_RDONLY);
    47     SDL_bool need_details = SDL_FALSE;
    48     uint16 regs[6];
    49     uint8 ac_status;
    50     uint8 battery_status;
    51     uint8 battery_flags;
    52     uint8 battery_life;
    53     uint32 battery_time;
    54 
    55     if (fd == -1) {
    56         return SDL_FALSE;       /* maybe some other method will work? */
    57     }
    58 
    59     memset(regs, '\0', sizeof(regs));
    60     regs[0] = APM_FUNC_OFFSET + APM_FUNC_GET_POWER_STATUS;
    61     regs[1] = APM_DEVICE_ALL;
    62     rc = ioctl(fd, APM_BIOS_CALL, regs);
    63     close(fd);
    64 
    65     if (rc < 0) {
    66         return SDL_FALSE;
    67     }
    68 
    69     ac_status = regs[1] >> 8;
    70     battery_status = regs[1] & 0xFF;
    71     battery_flags = regs[2] >> 8;
    72     battery_life = regs[2] & 0xFF;
    73     battery_time = (uint32) regs[3];
    74 
    75     /* in theory, _something_ should be set in battery_flags, right? */
    76     if (battery_flags == 0x00) {        /* older APM BIOS? Less fields. */
    77         battery_time = 0xFFFF;
    78         if (battery_status == 0xFF) {
    79             battery_flags = 0xFF;
    80         } else {
    81             battery_flags = (1 << status.battery_status);
    82         }
    83     }
    84 
    85     if ((battery_time != 0xFFFF) && (battery_time & (1 << 15))) {
    86         /* time is in minutes, not seconds */
    87         battery_time = (battery_time & 0x7FFF) * 60;
    88     }
    89 
    90     if (battery_flags == 0xFF) {        /* unknown state */
    91         *state = SDL_POWERSTATE_UNKNOWN;
    92     } else if (battery_flags & (1 << 7)) {      /* no battery */
    93         *state = SDL_POWERSTATE_NO_BATTERY;
    94     } else if (battery_flags & (1 << 3)) {      /* charging */
    95         *state = SDL_POWERSTATE_CHARGING;
    96         need_details = SDL_TRUE;
    97     } else if (ac_status == 1) {
    98         *state = SDL_POWERSTATE_CHARGED;        /* on AC, not charging. */
    99         need_details = SDL_TRUE;
   100     } else {
   101         *state = SDL_POWERSTATE_ON_BATTERY;     /* not on AC. */
   102         need_details = SDL_TRUE;
   103     }
   104 
   105     *percent = -1;
   106     *seconds = -1;
   107     if (need_details) {
   108         const int pct = (int) battery_life;
   109         const int secs = (int) battery_time;
   110 
   111         if (pct != 255) {       /* 255 == unknown */
   112             *percent = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */
   113         }
   114         if (secs != 0xFFFF) {   /* 0xFFFF == unknown */
   115             *seconds = secs;
   116         }
   117     }
   118 
   119     return SDL_TRUE;            /* the definitive answer if APM driver replied. */
   120 }
   121 
   122 #endif /* SDL_POWER_BEOS */
   123 #endif /* SDL_POWER_DISABLED */
   124 
   125 /* vi: set ts=4 sw=4 expandtab: */