/* * APM.C - Contains APM functions. * Copyright (C) 1998, 1999 Prashant TR * * Thanks to Ralf Brown. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * See the file COPYING.TR for more details. */ // ID for this file. #define _APM_CC_ #include "apm.h" int errflag = 0; FILE *fp; char cmdline[20]; #define DEVICES 8 typedef struct { long unsigned int id; char name[80]; } DEVICE; // Devices list. DEVICE device[DEVICES] = { { 0, "BIOS" }, { 1, "All devices" }, { 0x1ff, "Display" }, { 0x2ff, "HDD" }, { 0x3ff, "Parallel Port(s)" }, { 0x4ff, "Serial Port(s)" }, { 0x5ff, "Network adapter(s)" }, { 0x6ff, "PCMCIA socket(s)" }, }; // Write any string to the file and check for successfulness. void writestring(const char *string) { if (fprintf(fp, "%s", string) == EOF) { errflag = 2; checkerrors(); } } int sysinfo() { char output[256]; int major, minor, f; __dpmi_regs regs; // Create output file. if ((fp = fopen("apm.txt", "w")) == NULL) { errflag = 1; checkerrors(); } writestring("\nAPM :\n"); // APM installation check. regs.x.ax = 0x5300; regs.x.bx = 0; __dpmi_int(0x15, ®s); if ((regs.x.flags & 1) || (regs.x.bx != 0x504d)) { writestring("\tAPM not Installed.\n"); fclose(fp); return 0; } // Here we come if we have APM. major = regs.h.ah; minor = regs.h.al; sprintf(output, "\tPower Management Version : %x.%x\n", major, minor); writestring(output); // Connect the interface. // First disconnect. regs.x.ax = 0x5304; regs.x.bx = 0; __dpmi_int(0x15, ®s); // Connect real mode interface. // This is present on all APMs. regs.x.ax = 0x5301; regs.x.bx = 0; __dpmi_int(0x15, ®s); if (regs.x.flags & 1) fprintf(stderr, "Error: Could not connect interface\r\n"); sprintf(output, "\t16-bit Protected Mode Interface supported : %s\n", (regs.x.cx & 1) ? "Yes" : "No"); writestring(output); sprintf(output, "\t32-bit Protected Mode Interface supported : %s\n", (regs.x.cx & 2) ? "Yes" : "No"); writestring(output); sprintf(output, "\tCPU Idle call reduces processor speed : %s\n", (regs.x.cx & 4) ? "Yes" : "No"); writestring(output); sprintf(output, "\tAPM Enabled by BIOS : %s\n", (regs.x.cx & 8) ? "No" : "Yes"); writestring(output); // For APM v1.1 only. if ((major) && (minor)) { sprintf(output, "\tBIOS APM engaged : %s\n", (regs.x.cx & 16) ? "No" : "Yes"); writestring(output); // Check OEM APM. regs.x.ax = 0x5380; regs.h.bh = 0x7f; __dpmi_int(0x15, ®s); if (regs.x.flags & 1) writestring("\tOEM APM installed : No\n"); else writestring("\tOEM APM installed : Yes\n"); } // Check power status. regs.x.ax = 0x530a; regs.x.bx = 1; __dpmi_int(0x15, ®s); if (regs.x.flags & 1) fprintf(stderr, "Error: AC line status check failed\r\n"); else { // AC status. sprintf(output, "\tAC Status : %s\n", (!regs.h.bh) ? "Off-line" : (regs.h.bh == 1) ? "On-line" : (regs.h.bh == 2) ? "On Backup Power" : (regs.h.bh == 0xff) ? "Unknown" : "Unknown - (Reserved)"); writestring(output); // Battery information (APM v1.1 only). if ((major) && (minor)) { // Check if battery is installed. sprintf(output, "\tAPM Battery unit(s) installed : %s\n", (regs.h.ch == 0xff) ? "Unknown" : (regs.h.ch & 0x80) ? "No " : "Yes"); writestring(output); if (!(regs.h.ch & 0x80)) { sprintf(output, "\tAPM Battery status : %s\n", (regs.h.ch & 1) ? "High" : (regs.h.ch & 2) ? "Low" : (regs.h.ch & 4) ? "Critical" : (regs.h.ch & 8) ? "Charging" : "Unknown"); writestring(output); } else regs.x.dx = 0; // No battery time left. sprintf(output, "\tBattery life remaining : " "%d %s\n", regs.x.dx & 0x7fff, (regs.x.dx & 0x8000) ? "minutes" : "seconds"); writestring(output); } else { sprintf(output, "\tAPM Battery status : %s\n", (regs.h.bl & 1) ? "High" : (regs.h.bl & 2) ? "Low" : (regs.h.bl & 4) ? "Critical" : (regs.h.bl & 8) ? "Charging" : "Unknown"); writestring(output); } // Battery life percentage remaining. if (regs.h.cl == 0xff) { sprintf(output, "\tPercentage of Battery left : " "Unknown\n"); writestring(output); } else { sprintf(output, "\tPercentage of Battery left : " "%d\n", regs.h.cl); writestring(output); } // Get device APM support. for(f = 2; f < DEVICES; f++) { regs.x.ax = 0x5307; regs.x.bx = device[f].id; regs.x.cx = 0; __dpmi_int(0x15, ®s); switch(f) { case 2: strcpy(output, "\tDisplay Power off " " : "); break; case 3: strcpy(output, "\tHDD Power Down " " : "); break; case 4: strcpy(output, "\tDevice APM for Parallel " "Port(s) : "); break; case 5: strcpy(output, "\tDevice APM for Serial Po" "rt(s) : "); break; case 6: strcpy(output, "\tDevice APM for Network a" "dapter(s) : "); break; case 7: strcpy(output, "\tDevice APM for PCMICIA s" "ocket(s) : "); break; default: strcpy(output, "\tDevice APM - Unknown dev" "ice : "); break; } strcat(output, (regs.x.flags & 1) ? "Not supported\n" : "Supported\n"); writestring(output); } // For APM v1.1 only. if ((major) && (minor)) { regs.x.ax = 0x530e; regs.x.bx = 0; regs.h.ch = major; regs.h.cl = minor; __dpmi_int(0x15, ®s); if (regs.x.flags & 1) { sprintf(output, "\tAPM Interface connection version : " "Unknown\n"); writestring(output); } else { sprintf(output, "\tAPM Interface connection version : " "%X.%X\n", regs.h.ah, regs.h.al); writestring(output); } } // Standby and suspend functions. regs.x.ax = 0x5310; regs.x.bx = 0; __dpmi_int(0x15, ®s); if (!(regs.x.flags & 1)) { // APM syspend and standby. sprintf(output, "\tSystem Standby : %s\n", (regs.h.cl & 1) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tSystem Suspend : %s\n", (regs.h.cl & 2) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up Timer Standby : %s\n", (regs.h.cl & 4) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up Timer Suspend : %s\n", (regs.h.cl & 8) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up COM-Ring Standby : %s\n", (regs.h.cl & 16) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up COM-Ring Suspend : %s\n", (regs.h.cl & 32) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up PCMCIA-Ring Standby : %s\n", (regs.h.cl & 64) ? "Supported" : "Not Supported"); writestring(output); sprintf(output, "\tWake-up PCMCIA-Ring Suspend : %s\n", (regs.h.cl & 128) ? "Supported" : "Not Supported"); writestring(output); } } fclose(fp); return 0; } int apm_version() { int major, minor; __dpmi_regs regs; // Create output file. if ((fp = fopen("temp.$$$", "w")) == NULL) { errflag = 1; checkerrors(); } // APM installation check. regs.x.ax = 0x5300; regs.x.bx = 0; __dpmi_int(0x15, ®s); if ((regs.x.flags & 1) || (regs.x.bx != 0x504d)) { fprintf(fp, "%c%c", 0, 0); fclose(fp); return 0; } // Here we come if we have APM. major = regs.h.ah; minor = regs.h.al; // Write out the information. fprintf(fp, "%c%c", major, minor); fclose(fp); return 0; } void open_stderr() { fclose(&__dj_stdout); fclose(&__dj_stderr); if (fopen("nul", "wb") == NULL) exit(0x7f); if (fopen("nul", "wb") == NULL) exit(0x7f); if ((stderr = fopen("errors.$$$", "ab")) == NULL) exit(0x7f); } void get_cmdline() { if ((fp = fopen("cmdline.$$$", "rb")) == NULL) exit (0x7f); if (fscanf(fp, "%s", cmdline) != 1) { fclose(fp); exit (0x7f); } fclose(fp); unlink("cmdline.$$$"); } // The main function. int main() { open_stderr(); get_cmdline(); if (!strcmp(cmdline, "sysinfo")) return(sysinfo()); if (!strcmp(cmdline, "apm_version")) return(apm_version()); return 0; }