Path: blob/main/usr.sbin/acpi/acpiconf/acpiconf.c
106842 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 1999 Mitsuru IWASAKI <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*27* $Id: acpiconf.c,v 1.5 2000/08/08 14:12:19 iwasaki Exp $28*/2930#include <sys/param.h>3132#include <err.h>33#include <fcntl.h>34#include <stdio.h>35#include <sys/ioctl.h>36#include <sysexits.h>37#include <unistd.h>3839#include <dev/acpica/acpiio.h>4041#include <contrib/dev/acpica/include/acpi.h>4243#define ACPIDEV "/dev/acpi"4445static int acpifd;4647static void48acpi_init(void)49{50acpifd = open(ACPIDEV, O_RDWR);51if (acpifd == -1)52acpifd = open(ACPIDEV, O_RDONLY);53if (acpifd == -1)54err(EX_OSFILE, ACPIDEV);55}5657/* Prepare to sleep and then wait for the signal that sleeping can occur. */58static void59acpi_sleep(int sleep_type)60{61int ret;6263/* Notify OS that we want to sleep. devd(8) gets this notify. */64ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type);65if (ret != 0)66err(EX_IOERR, "request sleep type (%d) failed", sleep_type);67}6869/* Ack or abort a pending suspend request. */70static void71acpi_sleep_ack(int err_val)72{73int ret;7475ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val);76if (ret != 0)77err(EX_IOERR, "ack sleep type failed");78}7980/* should be a acpi define, but doesn't appear to be */81#define UNKNOWN_CAP 0xffffffff82#define UNKNOWN_VOLTAGE 0xffffffff8384static int85acpi_battinfo(int num)86{87union acpi_battery_ioctl_arg battio;88const char *pwr_units;89int hours, min, amp;90uint32_t volt;9192if (num < 0 || num > 64)93errx(EX_USAGE, "invalid battery %d", num);9495/* Print battery design information. */96battio.unit = num;97if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1)98err(EX_IOERR, "get battery info (%d) failed", num);99amp = battio.bix.units;100pwr_units = amp ? "mA" : "mW";101if (battio.bix.dcap == UNKNOWN_CAP)102printf("Design capacity:\tunknown\n");103else104printf("Design capacity:\t%d %sh\n", battio.bix.dcap,105pwr_units);106if (battio.bix.lfcap == UNKNOWN_CAP)107printf("Last full capacity:\tunknown\n");108else109printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap,110pwr_units);111printf("Technology:\t\t%s\n", battio.bix.btech == 0 ?112"primary (non-rechargeable)" : "secondary (rechargeable)");113if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) {114printf("Battery Swappable Capability:\t");115if (battio.bix.scap == ACPI_BIX_SCAP_NO)116printf("Non-swappable\n");117else if (battio.bix.scap == ACPI_BIX_SCAP_COLD)118printf("cold swap\n");119else if (battio.bix.scap == ACPI_BIX_SCAP_HOT)120printf("hot swap\n");121else122printf("unknown\n");123}124if (battio.bix.dvol == UNKNOWN_CAP)125printf("Design voltage:\t\tunknown\n");126else127printf("Design voltage:\t\t%d mV\n", battio.bix.dvol);128printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units);129printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units);130if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) {131if (battio.bix.cycles != ACPI_BATT_UNKNOWN)132printf("Cycle Count:\t\t%d\n", battio.bix.cycles);133printf("Measurement Accuracy:\t%d%%\n",134battio.bix.accuracy / 1000);135if (battio.bix.stmax != ACPI_BATT_UNKNOWN)136printf("Max Sampling Time:\t%d ms\n",137battio.bix.stmax);138if (battio.bix.stmin != ACPI_BATT_UNKNOWN)139printf("Min Sampling Time:\t%d ms\n",140battio.bix.stmin);141printf("Max Average Interval:\t%d ms\n",142battio.bix.aimax);143printf("Min Average Interval:\t%d ms\n",144battio.bix.aimin);145}146printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units);147printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units);148printf("Model number:\t\t%s\n", battio.bix.model);149printf("Serial number:\t\t%s\n", battio.bix.serial);150printf("Type:\t\t\t%s\n", battio.bix.type);151printf("OEM info:\t\t%s\n", battio.bix.oeminfo);152153/* Fetch battery voltage information. */154volt = UNKNOWN_VOLTAGE;155battio.unit = num;156if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1)157err(EX_IOERR, "get battery status (%d) failed", num);158if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT)159volt = battio.bst.volt;160161/* Print current battery state information. */162battio.unit = num;163if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1)164err(EX_IOERR, "get battery user info (%d) failed", num);165if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) {166const char *state;167switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) {168case 0:169state = "high";170break;171case ACPI_BATT_STAT_DISCHARG:172state = "discharging";173break;174case ACPI_BATT_STAT_CHARGING:175state = "charging";176break;177case ACPI_BATT_STAT_CRITICAL:178state = "critical";179break;180case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL:181state = "critical discharging";182break;183case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL:184state = "critical charging";185break;186default:187state = "invalid";188}189printf("State:\t\t\t%s\n", state);190if (battio.battinfo.cap == -1)191printf("Remaining capacity:\tunknown\n");192else193printf("Remaining capacity:\t%d%%\n",194battio.battinfo.cap);195if (battio.battinfo.min == -1)196printf("Remaining time:\t\tunknown\n");197else {198hours = battio.battinfo.min / 60;199min = battio.battinfo.min % 60;200printf("Remaining time:\t\t%d:%02d\n", hours, min);201}202if (battio.battinfo.rate == -1)203printf("Present rate:\t\tunknown\n");204else if (amp && volt != UNKNOWN_VOLTAGE) {205printf("Present rate:\t\t%d mA (%d mW)\n",206battio.battinfo.rate,207battio.battinfo.rate * volt / 1000);208} else209printf("Present rate:\t\t%d %s\n",210battio.battinfo.rate, pwr_units);211} else212printf("State:\t\t\tnot present\n");213214/* Print battery voltage information. */215if (volt == UNKNOWN_VOLTAGE)216printf("Present voltage:\tunknown\n");217else218printf("Present voltage:\t%d mV\n", volt);219220return (0);221}222223static void224usage(const char* prog)225{226printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog);227exit(0);228}229230int231main(int argc, char *argv[])232{233char *prog, *end;234int c, sleep_type, battery, ack;235int iflag = 0, kflag = 0, sflag = 0;236237prog = argv[0];238if (argc < 2)239usage(prog);240/* NOTREACHED */241242sleep_type = -1;243acpi_init();244while ((c = getopt(argc, argv, "hi:k:s:")) != -1) {245switch (c) {246case 'i':247iflag = 1;248battery = strtol(optarg, &end, 10);249if ((size_t)(end - optarg) != strlen(optarg))250errx(EX_USAGE, "invalid battery");251break;252case 'k':253kflag = 1;254ack = strtol(optarg, &end, 10);255if ((size_t)(end - optarg) != strlen(optarg))256errx(EX_USAGE, "invalid ack argument");257break;258case 's':259sflag = 1;260if (optarg[0] == 'S')261optarg++;262sleep_type = strtol(optarg, &end, 10);263if ((size_t)(end - optarg) != strlen(optarg))264errx(EX_USAGE, "invalid sleep type");265if (sleep_type < 1 || sleep_type > 4)266errx(EX_USAGE, "invalid sleep type (%d)",267sleep_type);268break;269case 'h':270default:271usage(prog);272/* NOTREACHED */273}274}275argc -= optind;276argv += optind;277278if (iflag != 0 && kflag != 0 && sflag != 0)279errx(EX_USAGE, "-i, -k and -s are mutually exclusive");280281if (iflag != 0) {282if (kflag != 0)283errx(EX_USAGE, "-i and -k are mutually exclusive");284if (sflag != 0)285errx(EX_USAGE, "-i and -s are mutually exclusive");286acpi_battinfo(battery);287}288289if (kflag != 0) {290if (sflag != 0)291errx(EX_USAGE, "-k and -s are mutually exclusive");292acpi_sleep_ack(ack);293}294295296if (sflag != 0)297acpi_sleep(sleep_type);298299close(acpifd);300exit (0);301}302303304