165283Siwasaki/*- 265283Siwasaki * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 365283Siwasaki * All rights reserved. 465283Siwasaki * 565283Siwasaki * Redistribution and use in source and binary forms, with or without 665283Siwasaki * modification, are permitted provided that the following conditions 765283Siwasaki * are met: 865283Siwasaki * 1. Redistributions of source code must retain the above copyright 965283Siwasaki * notice, this list of conditions and the following disclaimer. 1065283Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 1165283Siwasaki * notice, this list of conditions and the following disclaimer in the 1265283Siwasaki * documentation and/or other materials provided with the distribution. 1365283Siwasaki * 1465283Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1565283Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1665283Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1765283Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1865283Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1965283Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2065283Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2165283Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2265283Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2365283Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2465283Siwasaki * SUCH DAMAGE. 2565283Siwasaki * 2665283Siwasaki * $Id: acpiconf.c,v 1.5 2000/08/08 14:12:19 iwasaki Exp $ 2765283Siwasaki * $FreeBSD: releng/10.2/usr.sbin/acpi/acpiconf/acpiconf.c 281389 2015-04-11 01:17:19Z jkim $ 2865283Siwasaki */ 2965283Siwasaki 3065283Siwasaki#include <sys/param.h> 3165283Siwasaki 3265283Siwasaki#include <err.h> 3365283Siwasaki#include <fcntl.h> 3465283Siwasaki#include <stdio.h> 3566490Smsmith#include <sys/ioctl.h> 3687121Scjc#include <sysexits.h> 3765283Siwasaki#include <unistd.h> 3865283Siwasaki 3968475Siwasaki#include <dev/acpica/acpiio.h> 4068475Siwasaki 41193531Sjkim#include <contrib/dev/acpica/include/acpi.h> 42193531Sjkim 43124001Snjl#define ACPIDEV "/dev/acpi" 4465283Siwasaki 45120036Snjlstatic int acpifd; 46126625Stakawata 47137666Sphilipstatic void 48137638Sphilipacpi_init(void) 49120036Snjl{ 50120036Snjl acpifd = open(ACPIDEV, O_RDWR); 51137763Simp if (acpifd == -1) 52126609Stakawata acpifd = open(ACPIDEV, O_RDONLY); 53137763Simp if (acpifd == -1) 54120036Snjl err(EX_OSFILE, ACPIDEV); 55120036Snjl} 56120036Snjl 57170976Snjl/* Prepare to sleep and then wait for the signal that sleeping can occur. */ 58170976Snjlstatic void 5965283Siwasakiacpi_sleep(int sleep_type) 6065283Siwasaki{ 61124001Snjl int ret; 62170976Snjl 63170976Snjl /* Notify OS that we want to sleep. devd(8) gets this notify. */ 64170976Snjl ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type); 65170976Snjl if (ret != 0) 66170976Snjl err(EX_IOERR, "request sleep type (%d) failed", sleep_type); 67170976Snjl} 68124001Snjl 69170976Snjl/* Ack or abort a pending suspend request. */ 70170976Snjlstatic void 71170976Snjlacpi_sleep_ack(int err_val) 72170976Snjl{ 73170976Snjl int ret; 74124001Snjl 75170976Snjl ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val); 76124001Snjl if (ret != 0) 77170976Snjl err(EX_IOERR, "ack sleep type failed"); 7865283Siwasaki} 7965283Siwasaki 80138049Simp/* should be a acpi define, but doesn't appear to be */ 81138049Simp#define UNKNOWN_CAP 0xffffffff 82148491Snjl#define UNKNOWN_VOLTAGE 0xffffffff 83138049Simp 84120036Snjlstatic int 85120036Snjlacpi_battinfo(int num) 86120036Snjl{ 87120036Snjl union acpi_battery_ioctl_arg battio; 88120036Snjl const char *pwr_units; 89211763Smav int hours, min, amp; 90211763Smav uint32_t volt; 91120036Snjl 92120036Snjl if (num < 0 || num > 64) 93120036Snjl err(EX_USAGE, "invalid battery %d", num); 94120036Snjl 95148491Snjl /* Print battery design information. */ 96120036Snjl battio.unit = num; 97148310Snjl if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1) 98120036Snjl err(EX_IOERR, "get battery info (%d) failed", num); 99211763Smav amp = battio.bif.units; 100211763Smav pwr_units = amp ? "mA" : "mW"; 101138049Simp if (battio.bif.dcap == UNKNOWN_CAP) 102148491Snjl printf("Design capacity:\tunknown\n"); 103138049Simp else 104148491Snjl printf("Design capacity:\t%d %sh\n", battio.bif.dcap, 105148491Snjl pwr_units); 106138049Simp if (battio.bif.lfcap == UNKNOWN_CAP) 107148491Snjl printf("Last full capacity:\tunknown\n"); 108138049Simp else 109148491Snjl printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap, 110138049Simp pwr_units); 111120036Snjl printf("Technology:\t\t%s\n", battio.bif.btech == 0 ? 112120036Snjl "primary (non-rechargeable)" : "secondary (rechargeable)"); 113138049Simp if (battio.bif.dvol == UNKNOWN_CAP) 114148491Snjl printf("Design voltage:\t\tunknown\n"); 115138049Simp else 116138049Simp printf("Design voltage:\t\t%d mV\n", battio.bif.dvol); 117148491Snjl printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units); 118148491Snjl printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units); 119148491Snjl printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units); 120148491Snjl printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units); 121120036Snjl printf("Model number:\t\t%s\n", battio.bif.model); 122120036Snjl printf("Serial number:\t\t%s\n", battio.bif.serial); 123120036Snjl printf("Type:\t\t\t%s\n", battio.bif.type); 124120036Snjl printf("OEM info:\t\t%s\n", battio.bif.oeminfo); 125120036Snjl 126211763Smav /* Fetch battery voltage information. */ 127211763Smav volt = UNKNOWN_VOLTAGE; 128211763Smav battio.unit = num; 129211763Smav if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1) 130211763Smav err(EX_IOERR, "get battery status (%d) failed", num); 131211763Smav if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) 132211763Smav volt = battio.bst.volt; 133211763Smav 134148491Snjl /* Print current battery state information. */ 135138044Sphk battio.unit = num; 136148491Snjl if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1) 137148491Snjl err(EX_IOERR, "get battery user info (%d) failed", num); 138148491Snjl if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) { 139281389Sjkim const char *state; 140281389Sjkim switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) { 141281389Sjkim case 0: 142281389Sjkim state = "high"; 143281389Sjkim break; 144281389Sjkim case ACPI_BATT_STAT_DISCHARG: 145281389Sjkim state = "discharging"; 146281389Sjkim break; 147281389Sjkim case ACPI_BATT_STAT_CHARGING: 148281389Sjkim state = "charging"; 149281389Sjkim break; 150281389Sjkim case ACPI_BATT_STAT_CRITICAL: 151281389Sjkim state = "critical"; 152281389Sjkim break; 153281389Sjkim case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL: 154281389Sjkim state = "critical discharging"; 155281389Sjkim break; 156281389Sjkim case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL: 157281389Sjkim state = "critical charging"; 158281389Sjkim break; 159281389Sjkim default: 160281389Sjkim state = "invalid"; 161281389Sjkim } 162281389Sjkim printf("State:\t\t\t%s\n", state); 163148491Snjl if (battio.battinfo.cap == -1) 164148491Snjl printf("Remaining capacity:\tunknown\n"); 165138049Simp else 166148491Snjl printf("Remaining capacity:\t%d%%\n", 167148491Snjl battio.battinfo.cap); 168148491Snjl if (battio.battinfo.min == -1) 169148493Snjl printf("Remaining time:\t\tunknown\n"); 170148491Snjl else { 171148491Snjl hours = battio.battinfo.min / 60; 172148491Snjl min = battio.battinfo.min % 60; 173148491Snjl printf("Remaining time:\t\t%d:%02d\n", hours, min); 174148491Snjl } 175148491Snjl if (battio.battinfo.rate == -1) 176148491Snjl printf("Present rate:\t\tunknown\n"); 177211763Smav else if (amp && volt != UNKNOWN_VOLTAGE) { 178211763Smav printf("Present rate:\t\t%d mA (%d mW)\n", 179211763Smav battio.battinfo.rate, 180211763Smav battio.battinfo.rate * volt / 1000); 181211763Smav } else 182148491Snjl printf("Present rate:\t\t%d %s\n", 183148491Snjl battio.battinfo.rate, pwr_units); 184148491Snjl } else 185148491Snjl printf("State:\t\t\tnot present\n"); 186148491Snjl 187148491Snjl /* Print battery voltage information. */ 188211763Smav if (volt == UNKNOWN_VOLTAGE) 189211763Smav printf("Present voltage:\tunknown\n"); 190211763Smav else 191211763Smav printf("Present voltage:\t%d mV\n", volt); 192148491Snjl 193120036Snjl return (0); 194120036Snjl} 195120036Snjl 19668475Siwasakistatic void 19768475Siwasakiusage(const char* prog) 19868475Siwasaki{ 199170976Snjl printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog); 20068475Siwasaki exit(0); 20168475Siwasaki} 20268475Siwasaki 20365283Siwasakiint 20465283Siwasakimain(int argc, char *argv[]) 20565283Siwasaki{ 20668475Siwasaki char c, *prog; 20765283Siwasaki int sleep_type; 20865283Siwasaki 20968475Siwasaki prog = argv[0]; 210120036Snjl if (argc < 2) 211120036Snjl usage(prog); 212120036Snjl /* NOTREACHED */ 213120036Snjl 21465283Siwasaki sleep_type = -1; 215120036Snjl acpi_init(); 216170976Snjl while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { 21765283Siwasaki switch (c) { 218120036Snjl case 'i': 219120036Snjl acpi_battinfo(atoi(optarg)); 220120036Snjl break; 221170976Snjl case 'k': 222170976Snjl acpi_sleep_ack(atoi(optarg)); 223170976Snjl break; 22465283Siwasaki case 's': 225118127Snjl if (optarg[0] == 'S') 226118127Snjl sleep_type = optarg[1] - '0'; 227118127Snjl else 228118127Snjl sleep_type = optarg[0] - '0'; 229170976Snjl if (sleep_type < 1 || sleep_type > 4) 23087121Scjc errx(EX_USAGE, "invalid sleep type (%d)", 231120036Snjl sleep_type); 23265283Siwasaki break; 233120036Snjl case 'h': 23465283Siwasaki default: 235120036Snjl usage(prog); 236120036Snjl /* NOTREACHED */ 23765283Siwasaki } 23865283Siwasaki } 239120036Snjl argc -= optind; 240120036Snjl argv += optind; 24165283Siwasaki 242170976Snjl if (sleep_type != -1) 24365283Siwasaki acpi_sleep(sleep_type); 244120036Snjl 245120036Snjl close(acpifd); 246120036Snjl exit (0); 24765283Siwasaki} 248