Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/acpi/acpiconf/acpiconf.c
Show All 31 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <libxo/xo.h> | |||||
#include <dev/acpica/acpiio.h> | #include <dev/acpica/acpiio.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#define ACPIDEV "/dev/acpi" | #define ACPIDEV "/dev/acpi" | ||||
static int acpifd; | static int acpifd; | ||||
static void | static void | ||||
acpi_init(void) | acpi_init(void) | ||||
{ | { | ||||
acpifd = open(ACPIDEV, O_RDWR); | acpifd = open(ACPIDEV, O_RDWR); | ||||
if (acpifd == -1) | if (acpifd == -1) | ||||
acpifd = open(ACPIDEV, O_RDONLY); | acpifd = open(ACPIDEV, O_RDONLY); | ||||
if (acpifd == -1) | if (acpifd == -1) | ||||
err(EX_OSFILE, ACPIDEV); | xo_err(EX_OSFILE, ACPIDEV); | ||||
} | } | ||||
/* Prepare to sleep and then wait for the signal that sleeping can occur. */ | /* Prepare to sleep and then wait for the signal that sleeping can occur. */ | ||||
static void | static void | ||||
acpi_sleep(int sleep_type) | acpi_sleep(int sleep_type) | ||||
{ | { | ||||
int ret; | int ret; | ||||
/* Notify OS that we want to sleep. devd(8) gets this notify. */ | /* Notify OS that we want to sleep. devd(8) gets this notify. */ | ||||
ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type); | ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type); | ||||
if (ret != 0) | if (ret != 0) | ||||
err(EX_IOERR, "request sleep type (%d) failed", sleep_type); | xo_err(EX_IOERR, "request sleep type (%d) failed", sleep_type); | ||||
} | } | ||||
/* Ack or abort a pending suspend request. */ | /* Ack or abort a pending suspend request. */ | ||||
static void | static void | ||||
acpi_sleep_ack(int err_val) | acpi_sleep_ack(int err_val) | ||||
{ | { | ||||
int ret; | int ret; | ||||
ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val); | ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val); | ||||
if (ret != 0) | if (ret != 0) | ||||
err(EX_IOERR, "ack sleep type failed"); | xo_err(EX_IOERR, "ack sleep type failed"); | ||||
} | } | ||||
/* should be a acpi define, but doesn't appear to be */ | /* should be a acpi define, but doesn't appear to be */ | ||||
#define UNKNOWN_CAP 0xffffffff | #define UNKNOWN_CAP 0xffffffff | ||||
#define UNKNOWN_VOLTAGE 0xffffffff | #define UNKNOWN_VOLTAGE 0xffffffff | ||||
static int | static int | ||||
acpi_battinfo(int num) | acpi_battinfo(int num) | ||||
{ | { | ||||
union acpi_battery_ioctl_arg battio; | union acpi_battery_ioctl_arg battio; | ||||
const char *pwr_units; | const char *pwr_units; | ||||
int hours, min, amp; | int hours, min, amp; | ||||
uint32_t volt; | uint32_t volt; | ||||
if (num < 0 || num > 64) | if (num < 0 || num > 64) | ||||
errx(EX_USAGE, "invalid battery %d", num); | xo_errx(EX_USAGE, "invalid battery %d", num); | ||||
/* Print battery design information. */ | /* Print battery design information. */ | ||||
battio.unit = num; | battio.unit = num; | ||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1) | if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1) | ||||
err(EX_IOERR, "get battery info (%d) failed", num); | xo_err(EX_IOERR, "get battery info (%d) failed", num); | ||||
amp = battio.bix.units; | amp = battio.bix.units; | ||||
pwr_units = amp ? "mA" : "mW"; | pwr_units = amp ? "mA" : "mW"; | ||||
if (battio.bix.dcap == UNKNOWN_CAP) | if (battio.bix.dcap == UNKNOWN_CAP) | ||||
printf("Design capacity:\tunknown\n"); | xo_emit("{Lc:Design capacity}{P:\t}{:design-capacity/unknown}\n"); | ||||
else | else | ||||
printf("Design capacity:\t%d %sh\n", battio.bix.dcap, | xo_emit("{Lc:Design capacity}{P:\t}{:design-capacity/%d}{Uw:/%sh}\n", | ||||
pwr_units); | battio.bix.dcap, pwr_units); | ||||
if (battio.bix.lfcap == UNKNOWN_CAP) | if (battio.bix.lfcap == UNKNOWN_CAP) | ||||
printf("Last full capacity:\tunknown\n"); | xo_emit("{Lc:Last full capacity}{P:\t}{:last-full-capacity/unknown}\n"); | ||||
else | else | ||||
printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap, | xo_emit("{Lc:Last full capacity}{P:\t}{:last-full-capacity/%d}{Uw:/%sh}\n", | ||||
pwr_units); | battio.bix.lfcap, pwr_units); | ||||
printf("Technology:\t\t%s\n", battio.bix.btech == 0 ? | xo_emit("{Lc:Technology}{P:\t\t}{:technology}\n", battio.bix.btech == 0 ? | ||||
"primary (non-rechargeable)" : "secondary (rechargeable)"); | "primary (non-rechargeable)" : "secondary (rechargeable)"); | ||||
if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) { | if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) { | ||||
printf("Battery Swappable Capability:\t"); | xo_emit("{Lc:Battery Swappable Capability}{P:\t}"); | ||||
if (battio.bix.scap == ACPI_BIX_SCAP_NO) | if (battio.bix.scap == ACPI_BIX_SCAP_NO) | ||||
printf("Non-swappable\n"); | xo_emit("{:swappable/Non-swappable/no}\n"); | ||||
else if (battio.bix.scap == ACPI_BIX_SCAP_COLD) | else if (battio.bix.scap == ACPI_BIX_SCAP_COLD) | ||||
printf("cold swap\n"); | xo_emit("{:swappable/cold swap/cold}\n"); | ||||
else if (battio.bix.scap == ACPI_BIX_SCAP_HOT) | else if (battio.bix.scap == ACPI_BIX_SCAP_HOT) | ||||
printf("hot swap\n"); | xo_emit("{:swappable/hot swap/hot}\n"); | ||||
else | else | ||||
printf("unknown\n"); | xo_emit("{:swappable/unknown}\n"); | ||||
} | } | ||||
if (battio.bix.dvol == UNKNOWN_CAP) | if (battio.bix.dvol == UNKNOWN_CAP) | ||||
printf("Design voltage:\t\tunknown\n"); | xo_emit("{Lc:Design voltage}{P:\t\t}{:voltage/unknown}\n"); | ||||
else | else | ||||
printf("Design voltage:\t\t%d mV\n", battio.bix.dvol); | xo_emit("{Lc:Design voltage}{P:\t\t}{:voltage/%d}{Uw:mV}\n", battio.bix.dvol); | ||||
printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units); | xo_emit("{Lc:Capacity (warn)}{P:\t}{:warn-capacity/%d}{Uw:/%sh}\n", | ||||
printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units); | battio.bix.wcap, pwr_units); | ||||
xo_emit("{Lc:Capacity (low)}{P:\t\t}{:low-capacity/%d}{Uw:/%sh}\n", | |||||
battio.bix.lcap, pwr_units); | |||||
if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) { | if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) { | ||||
if (battio.bix.cycles != ACPI_BATT_UNKNOWN) | if (battio.bix.cycles != ACPI_BATT_UNKNOWN) | ||||
printf("Cycle Count:\t\t%d\n", battio.bix.cycles); | xo_emit("{Lc:Cycle Count}{P:\t\t}{:cycles/%d}\n", battio.bix.cycles); | ||||
printf("Mesurement Accuracy:\t%d %%\n", | xo_emit("{Lc:Mesurement Accuracy}{P:\t}{:accuracy/%d}{Uw:%%}\n", | ||||
battio.bix.accuracy / 1000); | battio.bix.accuracy / 1000); | ||||
if (battio.bix.stmax != ACPI_BATT_UNKNOWN) | if (battio.bix.stmax != ACPI_BATT_UNKNOWN) | ||||
printf("Max Sampling Time:\t%d ms\n", | xo_emit("{Lc:Max Sampling Time}{P:\t}{:sampling-max/%d}{Uw:ms}\n", | ||||
battio.bix.stmax); | battio.bix.stmax); | ||||
if (battio.bix.stmin != ACPI_BATT_UNKNOWN) | if (battio.bix.stmin != ACPI_BATT_UNKNOWN) | ||||
printf("Min Sampling Time:\t%d ms\n", | xo_emit("{Lc:Min Sampling Time}{P:\t}{:sampling-min/%d}{Uw:ms}\n", | ||||
battio.bix.stmin); | battio.bix.stmin); | ||||
printf("Max Average Interval:\t%d ms\n", | xo_emit("{Lc:Max Average Interval}{P:\t}{:avg-interval-max/%d}{Uw:ms}\n", | ||||
battio.bix.aimax); | battio.bix.aimax); | ||||
printf("Min Average Interval:\t%d ms\n", | xo_emit("{Lc:Min Average Interval}{P:\t}{:avg-interval-min/%d}{Uw:ms}\n", | ||||
battio.bix.aimin); | battio.bix.aimin); | ||||
} | } | ||||
printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units); | xo_emit("{Lc:Low\\/warn granularity}{P:\t}{:granularity-lw/%d}{Uw:/%sh}\n", | ||||
printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units); | battio.bix.gra1, pwr_units); | ||||
printf("Model number:\t\t%s\n", battio.bix.model); | xo_emit("{Lc:Warn\\/full granularity}{P:\t}{:granularity-wf/%d}{Uw:/%sh}\n", | ||||
printf("Serial number:\t\t%s\n", battio.bix.serial); | battio.bix.gra2, pwr_units); | ||||
printf("Type:\t\t\t%s\n", battio.bix.type); | xo_emit("{Lc:Model number}{P:\t\t}{:model}\n", battio.bix.model); | ||||
printf("OEM info:\t\t%s\n", battio.bix.oeminfo); | xo_emit("{Lc:Serial number}{P:\t\t}{:serial}\n", battio.bix.serial); | ||||
xo_emit("{Lc:Type}{P:\t\t\t}{:type}\n", battio.bix.type); | |||||
xo_emit("{Lc:OEM info}{P:\t\t}{:oeminfo}\n", battio.bix.oeminfo); | |||||
/* Fetch battery voltage information. */ | /* Fetch battery voltage information. */ | ||||
volt = UNKNOWN_VOLTAGE; | volt = UNKNOWN_VOLTAGE; | ||||
battio.unit = num; | battio.unit = num; | ||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1) | if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1) | ||||
err(EX_IOERR, "get battery status (%d) failed", num); | xo_err(EX_IOERR, "get battery status (%d) failed", num); | ||||
if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) | if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) | ||||
volt = battio.bst.volt; | volt = battio.bst.volt; | ||||
/* Print current battery state information. */ | /* Print current battery state information. */ | ||||
battio.unit = num; | battio.unit = num; | ||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1) | if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1) | ||||
err(EX_IOERR, "get battery user info (%d) failed", num); | xo_err(EX_IOERR, "get battery user info (%d) failed", num); | ||||
if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) { | if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) { | ||||
const char *state; | const char *state; | ||||
switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) { | switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) { | ||||
case 0: | case 0: | ||||
state = "high"; | state = "high"; | ||||
break; | break; | ||||
case ACPI_BATT_STAT_DISCHARG: | case ACPI_BATT_STAT_DISCHARG: | ||||
state = "discharging"; | state = "discharging"; | ||||
break; | break; | ||||
case ACPI_BATT_STAT_CHARGING: | case ACPI_BATT_STAT_CHARGING: | ||||
state = "charging"; | state = "charging"; | ||||
break; | break; | ||||
case ACPI_BATT_STAT_CRITICAL: | case ACPI_BATT_STAT_CRITICAL: | ||||
state = "critical"; | state = "critical"; | ||||
break; | break; | ||||
case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL: | case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL: | ||||
state = "critical discharging"; | state = "critical discharging"; | ||||
break; | break; | ||||
case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL: | case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL: | ||||
state = "critical charging"; | state = "critical charging"; | ||||
break; | break; | ||||
default: | default: | ||||
state = "invalid"; | state = "invalid"; | ||||
} | } | ||||
printf("State:\t\t\t%s\n", state); | xo_emit("{Lc:State}{P:\t\t\t}{:state}\n", state); | ||||
if (battio.battinfo.cap == -1) | if (battio.battinfo.cap == -1) | ||||
printf("Remaining capacity:\tunknown\n"); | xo_emit("{Lc:Remaining capacity}{P:\t}{:remaining-capacity/unknown}\n"); | ||||
else | else | ||||
printf("Remaining capacity:\t%d%%\n", | xo_emit("{Lc:Remaining capacity}{P:\t}{:remaining-capacity/%d}{D:%%}\n", | ||||
battio.battinfo.cap); | battio.battinfo.cap); | ||||
if (battio.battinfo.min == -1) | if (battio.battinfo.min == -1) | ||||
printf("Remaining time:\t\tunknown\n"); | xo_emit("{Lc:Remaining time}{P:\t\t}{:remaining-time/unknown}\n"); | ||||
else { | else { | ||||
hours = battio.battinfo.min / 60; | hours = battio.battinfo.min / 60; | ||||
min = battio.battinfo.min % 60; | min = battio.battinfo.min % 60; | ||||
printf("Remaining time:\t\t%d:%02d\n", hours, min); | xo_emit("{Lc:Remaining time}{P:\t\t}{:remaining-time/%d:%02d}\n", hours, min); | ||||
} | } | ||||
if (battio.battinfo.rate == -1) | if (battio.battinfo.rate == -1) | ||||
printf("Present rate:\t\tunknown\n"); | xo_emit("{Lc:Present rate}{P:\t\t}{:present-rate/unknown}\n"); | ||||
else if (amp && volt != UNKNOWN_VOLTAGE) { | else if (amp && volt != UNKNOWN_VOLTAGE) { | ||||
printf("Present rate:\t\t%d mA (%d mW)\n", | xo_emit("{Lc:Present rate}{P:\t\t}{:present-rate/%d}{Uw:mA} {D:(}{:present-rate-mw/%d}{Uw:mW}{D:)}\n", | ||||
battio.battinfo.rate, | battio.battinfo.rate, | ||||
battio.battinfo.rate * volt / 1000); | battio.battinfo.rate * volt / 1000); | ||||
} else | } else | ||||
printf("Present rate:\t\t%d %s\n", | xo_emit("{Lc:Present rate}{P:\t\t}{:present-rate/%d}{Uw:/%s}\n", | ||||
battio.battinfo.rate, pwr_units); | battio.battinfo.rate, pwr_units); | ||||
} else | } else | ||||
printf("State:\t\t\tnot present\n"); | xo_emit("{Lc:State}{P:\t\t\t}{:state/not present}\n"); | ||||
/* Print battery voltage information. */ | /* Print battery voltage information. */ | ||||
if (volt == UNKNOWN_VOLTAGE) | if (volt == UNKNOWN_VOLTAGE) | ||||
printf("Present voltage:\tunknown\n"); | xo_emit("{Lc:Present voltage}{P:\t}{q:present-voltage/unknown}\n"); | ||||
else | else | ||||
printf("Present voltage:\t%d mV\n", volt); | xo_emit("{Lc:Present voltage}{P:\t}{q:present-voltage/%d}{Uw:mV}\n", volt); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
usage(const char* prog) | usage(const char* prog) | ||||
{ | { | ||||
printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog); | xo_error("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog); | ||||
xo_close_container("acpiconf"); | |||||
xo_finish(); | |||||
exit(0); | exit(0); | ||||
} | } | ||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
char *prog, *end; | char *prog, *end; | ||||
int c, sleep_type, battery, ack; | int c, sleep_type, battery, ack; | ||||
int iflag = 0, kflag = 0, sflag = 0; | int iflag = 0, kflag = 0, sflag = 0; | ||||
prog = argv[0]; | prog = argv[0]; | ||||
argc = xo_parse_args(argc, argv); | |||||
if (argc < 0) | |||||
exit(1); | |||||
xo_open_container("acpiconf"); | |||||
if (argc < 2) | if (argc < 2) | ||||
usage(prog); | usage(prog); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
sleep_type = -1; | sleep_type = -1; | ||||
acpi_init(); | acpi_init(); | ||||
while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { | while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { | ||||
switch (c) { | switch (c) { | ||||
case 'i': | case 'i': | ||||
iflag = 1; | iflag = 1; | ||||
battery = strtol(optarg, &end, 10); | battery = strtol(optarg, &end, 10); | ||||
if ((size_t)(end - optarg) != strlen(optarg)) | if ((size_t)(end - optarg) != strlen(optarg)) | ||||
errx(EX_USAGE, "invalid battery"); | xo_errx(EX_USAGE, "invalid battery"); | ||||
break; | break; | ||||
case 'k': | case 'k': | ||||
kflag = 1; | kflag = 1; | ||||
ack = strtol(optarg, &end, 10); | ack = strtol(optarg, &end, 10); | ||||
if ((size_t)(end - optarg) != strlen(optarg)) | if ((size_t)(end - optarg) != strlen(optarg)) | ||||
errx(EX_USAGE, "invalid ack argument"); | xo_errx(EX_USAGE, "invalid ack argument"); | ||||
break; | break; | ||||
case 's': | case 's': | ||||
sflag = 1; | sflag = 1; | ||||
if (optarg[0] == 'S') | if (optarg[0] == 'S') | ||||
optarg++; | optarg++; | ||||
sleep_type = strtol(optarg, &end, 10); | sleep_type = strtol(optarg, &end, 10); | ||||
if ((size_t)(end - optarg) != strlen(optarg)) | if ((size_t)(end - optarg) != strlen(optarg)) | ||||
errx(EX_USAGE, "invalid sleep type"); | xo_errx(EX_USAGE, "invalid sleep type"); | ||||
if (sleep_type < 1 || sleep_type > 4) | if (sleep_type < 1 || sleep_type > 4) | ||||
errx(EX_USAGE, "invalid sleep type (%d)", | xo_errx(EX_USAGE, "invalid sleep type (%d)", | ||||
sleep_type); | sleep_type); | ||||
break; | break; | ||||
case 'h': | case 'h': | ||||
default: | default: | ||||
usage(prog); | usage(prog); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
} | } | ||||
} | } | ||||
argc -= optind; | argc -= optind; | ||||
argv += optind; | argv += optind; | ||||
if (iflag != 0 && kflag != 0 && sflag != 0) | if (iflag != 0 && kflag != 0 && sflag != 0) | ||||
errx(EX_USAGE, "-i, -k and -s are mutually exclusive"); | xo_errx(EX_USAGE, "-i, -k and -s are mutually exclusive"); | ||||
if (iflag != 0) { | if (iflag != 0) { | ||||
if (kflag != 0) | if (kflag != 0) | ||||
errx(EX_USAGE, "-i and -k are mutually exclusive"); | xo_errx(EX_USAGE, "-i and -k are mutually exclusive"); | ||||
if (sflag != 0) | if (sflag != 0) | ||||
errx(EX_USAGE, "-i and -s are mutually exclusive"); | xo_errx(EX_USAGE, "-i and -s are mutually exclusive"); | ||||
acpi_battinfo(battery); | acpi_battinfo(battery); | ||||
} | } | ||||
if (kflag != 0) { | if (kflag != 0) { | ||||
if (sflag != 0) | if (sflag != 0) | ||||
errx(EX_USAGE, "-k and -s are mutually exclusive"); | xo_errx(EX_USAGE, "-k and -s are mutually exclusive"); | ||||
acpi_sleep_ack(ack); | acpi_sleep_ack(ack); | ||||
} | } | ||||
if (sflag != 0) | if (sflag != 0) | ||||
acpi_sleep(sleep_type); | acpi_sleep(sleep_type); | ||||
close(acpifd); | close(acpifd); | ||||
xo_close_container("acpiconf"); | |||||
xo_finish(); | |||||
exit (0); | exit (0); | ||||
} | } |