/* $Id: plugin_apm.c,v 1.1 2004/03/14 07:11:42 reinelt Exp $ * * plugin for APM (battery status) * * Copyright 2003 Michael Reinelt * Copyright 2004 The LCD4Linux Team * * based on the old 'battery.c' which is * Copyright 2001 Leopold Tötsch * * This file is part of LCD4Linux. * * LCD4Linux 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. * * LCD4Linux 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; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * $Log: plugin_apm.c,v $ * Revision 1.1 2004/03/14 07:11:42 reinelt * parameter count fixed for plugin_dvb() * plugin_APM (battery status) ported * */ /* * exported functions: * * int plugin_init_apm (void) * adds apm() function * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "debug.h" #include "plugin.h" #include "hash.h" static int fd = -2; static HASH APM = { 0, }; /* from /usr/src/linux/arch/i386/kernel/apm.c: * * Arguments, with symbols from linux/apm_bios.h. Information is * from the Get Power Status (0x0a) call unless otherwise noted. * * 0) Linux driver version (this will change if format changes) * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. * 2) APM flags from APM Installation Check (0x00): * bit 0: APM_16_BIT_SUPPORT * bit 1: APM_32_BIT_SUPPORT * bit 2: APM_IDLE_SLOWS_CLOCK * bit 3: APM_BIOS_DISABLED * bit 4: APM_BIOS_DISENGAGED * 3) AC line status * 0x00: Off-line * 0x01: On-line * 0x02: On backup power (BIOS >= 1.1 only) * 0xff: Unknown * 4) Battery status * 0x00: High * 0x01: Low * 0x02: Critical * 0x03: Charging * 0x04: Selected battery not present (BIOS >= 1.2 only) * 0xff: Unknown * 5) Battery flag * bit 0: High * bit 1: Low * bit 2: Critical * bit 3: Charging * bit 7: No system battery * 0xff: Unknown * 6) Remaining battery life (percentage of charge): * 0-100: valid * -1: Unknown * 7) Remaining battery life (time units): * Number of remaining minutes or seconds * -1: Unknown * 8) min = minutes; sec = seconds * * p+= sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", * driver_version, * (apm_info.bios.version >> 8) & 0xff, * apm_info.bios.version & 0xff, * apm_info.bios.flags, * ac_line_status, * battery_status, * battery_flag, * percentage, * time_units, * units); */ static int parse_proc_apm (void) { char *key[] = { "driver_version", "bios_version", "bios_flags", "line_status", "battery_status", "battery_flag", "battery_percent", "battery_remaining", "time_units" }; char buffer[128], *beg, *end; int age, i; // reread every 10 msec only age = hash_age (&APM, NULL, NULL); if (age > 0 && age <= 10) return 0; if (fd == -2) { fd = open("/proc/apm", O_RDONLY | O_NDELAY); if (fd == -1) { error ("open(/proc/apm) failed: %s", strerror(errno)); return -1; } } if (lseek(fd, 0L, SEEK_SET) != 0) { error ("lseek(/proc/apm) failed: %s", strerror(errno)); fd = -1; return -1; } if (read (fd, &buffer, sizeof(buffer)-1) == -1) { error ("read(/proc/apm) failed: %s", strerror(errno)); fd=-1; return -1; } beg = buffer; for (i = 0; i < 9 && beg != NULL; i++) { while (*beg == ' ') beg++; if ((end = strpbrk(beg, " \n"))) *end='\0'; hash_set (&APM, key[i], beg); beg = end ? end+1 : NULL; } return 0; } static void my_apm (RESULT *result, RESULT *arg1) { char *val; if (parse_proc_apm()<0) { SetResult(&result, R_STRING, ""); return; } val=hash_get(&APM, R2S(arg1)); if (val==NULL) val=""; SetResult(&result, R_STRING, val); } int plugin_init_apm (void) { AddFunction ("apm", 1, my_apm); return 0; } void plugin_exit_apm (void) { if (fd > -1) { close (fd); } fd = -2; hash_destroy(&APM); }