From 76254fd53b03ef561f2fbc001fed1fb0499ae755 Mon Sep 17 00:00:00 2001 From: dg Date: Sat, 1 Oct 1994 03:23:33 +0000 Subject: Laptop Advanced Power Management support (userland end) by HOSOKAWA Tatsumi. Submitted by: HOSOKAWA Tatsumi --- usr.sbin/apm/Makefile | 10 ++ usr.sbin/apm/apm.c | 157 ++++++++++++++++++++ usr.sbin/apmconf/Makefile | 8 ++ usr.sbin/apmconf/apmconf.c | 349 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 524 insertions(+) create mode 100644 usr.sbin/apm/Makefile create mode 100644 usr.sbin/apm/apm.c create mode 100644 usr.sbin/apmconf/Makefile create mode 100644 usr.sbin/apmconf/apmconf.c (limited to 'usr.sbin') diff --git a/usr.sbin/apm/Makefile b/usr.sbin/apm/Makefile new file mode 100644 index 0000000..5c0cfda --- /dev/null +++ b/usr.sbin/apm/Makefile @@ -0,0 +1,10 @@ +# $Id$ + +PROG= apm +# CFLAGS+= -I/sys/i386/include +# BINGRP= apm +# BINMODE= 550 +LINKS= ${DESTDIR}/usr/sbin/apm ${DESTDIR}/usr/sbin/zzz +NOMAN= 1 + +.include diff --git a/usr.sbin/apm/apm.c b/usr.sbin/apm/apm.c new file mode 100644 index 0000000..e2e1224 --- /dev/null +++ b/usr.sbin/apm/apm.c @@ -0,0 +1,157 @@ +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatasumi + * + * This software may be used, modified, copied, distributed, and sold, + * in both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#include +#include +#include +#include +#include + +#define APMDEV "/dev/apm" + +int main_argc; +char **main_argv; + +void apm_suspend(int fd) +{ + if (ioctl(fd, APMIO_SUSPEND, NULL) == -1) { + fprintf(stderr, "%s: ioctl APMIO_SUSPEND failed.\n", main_argv[0]); + exit(1); + } +} + +void apm_getinfo(int fd, apm_info_t aip) +{ + if (ioctl(fd, APMIO_GETINFO, aip) == -1) { + fprintf(stderr, "%s: ioctl APMIO_GETINFO failed.\n", main_argv[0]); + exit(1); + } +} + +void print_all_info(apm_info_t aip) +{ + printf("APM version: %d.%d\n", aip->ai_major, aip->ai_minor); + printf("AC Line status: "); + if (aip->ai_acline == 255) { + printf("unknown"); + } + else if (aip->ai_acline > 1) { + printf("invalid value (0x%x)", aip->ai_acline); + } + else { + static char messages[][10] = {"off-line", "on-line"}; + printf("%s", messages[aip->ai_acline]); + } + printf("\n"); + printf("Battery status: "); + if (aip->ai_batt_stat == 255) { + printf("unknown"); + } + else if (aip->ai_batt_stat > 3) { + printf("invalid value (0x%x)", aip->ai_batt_stat); + } + else { + static char messages[][10] = {"high", "low", "critical", "charging"}; + printf("%s", messages[aip->ai_batt_stat]); + } + printf("\n"); + printf("Remaining battery life: "); + if (aip->ai_batt_life == 255) { + printf("unknown"); + } + else if (aip->ai_batt_life <= 100) { + printf("%d%%", aip->ai_batt_life); + } + else { + printf("invalid value (0x%x)", aip->ai_batt_life); + } + printf("\n"); +} + +int main(int argc, char *argv[]) +{ + int i, j, fd; + int sleep = 0, all_info = 1, batt_status = 0, batt_life = 0, ac_status = 0; + char *cmdname; + + main_argc = argc; + main_argv = argv; + if ((cmdname = strrchr(argv[0], '/')) != NULL) { + cmdname++; + } + else { + cmdname = argv[0]; + } + + if (strcmp(cmdname, "zzz") == 0) { + sleep = 1; + all_info = 0; + goto finish_option; + } + + for (i = argc - 1; i >= 1; i--) { + if (argv[i][0] != '-') { + fprintf(stderr, "%s: Unknown option '%s'.", argv[0], argv[i]); + } + for (j = 1; argv[i][j]; j++) { + switch (argv[i][j]) { + case 'z': + sleep = 1; + all_info = 0; + break; + case 'b': + batt_status = 1; + all_info = 0; + break; + case 'a': + ac_status = 1; + all_info = 0; + break; + case 'l': + batt_life = 1; + all_info = 0; + break; + } + } + } +finish_option: + fd = open(APMDEV, O_RDWR); + if (fd == -1) { + fprintf(stderr, "%s: Can't open %s.\n", argv[0], APMDEV); + return 1; + } + if (sleep) { + apm_suspend(fd); + } + else { + struct apm_info info; + + apm_getinfo(fd, &info); + if (all_info) { + print_all_info(&info); + } + if (batt_status) { + printf("%d\n", info.ai_batt_stat); + } + if (batt_life) { + printf("%d\n", info.ai_batt_life); + } + if (ac_status) { + printf("%d\n", info.ai_acline); + } + } + close(fd); + return 0; +} diff --git a/usr.sbin/apmconf/Makefile b/usr.sbin/apmconf/Makefile new file mode 100644 index 0000000..9cdb007 --- /dev/null +++ b/usr.sbin/apmconf/Makefile @@ -0,0 +1,8 @@ +# $Id$ + +PROG= apmconf +# BINMODE= 550 +# BINOWN= root +NOMAN= 1 + +.include diff --git a/usr.sbin/apmconf/apmconf.c b/usr.sbin/apmconf/apmconf.c new file mode 100644 index 0000000..dc8d27f --- /dev/null +++ b/usr.sbin/apmconf/apmconf.c @@ -0,0 +1,349 @@ +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatasumi + * + * This software may be used, modified, copied, distributed, and sold, + * in both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#include +#include +#include +#include +#include +#include + +#define CONFIGFILE "/etc/apm.conf" +#define APMDEV "/dev/apm" + +static const char *config_file = CONFIGFILE; +static int init = 0; +static int flush = 0, verbose = 0; +static int enable = 0, disable = 0; +static int haltcpu = 0, nothaltcpu = 0; +static int main_argc; +static char **main_argv; + +static void +parse_option(void) +{ + int i, option; + char *optarg; + enum {OPT_NONE, OPT_INIT, OPT_CONFFILE, OPT_FLUSH, OPT_VERBOSE, + OPT_ENABLE, OPT_DISABLE, OPT_HALTCPU, OPT_NOTHALTCPU} mode; + + for (i = 1; i < main_argc; i++) { + option = 0; + mode = OPT_NONE; + if (main_argv[i][0] == '-') { + switch (main_argv[i][1]) { + case 'f': + mode = OPT_CONFFILE; + option = 1; + break; + case 'i': + mode = OPT_INIT; + option = 0; + break; + case 'x': + mode = OPT_FLUSH; + option = 0; + break; + case 'v': + mode = OPT_VERBOSE; + option = 0; + break; + case 'e': + mode = OPT_ENABLE; + option = 0; + break; + case 'd': + mode = OPT_DISABLE; + option = 0; + break; + case 'h': + mode = OPT_HALTCPU; + option = 0; + break; + case 't': + mode = OPT_NOTHALTCPU; + option = 0; + break; + default: + fprintf(stderr, "%s: Unknown option '%s.'\n", main_argv[0], main_argv[i]); + exit(1); + } + } + if (option) { + if (i == main_argc - 1) { + fprintf(stderr, "%s: Option '%s' needs arguments.\n", main_argv[0], main_argv[i]); + exit(1); + } + optarg = main_argv[++i]; + } + + switch (mode) { + case OPT_CONFFILE: + config_file = optarg; + break; + case OPT_INIT: + init = 1; + break; + case OPT_FLUSH: + flush = 1; + break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_ENABLE: + enable = 1; + break; + case OPT_DISABLE: + disable = 1; + break; + case OPT_HALTCPU: + haltcpu = 1; + break; + case OPT_NOTHALTCPU: + nothaltcpu = 1; + break; + } + } +} + +static struct apm_eqv_event eqv_event[APM_MAX_EQUIV_EVENTS]; +static int eqv_num = 0; + +static apm_eqv_event_t +get_eqv_event(int id) +{ + int i; + + for (i = 0; i < eqv_num; i++) { + if (id == eqv_event[i].aee_event) { + return &eqv_event[i]; + } + } + return NULL; +} + +#define PMEV_SYMBOL(name) {#name, name} +#define ARRAY_SIZEOF(array) (sizeof(array) / sizeof(array[0])) + +typedef struct pmev_symbol { + char *name; + int id; +} *pmev_symbol_t; + +static struct pmev_symbol pmev_symbols[] = { + PMEV_SYMBOL(PMEV_NOEVENT), + PMEV_SYMBOL(PMEV_STANDBYREQ), + PMEV_SYMBOL(PMEV_SUSPENDREQ), + PMEV_SYMBOL(PMEV_NORMRESUME), + PMEV_SYMBOL(PMEV_CRITRESUME), + PMEV_SYMBOL(PMEV_BATTERYLOW), + PMEV_SYMBOL(PMEV_POWERSTATECHANGE), + PMEV_SYMBOL(PMEV_UPDATETIME), + PMEV_SYMBOL(PMEV_CRITSUSPEND), + PMEV_SYMBOL(PMEV_USERSTANDBYREQ), + PMEV_SYMBOL(PMEV_USERSUSPENDREQ), + PMEV_SYMBOL(PMEV_STANDBYRESUME), +}; + +static int +pmev(char *name, int *id) +{ + int i; + + for (i = 0; i < ARRAY_SIZEOF(pmev_symbols); i++) { + if (strcasecmp(pmev_symbols[i].name, name) == 0) { + *id = pmev_symbols[i].id; + return 0; + } + } + return 1; +} + +static void +parse_config_file(FILE *fp) +{ + int i, id, id_eqv, n; + char *bufp, *lastp; + char buffer[1024]; + char mode[64], event[64], equiv[64]; + apm_eqv_event_t table; + enum {MODE_DEFAULT, MODE_RESUME} mode_type; + + for (i = 1; fgets(buffer, sizeof(buffer), fp); i++) { + if (*buffer == '#') { + continue; + } + n = sscanf(buffer, "%s %s %s", mode, event, equiv); + if (n != 3) { + if (n == EOF) { + continue; /* Empty line */ + } + fprintf(stderr, "%s:%d: Syntax error\n", config_file, i); + exit(1); + } + if (pmev(event, &id)) { + id = strtol(event, NULL, 0); + } + if (pmev(equiv, &id_eqv)) { + id_eqv = strtol(equiv, NULL, 0); + } + if (!(table = get_eqv_event(id))) { + if (eqv_num == APM_MAX_EQUIV_EVENTS - 1) { + fprintf(stderr, "%s: Too many rules\n", main_argv[0]); + exit(1); + } + table = &eqv_event[eqv_num++]; + table->aee_event = id; + table->aee_equiv = PMEV_DEFAULT; + table->aee_resume = PMEV_DEFAULT; + } + if (strcasecmp(mode, "default") == 0) { + mode_type = MODE_DEFAULT; + } + else if (strcasecmp(mode, "resume") == 0) { + mode_type = MODE_RESUME; + } + else { + fprintf(stderr, "%s: %d : Unknown keyword '%s'\n", config_file, i, mode); + exit(1); + } + switch (mode_type) { + case MODE_DEFAULT: + table->aee_equiv = table->aee_resume = id_eqv; + break; + case MODE_RESUME: + table->aee_resume = id_eqv; + break; + } + } + if (verbose) { + printf("%-14s%-14s%-14s\n", " Original ", " Equivalent ", " After Resume "); + for (i = 0; i < eqv_num; i++) { + printf(" 0x%04x ", eqv_event[i].aee_event); + if (eqv_event[i].aee_equiv != PMEV_DEFAULT) { + printf(" 0x%04x ", eqv_event[i].aee_equiv); + } + else { + printf(" default "); + } + if (eqv_event[i].aee_resume != PMEV_DEFAULT) { + printf(" 0x%04x ", eqv_event[i].aee_resume); + } + else { + printf(" default "); + } + printf("\n"); + } + } +} + +static void +entry_eqv(int dh) +{ + int i; + + for (i = 0; i < eqv_num; i++) { + if (ioctl(dh, APMIO_DEFEQV, &eqv_event[i]) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_DEFEQV.\n", main_argv[0]); + exit(1); + } + } +} + +static void +flush_eqv(int dh) +{ + if (ioctl(dh, APMIO_FLUSHEQV, NULL) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_FLUSHBUF.\n", main_argv[0]); + exit(1); + } +} + +static void +enable_apm(int dh) +{ + if (ioctl(dh, APMIO_ENABLE, NULL) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_ENABLE.\n", main_argv[0]); + exit(1); + } +} + +static void +disable_apm(int dh) +{ + if (ioctl(dh, APMIO_DISABLE, NULL) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_DISABLE.\n", main_argv[0]); + exit(1); + } +} + +static void +haltcpu_apm(int dh) +{ + if (ioctl(dh, APMIO_HALTCPU, NULL) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_HALTCPU.\n", main_argv[0]); + exit(1); + } +} + +static void +nothaltcpu_apm(int dh) +{ + if (ioctl(dh, APMIO_NOTHALTCPU, NULL) == -1) { + fprintf(stderr, "%s: Can't ioctl APMIO_NOTHALTCPU.\n", main_argv[0]); + exit(1); + } +} +int +main(int argc, char *argv[]) +{ + int i, dh; + FILE *fp; + + main_argc = argc; + main_argv = argv; + if ((dh = open(APMDEV, O_RDWR)) == -1) { + fprintf(stderr, "%s: Can't open '%s'\n", argv[0], APMDEV); + exit(1); + } + parse_option(); + + /* disable operation is executed first */ + if (disable) { + disable_apm(dh); + } + if (init) { + if (!(fp = fopen(config_file, "r"))) { + fprintf(stderr, "%s: Can't open config file\n", CONFIGFILE); + exit(1); + } + parse_config_file(fp); + entry_eqv(dh); + } + if (flush) { + flush_eqv(dh); + } + if (haltcpu) { + haltcpu_apm(dh); + } + if (nothaltcpu) { + nothaltcpu_apm(dh); + } + /* enable operation is executed last */ + if (enable) { + enable_apm(dh); + } + return 0; +} -- cgit v1.1