summaryrefslogtreecommitdiffstats
path: root/usr.sbin/apm/apm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/apm/apm.c')
-rw-r--r--usr.sbin/apm/apm.c197
1 files changed, 188 insertions, 9 deletions
diff --git a/usr.sbin/apm/apm.c b/usr.sbin/apm/apm.c
index 3229a2a..bf6184f 100644
--- a/usr.sbin/apm/apm.c
+++ b/usr.sbin/apm/apm.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] =
- "$Id: apm.c,v 1.12 1997/11/12 04:16:23 jdp Exp $";
+ "$Id: apm.c,v 1.13 1998/02/20 07:17:46 hosokawa Exp $";
#endif /* not lint */
#include <err.h>
@@ -26,18 +26,57 @@ static const char rcsid[] =
#include <sys/ioctl.h>
#include <unistd.h>
#include <machine/apm_bios.h>
+#include <time.h>
#define APMDEV "/dev/apm"
+#define xh(a) (((a) & 0xff00) >> 8)
+#define xl(a) ((a) & 0xff)
+#define APMERR(a) xh(a)
+
+int cmos_wall = 0; /* True when wall time is in cmos clock, else UTC */
+
void
usage()
{
fprintf(stderr, "%s\n%s\n",
- "usage: apm [-ablstz] [-d 1|0]",
+ "usage: apm [-ablstzZ] [-d 1|0] [-r delta]",
" zzz");
exit(1);
}
+int
+int2bcd(int i)
+{
+ int retval = 0;
+ int base = 0;
+
+ if (i >= 10000)
+ return -1;
+
+ while (i) {
+ retval |= (i % 10) << base;
+ i /= 10;
+ base += 4;
+ }
+ return retval;
+}
+
+int
+bcd2int(int bcd)
+{
+ int retval = 0;
+
+ if (bcd > 0x9999)
+ return -1;
+
+ while (bcd) {
+ retval = retval * 10 + ((bcd & 0xf000) >> 12);
+ bcd = (bcd & 0xfff) << 4;
+ }
+ return retval;
+}
+
void
apm_suspend(int fd)
{
@@ -46,6 +85,13 @@ apm_suspend(int fd)
}
void
+apm_standby(int fd)
+{
+ if (ioctl(fd, APMIO_STANDBY, NULL) == -1)
+ err(1, NULL);
+}
+
+void
apm_getinfo(int fd, apm_info_t aip)
{
if (ioctl(fd, APMIO_GETINFO, aip) == -1)
@@ -53,8 +99,11 @@ apm_getinfo(int fd, apm_info_t aip)
}
void
-print_all_info(apm_info_t aip)
+print_all_info(int fd, apm_info_t aip)
{
+ struct apm_bios_arg args;
+ int apmerr;
+
printf("APM version: %d.%d\n", aip->ai_major, aip->ai_minor);
printf("APM Managment: %s\n", (aip->ai_status ? "Enabled" : "Disabled"));
printf("AC Line status: ");
@@ -100,8 +149,96 @@ print_all_info(apm_info_t aip)
printf("%2d:%02d:%02d", h, m, s);
}
printf("\n");
-}
+ if (aip->ai_infoversion >= 1) {
+ printf("Number of batteries: ");
+ if (aip->ai_batteries == (u_int) -1)
+ printf("unknown\n");
+ else
+ printf("%d\n", aip->ai_batteries);
+ }
+ /*
+ * try to get the suspend timer
+ */
+ bzero(&args, sizeof(args));
+ args.eax = (APM_BIOS) << 8 | APM_RESUMETIMER;
+ args.ebx = PMDV_APMBIOS;
+ args.ecx = 0x0001;
+ if (ioctl(fd, APMIO_BIOS, &args)) {
+ err(1,"Get resume timer");
+ } else {
+ apmerr = APMERR(args.eax);
+ if (apmerr == 0x0d || apmerr == 0x86)
+ printf("Resume timer: disabled\n");
+ else if (apmerr)
+ fprintf(stderr,
+ "Failed to get the resume timer: APM error0x%x\n",
+ apmerr);
+ else {
+ /*
+ * OK. We have the time (all bcd).
+ * CH - seconds
+ * DH - hours
+ * DL - minutes
+ * xh(SI) - month (1-12)
+ * xl(SI) - day of month (1-31)
+ * DI - year
+ */
+ struct tm tm;
+ char buf[1024];
+ time_t t;
+
+ tm.tm_sec = bcd2int(xh(args.ecx));
+ tm.tm_min = bcd2int(xl(args.edx));
+ tm.tm_hour = bcd2int(xh(args.edx));
+ tm.tm_mday = bcd2int(xl(args.esi));
+ tm.tm_mon = bcd2int(xh(args.esi)) - 1;
+ tm.tm_year = bcd2int(args.edi) - 1900;
+ if (cmos_wall)
+ t = mktime(&tm);
+ else
+ t = timegm(&tm);
+ tm = *localtime(&t);
+ strftime(buf, sizeof(buf), "%c", &tm);
+ printf("Resume timer: %s\n", buf);
+ }
+ }
+
+ /*
+ * Get the ring indicator resume state
+ */
+ bzero(&args, sizeof(args));
+ args.eax = (APM_BIOS) << 8 | APM_RESUMEONRING;
+ args.ebx = PMDV_APMBIOS;
+ args.ecx = 0x0002;
+ if (ioctl(fd, APMIO_BIOS, &args) == 0) {
+ printf("Resume on ring indicator: %sabled\n",
+ args.ecx ? "en" : "dis");
+ }
+
+ if (aip->ai_infoversion >= 1) {
+ printf("APM Capacities:\n", aip->ai_capabilities);
+ if (aip->ai_capabilities == 0xff00)
+ printf("\tunknown\n");
+ if (aip->ai_capabilities & 0x01)
+ printf("\tglobal standby state\n");
+ if (aip->ai_capabilities & 0x02)
+ printf("\tglobal suspend state\n");
+ if (aip->ai_capabilities & 0x04)
+ printf("\tresume timer from standby\n");
+ if (aip->ai_capabilities & 0x08)
+ printf("\tresume timer from suspend\n");
+ if (aip->ai_capabilities & 0x10)
+ printf("\tRI resume from standby\n");
+ if (aip->ai_capabilities & 0x20)
+ printf("\tRI resume from suspend\n");
+ if (aip->ai_capabilities & 0x40)
+ printf("\tPCMCIA RI resume from standby\n");
+ if (aip->ai_capabilities & 0x80)
+ printf("\tPCMCIA RI resume from suspend\n");
+ }
+
+}
/*
* currently, it can turn off the display, but the display never comes
@@ -115,13 +252,41 @@ apm_display(int fd, int newstate)
}
+void
+apm_set_timer(int fd, int delta)
+{
+ time_t tmr;
+ struct tm *tm;
+ struct apm_bios_arg args;
+
+ tmr = time(NULL) + delta;
+ if (cmos_wall)
+ tm = localtime(&tmr);
+ else
+ tm = gmtime(&tmr);
+ bzero(&args, sizeof(args));
+ args.eax = (APM_BIOS) << 8 | APM_RESUMETIMER;
+ args.ebx = PMDV_APMBIOS;
+ if (delta > 0) {
+ args.ecx = (int2bcd(tm->tm_sec) << 8) | 0x02;
+ args.edx = (int2bcd(tm->tm_hour) << 8) | int2bcd(tm->tm_min);
+ args.esi = (int2bcd(tm->tm_mon + 1) << 8) | int2bcd(tm->tm_mday);
+ args.edi = int2bcd(tm->tm_year + 1900);
+ } else {
+ args.ecx = 0x0000;
+ }
+ if (ioctl(fd, APMIO_BIOS, &args)) {
+ err(1,"Set resume timer");
+ }
+}
+
int
main(int argc, char *argv[])
{
int c, fd;
int sleep = 0, all_info = 1, apm_status = 0, batt_status = 0;
- int display = 0, batt_life = 0, ac_status = 0;
- int batt_time = 0;
+ int display = 0, batt_life = 0, ac_status = 0, standby = 0;
+ int batt_time = 0, delta = 0;
char *cmdname;
@@ -135,7 +300,7 @@ main(int argc, char *argv[])
all_info = 0;
goto finish_option;
}
- while ((c = getopt(argc, argv, "ablstzd:")) != -1) {
+ while ((c = getopt(argc, argv, "ablRr:stzd:Z")) != -1) {
switch (c) {
case 'a':
ac_status = 1;
@@ -158,6 +323,12 @@ main(int argc, char *argv[])
batt_life = 1;
all_info = 0;
break;
+ case 'R':
+ delta = -1;
+ break;
+ case 'r':
+ delta = atoi(optarg);
+ break;
case 's':
apm_status = 1;
all_info = 0;
@@ -170,6 +341,10 @@ main(int argc, char *argv[])
sleep = 1;
all_info = 0;
break;
+ case 'Z':
+ standby = 1;
+ all_info = 0;
+ break;
case '?':
default:
usage();
@@ -183,14 +358,18 @@ finish_option:
warn("can't open %s", APMDEV);
return 1;
}
+ if (delta)
+ apm_set_timer(fd, delta);
if (sleep)
apm_suspend(fd);
- else {
+ else if (standby)
+ apm_standby(fd);
+ else if (delta == 0) {
struct apm_info info;
apm_getinfo(fd, &info);
if (all_info)
- print_all_info(&info);
+ print_all_info(fd, &info);
if (ac_status)
printf("%d\n", info.ai_acline);
if (batt_status)
OpenPOWER on IntegriCloud