diff -urNb sleepd-old/apm.h sleepd/apm.h --- sleepd-old/apm.h 2009-05-15 20:57:04.000000000 +0200 +++ sleepd/apm.h 2003-01-16 22:50:36.000000000 +0100 @@ -1,7 +1,56 @@ -#include - -/* Symbolic constants for apm may be in system apm.h, or may not. */ -#ifndef AC_LINE_STATUS_ON +/* apm.h -- Header file for sample APM interface routines + * Created: Mon Jan 8 11:40:50 1996 by r.faith@ieee.org + * Revised: Thu Apr 4 21:57:31 1996 by r.faith@ieee.org + * Copyright 1996 Rickard E. Faith (r.faith@ieee.org) + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: apm.h,v 1.7 1999/07/05 22:31:11 apenwarr Exp $ + * + */ +#include +#include + +#define APM_PROC "/proc/apm" +#define APM_DEVICE "/dev/apm_bios" + +#define APM_DEV "/proc/devices" +#define APM_NAME "apm_bios" + +#ifndef APM_32_BIT_SUPPORT +#define APM_32_BIT_SUPPORT 0x0002 +#endif + +typedef struct apm_info +{ + const char driver_version[10]; + int apm_version_major; + int apm_version_minor; + int apm_flags; + int ac_line_status; + int battery_status; + int battery_flags; + int battery_percentage; + int battery_time; + int using_minutes; +} +apm_info; + +/* + * Encodings for apm_info + */ #define AC_LINE_STATUS_OFF (0) #define AC_LINE_STATUS_ON (1) #define AC_LINE_STATUS_BACKUP (2) @@ -23,5 +72,24 @@ #define BATTERY_PERCENTAGE_UNKNOWN (-1) #define BATTERY_TIME_UNKNOWN (-1) -#endif /* AC_LINE_STATUS_ON */ +extern int apm_exists(void); +extern int apm_read(apm_info * i); +extern dev_t apm_dev(void); +extern int apm_open(void); +extern int apm_close(int fd); +extern int apm_get_events(int fd, int timeout, apm_event_t * events, int n); +extern int apm_suspend(int fd); +extern int apm_standby(int fd); +extern int apm_set_ignore(int fd, int mode); +extern const char *apm_error_name( unsigned int err ); +extern const char *apm_event_name(apm_event_t event); +extern const char *apm_time(time_t t); +extern const char *apm_delta_time(time_t then, time_t now); +extern const char *apm_time_nosec(time_t t); + +#ifdef APM_IOC_REJECT +extern int apm_reject(int fd); +#else +#define apm_reject(fd) (-EINVAL) +#endif diff -urNb sleepd-old/apmlib.c sleepd/apmlib.c --- sleepd-old/apmlib.c 1970-01-01 01:00:00.000000000 +0100 +++ sleepd/apmlib.c 2010-03-17 17:27:37.648628834 +0100 @@ -0,0 +1,496 @@ +/* apmlib.c -- Sample APM interface routines + * Created: Mon Jan 8 10:28:16 1996 by faith@acm.org + * Revised: Fri Dec 26 21:38:29 1997 by faith@acm.org + * Copyright 1996, 1997 Rickard E. Faith (faith@acm.org) + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apm.h" + +#define BACKWARD_COMPAT 0 + + +/* + * Return a string describing an APM event. From p. 16 of the Intel/Microsoft + * Advanded Power Management (APM) BIOS Interface Specification, Revision + * 1.1 (September 1993). Intel Order Number: 241704-001. Microsoft Part + * Number: 781-110-X01. + * + * Updated to APM BIOS 1.2 spec (February 1996). Available on-line. + */ +const char *apm_event_name(apm_event_t event) +{ + switch (event) + { + case APM_SYS_STANDBY: + return "System Standby Request"; + case APM_SYS_SUSPEND: + return "System Suspend Request"; + case APM_NORMAL_RESUME: + return "Normal Resume System"; + case APM_CRITICAL_RESUME: + return "Critical Resume System"; + case APM_LOW_BATTERY: + return "Battery Low"; + case APM_POWER_STATUS_CHANGE: + return "Power Status Change"; + case APM_UPDATE_TIME: + return "Update Time"; + case APM_CRITICAL_SUSPEND: + return "Critical Suspend"; + case APM_USER_STANDBY: + return "User System Standby Request"; + case APM_USER_SUSPEND: + return "User System Suspend Request"; + case APM_STANDBY_RESUME: + return "System Standby Resume"; +#ifdef APM_CAPABILITY_CHANGE + case APM_CAPABILITY_CHANGE: + return "Capability Change"; +#endif + } + return "Unknown"; +} + + +/* + * Functions to format the time nicely. + */ + +#define SEC_PER_MIN (60) +#define SEC_PER_HOUR (SEC_PER_MIN*60) +#define SEC_PER_DAY (SEC_PER_HOUR*24) + +const char *apm_time(time_t t) +{ + static char buffer[128]; + unsigned long s, m, h, d; + + if (t<0) { + sprintf(buffer, "?"); + return buffer; + } + + d = t / SEC_PER_DAY; + t -= d * SEC_PER_DAY; + h = t / SEC_PER_HOUR; + t -= h * SEC_PER_HOUR; + m = t / SEC_PER_MIN; + t -= m * SEC_PER_MIN; + s = t; + + if (d) + sprintf(buffer, "%lud+%lu:%02lu:%02lu", d, h, m, s); + else + sprintf(buffer, "%lu:%02lu:%02lu", h, m, s); + + return buffer; +} + +const char *apm_time_nosec(time_t t) +{ + static char buffer[128]; + unsigned long s, m, h, d; + + if (t<0) { + sprintf(buffer, "?"); + return buffer; + } + + d = t / SEC_PER_DAY; + t -= d * SEC_PER_DAY; + h = t / SEC_PER_HOUR; + t -= h * SEC_PER_HOUR; + m = t / SEC_PER_MIN; + t -= m * SEC_PER_MIN; + s = t; + + if (s > 30) + ++m; + + if (d) + sprintf(buffer, "%lud+%lu:%02lu", d, h, m); + else + sprintf(buffer, "%lu:%02lu", h, m); + + return buffer; +} + +const char *apm_delta_time(time_t then, time_t now) +{ + return apm_time(now - then); +} + + +/* + * Read information from /proc/apm. Return 0 on success, + * 1 if APM not installed, 2 if APM installed but old version. + */ +int apm_read(apm_info * i) +{ + FILE *str; + char units[10]; + char buffer[100]; + int retcode = 0; + + if (!(str = fopen(APM_PROC, "r"))) + return 1; + fgets(buffer, sizeof(buffer) - 1, str); + buffer[sizeof(buffer) - 1] = '\0'; + + /* Should check for other driver versions; driver 1.9 (and some + * others) uses this format, which doesn't expose # batteries. + */ + sscanf(buffer, "%s %d.%d %x %x %x %x %d%% %d %s\n", + (char *) i->driver_version, + &i->apm_version_major, + &i->apm_version_minor, + &i->apm_flags, + &i->ac_line_status, + &i->battery_status, + &i->battery_flags, + &i->battery_percentage, + &i->battery_time, + units); + i->using_minutes = !strncmp(units, "min", 3) ? 1 : 0; + if (i->driver_version[0] == 'B') + { /* old style. argh. */ +#if !BACKWARD_COMPAT + retcode = 2; +#else + strcpy((char *) i->driver_version, "pre-0.7"); + i->apm_version_major = 0; + i->apm_version_minor = 0; + i->apm_flags = 0; + i->ac_line_status = 0xff; + i->battery_status = 0xff; + i->battery_flags = 0xff; + i->battery_percentage = -1; + i->battery_time = -1; + i->using_minutes = 1; + + sscanf(buffer, "BIOS version: %d.%d", + &i->apm_version_major, &i->apm_version_minor); + fgets(buffer, sizeof(buffer) - 1, str); + sscanf(buffer, "Flags: 0x%02x", &i->apm_flags); + if (i->apm_flags & APM_32_BIT_SUPPORT) + { + fgets(buffer, sizeof(buffer) - 1, str); + fgets(buffer, sizeof(buffer) - 1, str); + if (buffer[0] != 'P') + { + if (!strncmp(buffer + 4, "off line", 8)) + i->ac_line_status = 0; + else if (!strncmp(buffer + 4, "on line", 7)) + i->ac_line_status = 1; + else if (!strncmp(buffer + 4, "on back", 7)) + i->ac_line_status = 2; + + fgets(buffer, sizeof(buffer) - 1, str); + if (!strncmp(buffer + 16, "high", 4)) + i->battery_status = 0; + else if (!strncmp(buffer + 16, "low", 3)) + i->battery_status = 1; + else if (!strncmp(buffer + 16, "crit", 4)) + i->battery_status = 2; + else if (!strncmp(buffer + 16, "charg", 5)) + i->battery_status = 3; + + fgets(buffer, sizeof(buffer) - 1, str); + if (strncmp(buffer + 14, "unknown", 7)) + i->battery_percentage = atoi(buffer + 14); + if (i->apm_version_major >= 1 && i->apm_version_minor >= 1) + { + fgets(buffer, sizeof(buffer) - 1, str); + sscanf(buffer, "Battery flag: 0x%02x", &i->battery_flags); + + fgets(buffer, sizeof(buffer) - 1, str); + if (strncmp(buffer + 14, "unknown", 7)) + i->battery_time = atoi(buffer + 14); + } + } + } +#endif + } + + /* Fix possible kernel bug -- percentage + * set to 0xff (==255) instead of -1. + */ + if (i->battery_percentage > 100) + i->battery_percentage = -1; + + fclose(str); + return retcode; +} + + +/* + * Look up the device number of the apm_bios device. + */ +dev_t apm_dev(void) +{ + FILE *str; + static int cached = -1; + char buf[80]; + char *pt; + apm_info i; + + if (cached >= 0) + return cached; + + if (access(APM_PROC, R_OK) || apm_read(&i) == 1) + return cached = -1; + if (i.driver_version[0] == '1') + return cached = makedev(10, 134); + + if (!(str = fopen(APM_DEV, "r"))) + return -1; + while (fgets(buf, sizeof(buf) - 1, str)) + { + buf[sizeof(buf) - 1] = '\0'; + for (pt = buf; *pt && isspace(*pt); ++pt); /* skip leading spaces */ + for (; *pt && !isspace(*pt); ++pt); /* find next space */ + if (isspace(*pt)) + { + *pt++ = '\0'; + pt[strlen(pt) - 1] = '\0'; /* get rid of newline */ + if (!strcmp(pt, APM_NAME)) + { + fclose(str); + return cached = makedev(atoi(buf), 0); + } + } + } + fclose(str); + return cached = -1; +} + + +/* + * Return a file descriptor for the apm_bios device, or -1 if there is an + * error. + * + * apenwarr 2001/05/11: just throw out the weird temporary device file stuff. + * It was only for ancient kernel versions anyway. + * alexamici 2001/12/14: remove the redundant check for kernel apm support. + * Now apm_open() triggers the auto-load of the apm module. + */ +int apm_open(void) +{ + int fd; + + if ((fd = open(APM_DEVICE, O_RDWR)) < 0) + { + /* + * Try to create it. This is reasonable + * for backward compatibility. + */ + if (mknod(APM_DEVICE, S_IFCHR | S_IRUSR | S_IWUSR, apm_dev())) + { + unlink(APM_DEVICE); + return -1; + } + fd = open(APM_DEVICE, O_RDWR); + } + + return fd; +} + + +/* + * Given a file descriptor for the apm_bios device, close it. + */ +int apm_close(int fd) +{ + return close(fd); +} + + +/* + * If APM support of the right version exists in kernel, return zero. + * Otherwise, return 1 if no support exists, or 2 if it is the wrong + * version. *NOTE* The sense of the return value is not intuitive. + */ +int apm_exists(void) +{ + int fd; + apm_info i; + + /* This will force auto-load of the apm module if necessary. */ + fd = open(APM_DEVICE, O_WRONLY); + if (fd >= 0) + close(fd); + + if (access(APM_PROC, R_OK)) + return 1; + return apm_read(&i); +} + + +/* + * Given a file descriptor for the apm_bios device, this routine will wait + * timeout seconds for APM events. Up to n events will be placed in the + * events queue. The return code will indicate the number of events + * stored. Since this routine uses select(2), it will return if an + * unblocked signal is caught. A timeout < 0 means to block indefinately. + * + * Note that if you read a request to standby or to suspend, the kernel + * will be waiting for you to respond to it with a call to apm_suspend() + * or to apm_standby() ! + */ +int apm_get_events(int fd, int timeout, apm_event_t * events, int n) +{ + int retcode; + fd_set fds; + struct timeval t; + + t.tv_sec = timeout; + t.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + retcode = select(fd + 1, &fds, NULL, NULL, timeout < 0 ? NULL : &t); + if (retcode <= 0) + return 0; + return read(fd, events, n * sizeof(apm_event_t)) / sizeof(apm_event_t); +} + + +/* + * Request suspend or acknowledge suspend request + */ +int apm_suspend(int fd) +{ + sync(); + return ioctl(fd, APM_IOC_SUSPEND, NULL) < 0 ? -errno : 0; +} + + +/* + * Request standby or acknowledge standby request + */ +int apm_standby(int fd) +{ + sync(); + return ioctl(fd, APM_IOC_STANDBY, NULL); +} + + +/* + * apm_error_name -- return string describing APM error + */ + +typedef struct lookup_t { + int key; + char * msg; +} lookup_t; + +static const lookup_t error_table[] = { +/* N/A { APM_SUCCESS, "Operation succeeded" }, */ + { APM_DISABLED, "Power management disabled" }, + { APM_CONNECTED, "Real mode interface already connected" }, + { APM_NOT_CONNECTED, "Interface not connected" }, + { APM_16_CONNECTED, "16 bit interface already connected" }, +/* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */ + { APM_32_CONNECTED, "32 bit interface already connected" }, + { APM_32_UNSUPPORTED, "32 bit interface not supported" }, + { APM_BAD_DEVICE, "Unrecognized device ID" }, + { APM_BAD_PARAM, "Parameter out of range" }, + { APM_NOT_ENGAGED, "Interface not engaged" }, +#ifdef APM_BAD_FUNCTION + { APM_BAD_FUNCTION, "Function not supported" }, +#endif +#ifdef APM_RESUME_DISABLED + { APM_RESUME_DISABLED, "Resume timer disabled" }, +#endif + { APM_BAD_STATE, "Unable to enter requested state" }, +/* N/A { APM_NO_EVENTS, "No events pending" }, */ + { APM_NOT_PRESENT, "No APM present" } +}; + +#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) + +const char *apm_error_name( unsigned int err ) +{ + int i; + + for(i=0; i #include #include -#include +#include "apm.h" #include #include "acpi.h" #ifdef HAL