Laptop Advanced Power Management support (userland end) by HOSOKAWA Tatsumi.
Submitted by: HOSOKAWA Tatsumi
This commit is contained in:
parent
22414e535a
commit
140cffd349
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3259
10
usr.sbin/apm/Makefile
Normal file
10
usr.sbin/apm/Makefile
Normal file
@ -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 <bsd.prog.mk>
|
157
usr.sbin/apm/apm.c
Normal file
157
usr.sbin/apm/apm.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* LP (Laptop Package)
|
||||
*
|
||||
* Copyright (C) 1994 by HOSOKAWA Tatasumi <hosokawa@mt.cs.keio.ac.jp>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <machine/apm_bios.h>
|
||||
|
||||
#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;
|
||||
}
|
8
usr.sbin/apmconf/Makefile
Normal file
8
usr.sbin/apmconf/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# $Id$
|
||||
|
||||
PROG= apmconf
|
||||
# BINMODE= 550
|
||||
# BINOWN= root
|
||||
NOMAN= 1
|
||||
|
||||
.include <bsd.prog.mk>
|
349
usr.sbin/apmconf/apmconf.c
Normal file
349
usr.sbin/apmconf/apmconf.c
Normal file
@ -0,0 +1,349 @@
|
||||
/*
|
||||
* LP (Laptop Package)
|
||||
*
|
||||
* Copyright (C) 1994 by HOSOKAWA Tatasumi <hosokawa@mt.cs.keio.ac.jp>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <machine/apm_bios.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user