1000 lines
24 KiB
C
1000 lines
24 KiB
C
/*
|
|
* wmapm-3.1
|
|
*
|
|
* A WindowMaker dockable application that allows laptop users
|
|
* to graphically monitor the status of their power source.
|
|
* (I.e. whether or not AC or battery is in use as well as
|
|
* how long it will take to drain or charge the battery.)
|
|
*
|
|
* Originally written (and copyrighted under GPL) by
|
|
* Chris D. Faulhaber <jedgar@fxp.org>. Version 3.0
|
|
* is an extensively modified version of version 2.0
|
|
* by Michael G. Henderson <mghenderson@lanl.gov>.
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (see the file COPYING); if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
*
|
|
* Portions of code derived from:
|
|
* apm/apmd/libapm : (c) 1996 Rickard E. Faith (r.faith@ieee.org)
|
|
* wmmon : (c) 1998 Martijn Pieterse (pieterse@xs4all.nl) and
|
|
* Antoine Nulle (warp@xs4all.nl)
|
|
*
|
|
* Thanx to Timecop <timecop@linuxwarez.com> for pointing out/helping to
|
|
* Toggle fix the meter mismatch.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Changes:
|
|
*
|
|
* 3.1 -Released: June 1, 1999.
|
|
* + Added support for time left on FreeBSD 3.x/4.x
|
|
* (Chris D. Faulhaber <jedgar@fxp.org>)
|
|
*
|
|
*
|
|
* 3.01 -Released: January 3, 1999.
|
|
*
|
|
* + Added a LowColor Pixmap for the poor saps using 8-bit displays
|
|
* on laptops. There are a *lot* of laptops out there that are only
|
|
* 8-bit. Use the "-l" command-line option to invoke.
|
|
*
|
|
*
|
|
* 3.0 -Released: December 15, 1998.
|
|
* A Major overhaul performed. Changes include;
|
|
*
|
|
* + Added buttons to place laptop into "Suspend" (button labeled `Z')
|
|
* or "Standby" (button labeled `S') mode. Buttons are separated
|
|
* by status LEDs to minimize accidentally clicking on the wrong
|
|
* one. I used `Z' for suspend because its like the laptop is
|
|
* catching some Zs (i.e. going to sleep).
|
|
*
|
|
* + Replaced the 3 rectangular red/yellow/green status indicators
|
|
* with 3 small round LEDs and moved them to a viewport at the
|
|
* bottom between the two buttons. This array of LEDs could in future
|
|
* be moved to a single LED in the main viewport to make room for
|
|
* other things at this location (perhaps more buttons if apm supports
|
|
* more things like truning off LCD, etc).
|
|
*
|
|
* + Created user-definable LowLevel and CriticalLevel thresholds. Yellow LED
|
|
* comes on when Battery Percentage hits the LowLevel threshold. Red comes on
|
|
* when you reach CriticalLevel threshold.
|
|
*
|
|
* + Made red status LED blink for extra noticability. User can define blink rate.
|
|
* A BlinkRate of 0 turns off blinking.
|
|
*
|
|
* + Moved all of the other indicators into a single viewport above the
|
|
* buttons and status LEDs.
|
|
*
|
|
* + Changed the red-dark-green colorbar to a banded blue LED bar that is tipped
|
|
* with a color indicating capacity level. The tip color goes through
|
|
* green-yellow-orange-red. A series of single-pixel dots is always present
|
|
* below the bar to indicate its range. This is needed now, because
|
|
* the bar is free-floating in the viewport. The single-pixel dots can be
|
|
* seen easily on an LCD - the type of monitor wmapm is likely to be used.
|
|
*
|
|
* + Changed the `CHARGING' indicator with a single red `C' indicator at the
|
|
* upper left of the APP.
|
|
*
|
|
* + Changed percentage indicator so that it can display 100%. (Used to only go
|
|
* up to 99% max).
|
|
*
|
|
* + Changed time indicator to have a +/- sign depending on whether you are
|
|
* charging up or draining down. (+ means you have that much battery life
|
|
* left before its discharged. - means you have that much time to wait until
|
|
* the battery is fully charged.)
|
|
*
|
|
* + Fixed a problem with very large "TimeLeft" values. If the time is greater
|
|
* than the maximum time displayable 99 hours and 59 minutes, a ---:-- is
|
|
* listed instead. Since the time is based on measured charge/discharge rates,
|
|
* when the battery is doing neither, the time is essentially infinite. On my
|
|
* (M Henderson's) laptop, the time left indicated 32766 when this happened.
|
|
* FreeBSD systems should also show a ---:-- indicator. Dont have FreeBSD though
|
|
* so I couldnt test it....
|
|
*
|
|
* + Changed Makefile to suid the apm program. This is needed to allow users to
|
|
* invoke the standby and suspend capabilities in apm.
|
|
*
|
|
* + Sped up the loop to catch button press and expose events. But the querying of
|
|
* /proc/apm is still done about once a second...
|
|
*
|
|
* + Added alert feature. User can use command line option -A <T1 T2> to turn on alerts
|
|
* via wall. T1 and T2 are the time in seconds between updates for Low and Critical
|
|
* status. By default the alerts are turned off.
|
|
*
|
|
* + Various sundry code cleanups.
|
|
*
|
|
*
|
|
* 2.0 - Added FreeBSD support.
|
|
*
|
|
* 1.3 - Fixed an annoying little problem with the the meter
|
|
* not properly lowering as the battery is depleted.
|
|
* Also did some code cleanup, enhanced the Makefile which
|
|
* now includes 'make install'.
|
|
* Released 980826
|
|
*
|
|
* 1.2 - Fixed bug that showed 100% battery capacity
|
|
* as 90% (I never noticed since my battery seems
|
|
* to max out at 98%).
|
|
* Thanx to Brice Ruth <bruth@ltic.com> for pointing out/helping fix the
|
|
* 100% bug (err...feature).
|
|
* Released 980731
|
|
*
|
|
* 1.1 - Removed libapm dependency; tweaked some code.
|
|
* Released 980729
|
|
*
|
|
* 1.0 - Initial release version.
|
|
* Released 980725
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef SunOS
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <stropts.h>
|
|
#include <sys/battery.h>
|
|
#endif
|
|
|
|
|
|
#ifdef FreeBSD
|
|
#include <err.h>
|
|
#include <sys/file.h>
|
|
#include <sys/ioctl.h>
|
|
#include <machine/apm_bios.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <X11/X.h>
|
|
#include <X11/xpm.h>
|
|
#include "wmapm.h"
|
|
#include <libdockapp/wmgeneral.h>
|
|
#include "wmapm_master.xpm"
|
|
#include "wmapm_master_LowColor.xpm"
|
|
#include "wmapm_mask.xbm"
|
|
|
|
|
|
|
|
#ifdef Linux
|
|
int apm_read(struct my_apm_info *i);
|
|
#else
|
|
# ifdef FreeBSD
|
|
int apm_read(apm_info_t temp_info);
|
|
# endif
|
|
#endif
|
|
int apm_exists();
|
|
void ParseCMDLine(int argc, char *argv[]);
|
|
void pressEvent(XButtonEvent *xev);
|
|
|
|
|
|
|
|
|
|
int CriticalLevel = 10;
|
|
int LowLevel = 40;
|
|
float BlinkRate = 3.0; /* blinks per second */
|
|
float UpdateRate = 0.8; /* Number of updates per second */
|
|
int Beep = 0; /* Controls beeping when you get to CriticalLevel: Off by default */
|
|
int Volume = 50; /* ring bell at 50% volume */
|
|
int Alert = 0; /* Controls whether alert is sent to all users via wall: Off by default */
|
|
int UseLowColorPixmap = 0; /* Use a lower number of colors for the poor saps on 8-bit displays -- common
|
|
on laptops! */
|
|
float LAlertRate = 300.0; /* send alert every 5 minutes when Low */
|
|
float CAlertRate = 120.0; /* send alert every 2 minutes when Critical */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* main
|
|
*/
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
|
struct my_apm_info my_cur_info;
|
|
int time_left,
|
|
hour_left,
|
|
min_left,
|
|
digit;
|
|
#ifdef FreeBSD
|
|
struct apm_info temp_info;
|
|
#endif
|
|
XEvent event;
|
|
int m, mMax, n, nMax, k, Toggle;
|
|
long int r, rMax, s, sMax;
|
|
FILE *fp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BlinkRate = 3.0;
|
|
UpdateRate = 1.0/1.25;
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Parse any command line arguments.
|
|
*/
|
|
ParseCMDLine(argc, argv);
|
|
|
|
BlinkRate = (BlinkRate >= 0.0) ? BlinkRate : -1.0*BlinkRate;
|
|
UpdateRate = (UpdateRate >= 0.0) ? UpdateRate : -1.0*UpdateRate;
|
|
|
|
|
|
nMax = (int)( 1.0e6/(2.0*UpdateRate*DELAY) );
|
|
mMax = (BlinkRate > 0.0) ? (int)( 1.0e6/(2.0*BlinkRate*DELAY) ) : nMax;
|
|
rMax = (int)( LAlertRate*1.0e6/(2.0*DELAY) );
|
|
sMax = (int)( CAlertRate*1.0e6/(2.0*DELAY) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Check for APM support
|
|
*/
|
|
if (!apm_exists()) {
|
|
#ifdef Linux
|
|
fprintf(stderr, "No APM support in kernel\n");
|
|
#else
|
|
fprintf(stderr, "Unable to access APM info\n");
|
|
#endif
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (UseLowColorPixmap)
|
|
openXwindow(argc, argv, wmapm_master_LowColor, wmapm_mask_bits, wmapm_mask_width, wmapm_mask_height);
|
|
else
|
|
openXwindow(argc, argv, wmapm_master, wmapm_mask_bits, wmapm_mask_width, wmapm_mask_height);
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Loop until we die...
|
|
*/
|
|
n = 32000;
|
|
m = 32000;
|
|
r = rMax+1;
|
|
s = sMax+1;
|
|
while(1) {
|
|
|
|
|
|
/*
|
|
* Only process apm info only every nMax cycles of this
|
|
* loop. We run it faster to catch the xevents like button
|
|
* presses and expose events, etc...
|
|
*
|
|
* DELAY is set at 0.00625 seconds, so process apm info
|
|
* every 1.25 seconds...
|
|
*
|
|
*/
|
|
if (n>nMax){
|
|
|
|
n = 0;
|
|
|
|
#if defined(Linux) || defined(SunOS)
|
|
if (apm_read(&my_cur_info)) {
|
|
#else
|
|
# ifdef FreeBSD
|
|
if (apm_read(&temp_info)) {
|
|
# endif
|
|
#endif
|
|
fprintf(stderr, "Cannot read APM information: %i\n");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
#ifdef FreeBSD /* Convert status's */
|
|
my_cur_info.ac_line_status = (int)temp_info.ai_acline;
|
|
my_cur_info.battery_status = (int)temp_info.ai_batt_stat;
|
|
my_cur_info.battery_percentage = (int)temp_info.ai_batt_life;
|
|
my_cur_info.battery_time = (int)temp_info.ai_batt_time;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Check AC status.
|
|
*/
|
|
switch (my_cur_info.ac_line_status) {
|
|
|
|
case 1:
|
|
/*
|
|
* AC on-line. I.e. we are "plugged-in".
|
|
*/
|
|
copyXPMArea(68, 6, 26, 7, 31, 35);
|
|
break;
|
|
default:
|
|
/*
|
|
* AC off-line. I.e. we are using battery.
|
|
*/
|
|
copyXPMArea(68, 20, 26, 7, 31, 35);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Paste up the default charge status and time
|
|
*/
|
|
copyXPMArea(104, 6, 5, 7, 6, 7);
|
|
copyXPMArea(83, 93, 41, 9, 15, 7);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Check to see if we are charging.
|
|
*/
|
|
if ( (int)(my_cur_info.battery_status) == 3){
|
|
|
|
/*
|
|
* Battery Status: Charging.
|
|
*/
|
|
copyXPMArea(98, 6, 5, 7, 6, 7);
|
|
copyXPMArea(75, 81, 1, 2, 17, 9);
|
|
copyXPMArea(75, 81, 1, 2, 17, 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Repaint buttons.
|
|
*/
|
|
copyXPMArea(42, 106, 13, 11, 5, 48);
|
|
copyXPMArea(57, 106, 13, 11, 46, 48);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Paste up the "Time Left". This time means:
|
|
*
|
|
* If not charging: Time left before battery drains to 0%
|
|
* If charging: Time left before battery gets to maximum
|
|
*
|
|
*/
|
|
#ifdef Linux
|
|
if (my_cur_info.battery_time >= ((my_cur_info.using_minutes) ? 1440 : 86400) ) {
|
|
#else
|
|
# ifdef FreeBSD
|
|
if (my_cur_info.battery_time >= 86400) {
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
* If battery_time is too large, it likely means that there is
|
|
* no charging or discharging going on. So just display a "null"
|
|
* indicator (--:--).
|
|
*
|
|
*/
|
|
copyXPMArea(83, 106, 41, 9, 15, 7);
|
|
|
|
} else if (my_cur_info.battery_time >= 0) {
|
|
|
|
#ifdef Linux
|
|
time_left = (my_cur_info.using_minutes) ? my_cur_info.battery_time : my_cur_info.battery_time / 60;
|
|
#endif
|
|
#ifdef FreeBSD
|
|
time_left = (my_cur_info.using_minutes) ? my_cur_info.battery_time / 60 : my_cur_info.battery_time / 3600;
|
|
#endif
|
|
|
|
hour_left = time_left / 60;
|
|
min_left = time_left % 60;
|
|
|
|
copyXPMArea( (hour_left / 10) * 7 + 5, 93, 7, 9, 21, 7); /* Show 10's (hour) */
|
|
copyXPMArea((hour_left % 10) * 7 + 5, 93, 7, 9, 29, 7); /* Show 1's (hour) */
|
|
copyXPMArea(76, 93, 2, 9, 38, 7); /* colon */
|
|
copyXPMArea((min_left / 10) * 7 + 5, 93, 7, 9, 42, 7); /* Show 10's (min) */
|
|
copyXPMArea((min_left % 10) * 7 + 5, 93, 7, 9, 50, 7); /* Show 1's (min) */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Do Battery Percentage.
|
|
*/
|
|
copyXPMArea(76, 81, 19, 7, 7, 34); /* Show Default % */
|
|
copyXPMArea(66, 31, 49, 9, 7, 21); /* Show Default Meter */
|
|
if (my_cur_info.battery_percentage == 100){
|
|
copyXPMArea(15, 81, 1, 7, 7, 34); /* If 100%, show 100% */
|
|
copyXPMArea( 5, 81, 6, 7, 9, 34);
|
|
copyXPMArea( 5, 81, 6, 7, 15, 34);
|
|
copyXPMArea(64, 81, 7, 7, 21, 34); /* Show '%' */
|
|
copyXPMArea(66, 42, 49, 9, 7, 21); /* Show Meter */
|
|
} else {
|
|
|
|
if (my_cur_info.battery_percentage >= 10)
|
|
copyXPMArea((my_cur_info.battery_percentage / 10) * 6 + 4, 81, 6, 7, 9, 34); /* Show 10's */
|
|
copyXPMArea((my_cur_info.battery_percentage % 10) * 6 + 4, 81, 6, 7, 15, 34); /* Show 1's */
|
|
copyXPMArea(64, 81, 7, 7, 21, 34); /* Show '%' */
|
|
|
|
/*
|
|
* Show Meter
|
|
*/
|
|
k = my_cur_info.battery_percentage * 49 / 100;
|
|
copyXPMArea(66, 42, k, 9, 7, 21);
|
|
if (k%2)
|
|
copyXPMArea(66+k-1, 52, 1, 9, 7+k-1, 21);
|
|
else
|
|
copyXPMArea(66+k, 52, 1, 9, 7+k, 21);
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Update the counter. When it hits nMax, we will
|
|
* process /proc/apm information again.
|
|
*/
|
|
++n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* This controls the 3 LEDs
|
|
*/
|
|
if (m>mMax){
|
|
|
|
m = 0;
|
|
|
|
|
|
if (( (int)(my_cur_info.battery_status) == 2)
|
|
||( (int)(my_cur_info.battery_percentage) <= CriticalLevel )){
|
|
|
|
/*
|
|
* Battery Status: Critical.
|
|
* Blink the red led on/off...
|
|
*/
|
|
if (Toggle||(BlinkRate == 0.0)){
|
|
if (Beep) XBell(display, Volume);
|
|
Toggle = 0;
|
|
copyXPMArea(95, 68, 4, 4, 24, 51);
|
|
} else{
|
|
Toggle = 1;
|
|
copyXPMArea(75, 68, 4, 4, 24, 51);
|
|
}
|
|
copyXPMArea(81, 68, 4, 4, 30, 51); /* turn off yellow */
|
|
copyXPMArea(87, 68, 4, 4, 36, 51); /* turn off green */
|
|
|
|
} else if (( (int)(my_cur_info.battery_status) == 1)
|
|
||( (int)(my_cur_info.battery_percentage) <= LowLevel )){
|
|
|
|
/*
|
|
* Battery Status: Low.
|
|
*/
|
|
copyXPMArea(75, 68, 4, 4, 24, 51); /* turn off red */
|
|
copyXPMArea(101, 68, 4, 4, 30, 51); /* turn ON yellow */
|
|
copyXPMArea(87, 68, 4, 4, 36, 51); /* turn off green */
|
|
|
|
} else if (( (int)( my_cur_info.battery_status ) == 0)
|
|
||( (int)(my_cur_info.battery_percentage) > LowLevel )){
|
|
|
|
/*
|
|
* Battery Status: High.
|
|
*/
|
|
copyXPMArea(75, 68, 4, 4, 24, 51); /* turn off red */
|
|
copyXPMArea(81, 68, 4, 4, 30, 51); /* turn off yellow */
|
|
copyXPMArea(107, 68, 4, 4, 36, 51); /* turn ON green */
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Update the counter.
|
|
*/
|
|
++m;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* This controls Critical Alerts
|
|
*/
|
|
if (Alert){
|
|
if (( (int)(my_cur_info.battery_status) == 2)
|
|
||( (int)(my_cur_info.battery_percentage) <= CriticalLevel )){
|
|
|
|
if (s>sMax){
|
|
|
|
s = 0;
|
|
fp = popen("wall", "w");
|
|
fprintf(fp, "Battery is critical!. Percent: %d\n", (int)(my_cur_info.battery_percentage));
|
|
pclose(fp);
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Update the counter.
|
|
*/
|
|
++s;
|
|
|
|
}
|
|
|
|
} else if (( (int)(my_cur_info.battery_status) == 1)
|
|
||( (int)(my_cur_info.battery_percentage) <= LowLevel )){
|
|
|
|
if (r>rMax){
|
|
|
|
r = 0;
|
|
fp = popen("wall", "w");
|
|
fprintf(fp, "Battery is low. Percent: %d\n", (int)(my_cur_info.battery_percentage));
|
|
pclose(fp);
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Update the counter.
|
|
*/
|
|
++r;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Process any pending X events.
|
|
*/
|
|
while(XPending(display)){
|
|
XNextEvent(display, &event);
|
|
switch(event.type){
|
|
case Expose:
|
|
RedrawWindow();
|
|
break;
|
|
case ButtonPress:
|
|
pressEvent(&event.xbutton);
|
|
break;
|
|
case ButtonRelease:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Redraw and wait for next update
|
|
*/
|
|
RedrawWindow();
|
|
usleep(DELAY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* This routine handles button presses. Pressing the 'S' button
|
|
* invokes 'apm -S' to place the machine into standby mode. And
|
|
* pressing the 'Z' buton invokes 'apm -s' to place the machine
|
|
* into suspend mode.
|
|
*
|
|
* Note: in order for users other than root to be able to run
|
|
* 'apm -s' and 'apm -S', you need to make apm suid (i.e.
|
|
* run 'chmod +s /usr/bin/apm' as root). This will allow
|
|
* 'normal' users to execute apm with root privilages.
|
|
*
|
|
*/
|
|
void pressEvent(XButtonEvent *xev){
|
|
|
|
int x=xev->x;
|
|
int y=xev->y;
|
|
|
|
if(x>=5 && y>=48 && x<=17 && y<=58){
|
|
|
|
/*
|
|
* Standby Call.
|
|
*
|
|
* Draw button as 'pushed'. Redraw window to show it.
|
|
* Call 'apm -S' to standby. Sleep for 2 seconds so that
|
|
* the button doesnt immediately redraw back to unpressed
|
|
* before the 'apm -S' takes effect.
|
|
*/
|
|
copyXPMArea(5, 106, 13, 11, 5, 48);
|
|
RedrawWindow();
|
|
#ifndef SunOS
|
|
system("apm -S");
|
|
#endif
|
|
usleep(2000000L);
|
|
|
|
} else if (x>=46 && y>=48 && x<=58 && y<=58){
|
|
|
|
/*
|
|
* Suspend Call.
|
|
*
|
|
* Draw button as 'pushed'. Redraw window to show it.
|
|
* Call 'apm -s' to suspend. Sleep for 2 seconds so that
|
|
* the button doesnt immediately redraw back to unpressed
|
|
* before the 'apm -s' takes effect.
|
|
*/
|
|
copyXPMArea(21, 106, 13, 11, 46, 48);
|
|
RedrawWindow();
|
|
#ifndef SunOS
|
|
system("apm -s");
|
|
#endif
|
|
usleep(2000000L);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* apm_exists()
|
|
* - Check to see if /proc/apm exists...
|
|
*
|
|
*/
|
|
int apm_exists()
|
|
{
|
|
|
|
if (access(APMDEV, R_OK))
|
|
|
|
/*
|
|
* Cannot find /proc/apm
|
|
*/
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* apm_read()
|
|
* - Read in the information found in /proc/apm...
|
|
*
|
|
*/
|
|
#ifdef Linux
|
|
int apm_read(struct my_apm_info *i){
|
|
|
|
FILE *str;
|
|
char units[10];
|
|
char buffer[100];
|
|
int retcode = 0;
|
|
|
|
/*
|
|
* Open /proc/apm for reading
|
|
*/
|
|
if (!(str = fopen(APMDEV, "r")))
|
|
return 1;
|
|
|
|
|
|
|
|
/*
|
|
* Scan in the information....
|
|
*/
|
|
fgets(buffer, sizeof(buffer) - 1, str);
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
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;
|
|
|
|
|
|
|
|
/*
|
|
* Old Style
|
|
*/
|
|
if (i->driver_version[0] == 'B') {
|
|
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);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Take care of battery percentages > 100%
|
|
*/
|
|
if (i->battery_percentage > 100) i->battery_percentage = -1;
|
|
|
|
fclose(str);
|
|
return retcode;
|
|
|
|
}
|
|
#else
|
|
# ifdef FreeBSD
|
|
int apm_read(apm_info_t temp_info) {
|
|
|
|
int fd;
|
|
|
|
if ( (fd = open(APMDEV, O_RDWR)) < 0){
|
|
|
|
return(1);
|
|
|
|
} else if ( ioctl(fd, APMIO_GETINFO, temp_info) == -1 ) {
|
|
|
|
close(fd);
|
|
return(1);
|
|
|
|
} else {
|
|
|
|
close(fd);
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef SunOS
|
|
int apm_read(struct my_apm_info *i) {
|
|
|
|
int fd;
|
|
battery_t info;
|
|
|
|
memset(i,0,sizeof(*i));
|
|
if ((fd = open(APMDEV,O_RDONLY)) < 0) {
|
|
perror("open");
|
|
exit(1);
|
|
}
|
|
|
|
if (ioctl(fd,BATT_STATUS,&info) < 0) return(1);
|
|
|
|
close(fd);
|
|
|
|
i->battery_percentage = info.capacity;
|
|
i->battery_time = info.discharge_time;
|
|
i->using_minutes = 0;
|
|
|
|
/* convert to internal status:
|
|
*
|
|
* 0 = high
|
|
* 1 = low
|
|
* 2 = critical
|
|
* 3 = charging
|
|
*/
|
|
switch(info.status) {
|
|
case EMPTY: /* Battery has (effectively) no capacity */
|
|
i->battery_status = 2;
|
|
break;
|
|
case LOW_CAPACITY: /* Battery has less than 25% capacity */
|
|
i->battery_status = 1;
|
|
break;
|
|
case MED_CAPACITY: /* Battery has less than 50% capacity */
|
|
i->battery_status = 1;
|
|
break;
|
|
case HIGH_CAPACITY: /* Battery has less than 75% capacity */
|
|
case FULL_CAPACITY: /* Battery has more than 75% capacity */
|
|
i->battery_status = 0;
|
|
break;
|
|
default:
|
|
i->battery_status = 2;
|
|
break;
|
|
}
|
|
|
|
switch(info.charge) {
|
|
case DISCHARGE: /* Battery is discharging (i.e. in use) */
|
|
i->ac_line_status = 0;
|
|
break;
|
|
case FULL_CHARGE: /* Battery is charging at its fastest rate */
|
|
case TRICKLE_CHARGE: /* Battery is charging at a slower rate */
|
|
default:
|
|
i->ac_line_status = 1;
|
|
break;
|
|
}
|
|
|
|
if (i->battery_percentage > 100) i->battery_percentage = 100;
|
|
|
|
/* Not sure what else we can fill in right now.
|
|
* Relevant information is:
|
|
*
|
|
* info.id_string = type of battery (internal, external, etc)
|
|
* info.total = total capacity (mWhrs)
|
|
*/
|
|
|
|
return(0);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
* ParseCMDLine()
|
|
*/
|
|
void ParseCMDLine(int argc, char *argv[]) {
|
|
char *cmdline;
|
|
int i,j;
|
|
char puke[20];
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
cmdline = argv[i];
|
|
|
|
if (cmdline[0] == '-') {
|
|
switch(cmdline[1]) {
|
|
case 'd':
|
|
++i;
|
|
break;
|
|
case 'A':
|
|
Alert = 1;
|
|
LAlertRate = atof(argv[++i]);
|
|
CAlertRate = atof(argv[++i]);
|
|
break;
|
|
case 'b':
|
|
BlinkRate = atof(argv[++i]);
|
|
break;
|
|
case 'C':
|
|
CriticalLevel = atoi(argv[++i]);
|
|
break;
|
|
case 'L':
|
|
LowLevel = atoi(argv[++i]);
|
|
break;
|
|
case 'l':
|
|
UseLowColorPixmap = 1;
|
|
break;
|
|
case 'B':
|
|
Beep = 1;
|
|
Volume = atoi(argv[++i]);
|
|
break;
|
|
default:
|
|
printf("\nwmapm version: %s\n", WMAPM_VERSION);
|
|
printf("usage:\n");
|
|
printf("\t-display <display>\tUse alternate display.\n");
|
|
printf("\t-l\t\t\tUse a low-color pixmap to conserve colors on 8-bit displays.\n");
|
|
printf("\t-L <LowLevel>\t\tDefine level at which yellow LED turns on.\n");
|
|
printf("\t \t\tCriticalLevel takes precedence if LowLevel<CriticalLevel.\n");
|
|
printf("\t-C <CriticalLevel>\tDefine level at which red LED turns on.\n");
|
|
printf("\t-b <BlinkRate>\t\tBlink rate for red LED. (0 for no blinking.)\n");
|
|
printf("\t-B <Volume>\t\tBeep at Critical Level. Volume is between -100%% to 100%%.\n");
|
|
printf("\t-A <T1 T2>\t\tSend messages to users terminals when Low and critical.\n");
|
|
printf("\t \t\tT1 is seconds between messages when Low. T2 is seconds between messages when Critical.\n");
|
|
printf("\t-h\t\t\tDisplay help screen.\n\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|