Logo Search packages:      
Sourcecode: acpitool version File versions  Download package

acpitool.cpp

/*---------------------------------------------------------------------------*/
/* Program to get/set some ACPI settings                                     */
/* Author : David Leemans   -   http://freeunix.dyndns.org:8000/             */
/* Last update : 27-11-2005                                                  */
/*---------------------------------------------------------------------------*/
/*                                                                           */
/* acpitool.cpp                                                              */
/*                                                                           */
/* Copyright (C) 2004  David Leemans <davidleemans AT tiscali DOT be>        */
/*                                                                           */
/* 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.                                       */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
/* GNU General Public License for more details.                              */
/*                                                                           */
/* You should have received a copy of the GNU General Public License         */
/* along with this program; if not, write to the Free Software               */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
/*---------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <iomanip>
#include <fstream>
#include <dirent.h>
#include "acpitool.h"
#include "thinkpad.h"
#include "toshiba.h"

using namespace std;

#define App_Version  "AcpiTool v0.4.0"
#define Release_Date "27-Nov-2005"

int Kernel_24 = 0, Kernel_26 = 0;

/*----------------------------------------------------------------------------------------------------------------------------*/

int Has_ACPI()
{
    ifstream file_in;
    char *filename;
    
    filename = "/proc/acpi/info";
    
    file_in.open(filename);
    if (!file_in)
      return 0;
    else
    {
      file_in.close();
        return 1;
    }
}
    
int Print_ACPI_Info(int show_ac, int show_therm, int show_trip, int show_fan, int show_batteries, int show_empty, int show_version, int show_cpu, int show_wake, int e_set, int info_level, int verbose)
{
    if(show_version)
      Do_SysVersion_Info(verbose);
    if(show_batteries)
      Do_Battery_Stuff(show_empty, info_level, verbose);
    if(e_set) cout<<endl;     
    if(show_ac)
      Do_AC_Info(verbose);
    if(show_fan)
      Do_Fan_Info(verbose);
    if(e_set) cout<<endl;
    if(show_cpu)
      Show_CPU_Info();
    if(e_set) cout<<endl;
    if(show_therm)
      Do_Thermal_Info(show_trip, verbose);
    if(e_set) cout<<endl;
    if(show_wake)
      Show_WakeUp_Devices(verbose); 
    return 0;
}

// remaining battery capacity (in %) = (remaining capacity / last full battery capacity) x 100 //
// remaining battery life (in hh:mm:ss) = (remaining capacity / present battery rate ) //
   
int Do_Battery_Stuff(int show_empty, int info_level, int verbose)
{
    Battery_Info *Batt_Info;
    int Bat_Nr;
    float Remaining_Percentage, Remaining_Time, Battery_Left_Percent;
    int Time_In_Seconds = 0;
    int Hours = 0;
    int Minutes = 0;
    int Show_Time = 0;
    int Precision = 0;
    int Is_Charging = 0;
    
    int Nr_Batteries = Count_Batteries();
    
    if(Nr_Batteries>0)
    {
        Batt_Info = new Battery_Info;
            
        for(int i=0; i<Nr_Batteries; i++)
      {
          Bat_Nr = i+1;
                  
          Batt_Info->Battery_Present = 0;
          bzero(Batt_Info->Remaining_Cap, 10);
          bzero(Batt_Info->Design_Cap, 10);
          bzero(Batt_Info->LastFull_Cap, 10);
          bzero(Batt_Info->Present_Rate, 10);
          bzero(Batt_Info->Charging_State, 12);
          bzero(Batt_Info->Technology, 13);
          bzero(Batt_Info->Model, 13);
          bzero(Batt_Info->Serial, 13);
          bzero(Batt_Info->Bat_Type, 13); 
          // initialize all struct members to blanks --> avoid rubbish in output //
                  
          Get_Battery_Info(Bat_Nr, Batt_Info, verbose);
          Show_Time = atoi(Batt_Info->Present_Rate);   
          // avoid division by 0 if system is on AC power and battery is full and thus not charging //

          Is_Charging = 0;  // determine whether battery is charging or not //
          
          switch(Batt_Info->Battery_Present)
          {
            case 1 : 
            {     
                Remaining_Percentage = float(atoi(Batt_Info->Remaining_Cap)) / float(atoi(Batt_Info->LastFull_Cap)) * 100.0;
                
                /* from Alan Pope : some broken Dell batteries report a remaining capacity bigger
                   than their last full capacity or their design capacity. This led acpitool to report
                   stuff like 107% battery percentage. To avoid this silliness, I added next if statement */  
                  
                if( Remaining_Percentage > 100.0)
                  Remaining_Percentage = 100.0;
                                  
                if( int(Remaining_Percentage) < 10)
                        Precision = 3;
                      else
                        Precision = 4;
                      
                if(strncmp(Batt_Info->Charging_State,"char",4)==0) Is_Charging = 1;
                            
                if(Show_Time)      // calculate remaining or charging time only if present battery rate != 0 //
                {
                  if(Is_Charging)
                    Remaining_Time = (float(atoi(Batt_Info->LastFull_Cap)) - float(atoi(Batt_Info->Remaining_Cap))) / float(atoi(Batt_Info->Present_Rate)); 
                  else
                    Remaining_Time = float(atoi(Batt_Info->Remaining_Cap)) / float(atoi(Batt_Info->Present_Rate)); 
                  // this represents hours //
            
                  Time_In_Seconds = int(Remaining_Time * 3600.0);
                  Hours = Time_In_Seconds / 3600;
                  Time_In_Seconds = Time_In_Seconds - (Hours * 3600);
                  Minutes = Time_In_Seconds / 60;
                  Time_In_Seconds = Time_In_Seconds - (Minutes * 60);
                }
                
                if(atoi(Batt_Info->Design_Cap) > 0)
                  Battery_Left_Percent = float(atoi(Batt_Info->LastFull_Cap)) / float(atoi(Batt_Info->Design_Cap)) * 100.0;
                else
                  Battery_Left_Percent = -1.0;
                                      
          
                switch(info_level)
                {
                  case 0 : cout.precision(Precision);
                           cout<<"  Battery #"<<Bat_Nr<<"     : "<<Batt_Info->Charging_State<<", "<<showpoint<<Remaining_Percentage<<"%";
                           if(Show_Time)
                            cout<<", "<<setfill('0')<<setw(2)<<Hours<<":"<<setfill('0')<<setw(2)<<Minutes<<":"\
                            <<setfill('0')<<setw(2)<<Time_In_Seconds;
                           cout<<endl; 
                           break;
                         
                  case 1 : cout<<"  Battery #"<<Bat_Nr<<"     : present"<<endl;
                           cout<<"    Remaining capacity : "<<Batt_Info->Remaining_Cap<<", ";
                           cout.precision(Precision);
                           cout<<showpoint<<Remaining_Percentage<<"%";
                         
                         if(Show_Time)
                            cout<<", "<<setfill('0')<<setw(2)<<Hours<<":"<<setfill('0')<<setw(2)<<Minutes<<":"\
                            <<setfill('0')<<setw(2)<<Time_In_Seconds;
                         cout<<endl;
                         
                         cout<<"    Design capacity    : "<<Batt_Info->Design_Cap<<endl;
                         cout<<"    Last full capacity : "<<Batt_Info->LastFull_Cap;
                         
                         if(Battery_Left_Percent<100.0)
                         {
                            cout<<", "<<Battery_Left_Percent<<"% of design capacity"<<endl;
                            cout<<"    Capacity loss      : "<<(100.0 - Battery_Left_Percent)<<"%"<<endl;
                         }    
                         else
                           cout<<endl;
                         
                         cout<<"    Present rate       : "<<Batt_Info->Present_Rate<<endl;
                           cout<<"    Charging state     : "<<Batt_Info->Charging_State<<endl;
                           cout<<"    Battery type       : "<<Batt_Info->Technology<<", "<<Batt_Info->Bat_Type<<endl;
                         
                         if (strlen(Batt_Info->Model)!=0)
                              cout<<"    Model number       : "<<Batt_Info->Model<<endl;
                           if (strlen(Batt_Info->Serial)!=0)
                            cout<<"    Serial number      : "<<Batt_Info->Serial<<endl;
                         /* on some batteries, these values are empty */     
                            
                           break;
                         
                  default : cout<<"  Undefined info level, fix this. Info level : "<<info_level<<endl;
                            break;
                }
                break;  
            }
          case 0 : if(show_empty) cout<<"  Battery #"<<Bat_Nr<<"     : slot empty"<<endl;
                 break;
          case 2 : cout<<"  Battery         : <not available>"<<endl;
                 break;
          case 3 : cout<<"  Battery         : <not available>"<<endl;
                 break;
          default : cout<<"  Undefined present value, fix this. Value : "<<Batt_Info->Battery_Present<<endl;
                    break;
          }    
      
      }
      delete Batt_Info;
    }
    else
    {
      if(Nr_Batteries==0)   //this would apply to a regular desktop with acpi support //
      {
          cout<<"  Battery status : <not available>"<<endl;
          return 0;
      }
      if(Nr_Batteries<0)
      {
          if(!verbose)
          {
            cout<<"  Battery status : <error reading info>"<<endl;
            return 0;
          }
          else
          {
            cout<<"  Battery status : <error reading info>"<<endl;
            cout<<"  Function Count_Batteries returned : "<<Nr_Batteries<<endl;
            return -1;
          }
      }
    }
    return 0;
}


int Get_ACPI_Version(char *c, int verbose)
{
    ifstream file_in;
    char *filename, str[50];
    
    filename = "/proc/acpi/info";
    
    file_in.open(filename);
    if (!file_in)
    {
      if(!verbose)
      {
          strcpy(c, "<n.a>");
          return 0;
      }
      else
      {
          cout<<"  Could not open file : "<<filename<<endl;
          cout<<"  Make sure your kernel has ACPI support enabled."<<endl;
          return -1;
      }     
    }
       
    file_in.getline(str, 50);
    file_in.close();
    
    /* version takes 8 chars starting from pos 26 */
    strncpy(c, str+25,8);
    
    return 0;
}


int Get_Kernel_Version(char *c, int verbose)
{
    ifstream file_in;
    char *filename, str[20];
    
    filename = "/proc/sys/kernel/osrelease";
    
    file_in.open(filename);
    if (!file_in)
    {
      if(!verbose)
      {
          strcpy(c, "<n.a>");
          return 0;
      }
      else
      {
          cout<<"  Could not open file : "<<filename<<endl;
          return -1;
      }     
    }
       
    file_in.getline(str, 16);
    file_in.close();
    
    strcpy(c, str);
    
    return 0;
}


int Do_SysVersion_Info(int verbose)
{
    char Acpi_Version[10], Kernel_Version[15];
 
    bzero(Acpi_Version, 10); 
    bzero(Kernel_Version, 15);   

    Get_Kernel_Version(Kernel_Version, verbose);
    Get_ACPI_Version(Acpi_Version, verbose);

    cout<<"  Kernel version : "<<Kernel_Version<<"   -    ACPI version : "<<Acpi_Version<<endl;
    cout<<"  -----------------------------------------------------------"<<endl;
    
    return 0;
}  


int Set_Kernel_Version()
{
    ifstream file_in;
    char *filename, str[10];
    
    filename = "/proc/sys/kernel/osrelease";
    
    file_in.open(filename);
    if (!file_in)
    {
      cout<<"  Could not open file : "<<filename<<endl;
      cout<<"  function Set_Kernel_Version() : can't set kernel version, bailing out"<<endl;
      return -1;
    } 
       
    file_in.getline(str, 9);
    file_in.close();
    
    if(strncmp(str,"2.4",3)==0)
    {
      Kernel_24 = 1;           
      Kernel_26 = 0;
    }
        
    if(strncmp(str,"2.6",3)==0)
    {
      Kernel_24 = 0;           
      Kernel_26 = 1;
    }    
    
    return 0;
}


int Do_Thermal_Info(const int show_trip, int verbose)
{
    ifstream file_in, file_in2;
    char *dirname, filename[9][65], str[90];
    int tz_count = 0;
    DIR *thermal_dir;
    char *name;
    char Temperature[5], State[5];
 
    bzero(Temperature, 5);     
    bzero(State, 5);
    
    dirname = "/proc/acpi/thermal_zone/";   
    thermal_dir = opendir(dirname);
    if(thermal_dir)                    
    {
      struct dirent **namelist;
      int n;

      n = scandir(dirname, &namelist, 0, alphasort);
      if(n<0)
          perror("scandir");
      else
      {
          while(n--)
          {
            name = namelist[n]->d_name;
            // skip . and .. //
            if (!strncmp (".", name, 1) || !strncmp ("..", name, 2)) continue;
                        
            sprintf(filename[tz_count], "/proc/acpi/thermal_zone/%s/state", name);
                  tz_count++;
                  sprintf(filename[tz_count], "/proc/acpi/thermal_zone/%s/temperature", name);
            tz_count++;
            sprintf(filename[tz_count], "/proc/acpi/thermal_zone/%s/trip_points", name);
            tz_count++;
            free(namelist[n]);
          }
          free(namelist);
      }
    }       
    else        
    {
            if(!verbose)    
      {
          cout<<"  Thermal info   : <not available>"<<endl;
                return 0;
      }
      else            
      {
          cout<<"  Could not open directory : "<<dirname<<endl;
          cout<<"  function Do_Thermal_Info() : make sure your kernel has /proc/acpi/thermal_zone support enabled."<<endl;
          return -1;
      }     
    }
    closedir(thermal_dir);  
    
    if(tz_count>0)     
    {
      
      tz_count--;
      int tz=0;   
      
      for(int i=tz_count; i>0; i-=3)     //process entries in reverse order //
      {
          file_in.open(filename[i-2]);
          if(file_in)                   
          {
            file_in.getline(str, 90);
            strncpy(State, str+25, 5);
            cout<<"  Thermal zone "<<++tz<<" : "<<State<<", ";
          }
          file_in.close();
          file_in2.open(filename[i-1]);
          if(file_in2)                   
          {
            file_in2.getline(str, 90);
            strncpy(Temperature, str+25, 5);
            cout<<Temperature<<endl;
          }
          file_in2.close();
          if(show_trip)           // show trip_points ? //
          {
            FILE *fp = fopen(filename[i], "r");           
            
            /* using classic FILE and fopen here because ifstream.open fails mysteriously when asigned to multiple files ???? */
            
            if(fp)
            {
                cout<<"  Trip points : "<<endl;
                cout<<"  ------------- "<<endl;
                while(!feof(fp))
                {
                  /* fscanf(fp, "%s", str); */
                  bzero(str, 90);
                  fgets(str, 90, fp);
                  if (strlen(str)!=0)  
                    cout<<"  "<<str;       /* avoid printing empty line */
                }
                cout<<endl;   
            }
            else
               cout<<"  Trip points : <error opening file>"<<endl;
            fclose(fp);     
          }
      }
    }
    else   
      cout<<"  Thermal info   : <not available>"<<endl;
    return 0;
}


int Do_AC_Info(int verbose)
{
    ifstream file_in;
    char *dirname, filename[4][50], str[40];
    int ac_count = 0;
    DIR *ac_dir;
    struct dirent *ac_dirent;
    char *name;
    char AC_Status[9];
 
    bzero(AC_Status, 9);         // avoid rubbish in output //
      
    dirname = "/proc/acpi/ac_adapter/";    
    ac_dir = opendir(dirname);
    if(ac_dir)                             
    {
      while((ac_dirent = readdir(ac_dir)))   
      {
          name = ac_dirent->d_name;
                // skip . and .. // 
          if (!strncmp (".", name, 1) || !strncmp ("..", name, 2)) continue;
                sprintf(filename[ac_count], "/proc/acpi/ac_adapter/%s/state", name);
                ac_count++;
            }
    }
    else        
    {
            if(!verbose)   
      {
          cout<<"  AC adapter     : <not available>"<<endl;
                return 0;
      }
      else              
      {
          cout<<"  Could not open directory : "<<dirname<<endl;
          cout<<"  function Do_AC_Info() : make sure your kernel has ACPI ac_adapter support enabled."<<endl;
          return -1;
      }     
    }
    closedir(ac_dir);  
    
    if(ac_count>0)
    {
      for(int i=0; i<ac_count; i++)
      {
          file_in.open(filename[i]);
          if(file_in)                   
          {
            file_in.getline(str, 40);
            strncpy(AC_Status, str+25, 8);
            file_in.close();
            cout<<"  AC adapter     : "<<AC_Status<<endl;
          }
      }
    }
    else
      cout<<"  AC adapter     : <not available>"<<endl;
    return 0;
}



int Do_Fan_Info(int verbose)
{
    ifstream file_in;
    char *dirname, filename[4][50], str[40];
    int fan_count = 0;
    DIR *fan_dir;
    struct dirent *fan_dirent;
    char *name;
    char FAN_Status[9];
 
    if (Has_Thinkpad_ACPI())
    {
      Do_Thinkpad_Fan_Info();
      return 0;
    }
    
    if (Has_Toshiba_ACPI())
    {
      Do_Toshiba_Fan_Info();
      return 0;
    }

    bzero(FAN_Status, 9);         // avoid rubbish in output //
      
    dirname = "/proc/acpi/fan/";    
    fan_dir = opendir(dirname);
    if(fan_dir)                             
    {
      while((fan_dirent = readdir(fan_dir)))   
      {
          name = fan_dirent->d_name;
                // skip . and .. // 
          if (!strncmp (".", name, 1) || !strncmp ("..", name, 2)) continue;
                sprintf(filename[fan_count], "/proc/acpi/fan/%s/state", name);
                fan_count++;
            }
    }
    else        
    {
            if(!verbose)   
      {
          cout<<"  Fan            : <not available>"<<endl;
                return 0;
      }
      else              
      {
          cout<<"  Could not open directory : "<<dirname<<endl;
          cout<<"  function Do_Fan_Info() : make sure your kernel has ACPI fan support enabled."<<endl;
          return -1;
      }     
    }
    closedir(fan_dir);  
    
    if(fan_count>0)
    {
      for(int i=0; i<fan_count; i++)
      {
          file_in.open(filename[i]);
          if(file_in)                   
          {
            file_in.getline(str, 40);
            strncpy(FAN_Status, str+25, 8);
            file_in.close();
            cout<<"  Fan            : "<<FAN_Status<<endl;
          }
      }
    }
    else
      cout<<"  Fan            : <not available>"<<endl;
    return 0;
}


int Show_CPU_Info()
{
    ifstream file_in, file2_in;
    char *dirname, filename[12][70], str[200], temp[80];
    int cpu_count = 0, findex = 0, thrott = 0;
    DIR *cpu_dir;
    char *name;
    
    file_in.open("/proc/cpuinfo");
    if(file_in)                   
    {
        for(int t=0; t<4; t++) file_in.getline(str, 80);          //skip 4 lines //
      file_in.getline(str, 100);
      bzero(temp, 80);
      strncpy(temp, str+13, 49);
      cout<<"  CPU type               : "<<temp<<endl;
      file_in.getline(str, 100);
      file_in.getline(str, 100);
      bzero(temp, 80);
      strncpy(temp, str+11, 10);
      cout<<"  CPU speed              : "<<temp<<" MHz"<<endl;
      for(int t=0; t<11; t++) file_in.getline(str,199);        //skip 10 lines //
      bzero(temp, 80);
      strncpy(temp, str+11, 10);
      cout<<"  Bogomips               : "<<temp<<endl;
      file_in.close();
    }
    else
    {
      cout<<"  Error : Could not open file /proc/cpuinfo."<<endl;
      return -1;
    } 
       
    dirname = "/proc/acpi/processor/";    //find all entries in this dir //
    cpu_dir = opendir(dirname);
    if(cpu_dir)                     // we can read this dir //
    {
      struct dirent **namelist;
      int n;

      n = scandir(dirname, &namelist, 0, alphasort);
      if(n<0)
          perror("scandir");
      else
      {
          while(n--)
          {
            name = namelist[n]->d_name;
            // skip . and .. //
            if (!strncmp (".", name, 1) || !strncmp ("..", name, 2)) continue;
            
            sprintf(filename[findex], "/proc/acpi/processor/%s/info", name);
            findex++;
            sprintf(filename[findex], "/proc/acpi/processor/%s/power", name);
            findex++;
            sprintf(filename[findex], "/proc/acpi/processor/%s/throttling", name);
            findex++;
            cpu_count++;
                        
            free(namelist[n]);
          }
          free(namelist);
      }
    }       
    else
    {
      cout<<"  Function Show_CPU_Info : could not read directory "<<dirname<<endl;
      cout<<"  Make sure your kernel has ACPI processor support enabled."<<endl;
      return -1;
    }
    closedir(cpu_dir);  

    if(cpu_count>0)     
    {
      findex--;
      
      if(cpu_count>1) cout<<endl<<"# of CPU's found       : "<<cpu_count<<endl<<endl;
      
      for(int i=findex; i>0; i-=3)     //process entries in reverse order //
      {
          file_in.open(filename[i-2]);
          if(file_in)                   
          {
              file_in.getline(str, 90);
            bzero(temp, 80);
              strncpy(temp, str+25, 5);
            cout<<"  Processor ID           : "<<temp<<endl;
            
            file_in.getline(str, 100);
            file_in.getline(str, 100);
            bzero(temp, 80);
              strncpy(temp, str+25, 5);
            cout<<"  Bus mastering control  : "<<temp<<endl;
            
            file_in.getline(str, 100);
            bzero(temp, 80);
              strncpy(temp, str+25, 5);
            cout<<"  Power management       : "<<temp<<endl;
            
            file_in.getline(str, 100);
            bzero(temp, 80);
              strncpy(temp, str+25, 5);
            cout<<"  Throttling control     : "<<temp<<endl;
            if(strncmp(temp,"yes",3)==0)
                thrott = 1;               //yes, this CPU reports it can do power throttling //
            
            file_in.getline(str, 100);
            bzero(temp, 80);
              strncpy(temp, str+25, 5);
            cout<<"  Limit interface        : "<<temp<<endl;

            file_in.close();
          }
          else
          {
            cout<<"  could not open file "<<filename[i-2]<<endl;
          } 
                
          file2_in.open(filename[i-1]);
          if(file2_in)                   
          {
            file2_in.getline(str, 100);
            bzero(temp, 80);
            strncpy(temp, str+25, 5);
            cout<<"  Active C-state         : "<<temp<<endl;
            file2_in.close();
          }
          else
          {
            cout<<"  could not open file "<<filename[i-1]<<endl;
          }
          
          
          if(thrott)
          {
            file_in.open(filename[i]);
            if(file_in)                   
            {
                file_in.getline(str, 100);
                bzero(temp, 80);
                strncpy(temp, str+25, 5);
                cout<<"  T-state count          : "<<temp<<endl;       // number of throttling states //
                file_in.getline(str, 100);
                bzero(temp, 80);
                strncpy(temp, str+25, 5);
                cout<<"  Active T-state         : "<<temp<<endl;
                file2_in.close();
            }
            else cout<<" could not open file "<<filename[i]<<endl;
          }
          
          if(cpu_count>1) cout<<endl;
      }
    }
    else   
      cout<<"  CPU info       : <not available>"<<endl;
    return 0;
}


int Show_WakeUp_Devices(int verbose)
{
    ifstream file_in;
    char *filename, str[40];
    
    filename = "/proc/acpi/wakeup";
    
    file_in.open(filename);
    if (!file_in)        
    {
      if(!verbose)        
      {
          cout<<"  wakeup devices : <not available>"<<endl;
          return 0;
      }
      else              
      {
          cout<<"  Function Show_WakeUp_Devices : could not open file "<<filename<<endl;
          cout<<"  Make sure your kernel has /proc/acpi/wakeup support enabled."<<endl;
          return -1;
      }     
    }
    else
    {
      file_in.getline(str, 40);           // first line are just headers //
      cout<<"   "<<str<<endl;
      cout<<"  ---------------------------------------"<<endl;
        int t = 1;
      while(!file_in.eof())
      {
          file_in.getline(str, 40);
          if (strlen(str)!=0)                     // avoid printing last empty line //
          {
            cout<<"  "<<t<<". "<<str<<endl;
            t++;
          }
      }     
      file_in.close();
    }
    
    return 0;
}


int Toggle_WakeUp_Device(const int Device, int verbose)
{
    ifstream file_in;
    ofstream file_out;
    char *filename, str[50];
    int index = 1;
    char Name[25][5];            // 25 should be enough I guess, I have only 9 so far //
    
    filename = "/proc/acpi/wakeup";
    
    file_in.open(filename);
    if (!file_in)        
    {
      if(!verbose)        
      {
          cout<<"  wakeup devices : <not available>"<<endl;
          return 0;
      }
      else              
      {
          cout<<"  Function Toggle_WakeUp_Device : could not open file "<<filename<<endl;
          cout<<"  Make sure your kernel has /proc/acpi/wakeup support enabled."<<endl;
          return -1;
      }     
    }
    
    file_in.getline(str, 50);             // first line are just headers //
    while(!file_in.eof())                 // count all devices and store their names//
    {
        file_in.getline(str, 50);
        if(strlen(str)!=0)                // avoid empty last line //
        {
          bzero(Name[index], 5);
          strncpy(Name[index], str, 4);
          index++;
      }
    } 
    file_in.close();
      
    index--;                                      // last device = index - 1 //
      
    if( (Device>=1) && (Device<=index) )          // check this first !! //
    {
        file_out.open(filename);
        if (!file_out)
        {
          cout<<"  Function Toggle_WakeUp_Device : could not open file : "<<filename<<". \n"
          "  You must have write access to "<<filename<<" to enable or disable a wakeup device. \n"
          "  Check the permissions on "<<filename<<" or run acpitool as root."<<endl;
          return -1;
      }
      else file_out<<Name[Device];     // change status //
      cout<<"  Changed status for wakeup device #"<<Device<<" ("<<Name[Device]<<")"<<endl<<endl;
      file_out.close();
    }
    else
    {
        cout<<" Function Toggle_Wakeup_Device : invalid device number "<<Device<<". \n"
            " Run 'acpitool -w' to get valid device numbers ."<<endl;
      return -1;
    }
    
    return 0;
}



int Get_Battery_Info(const int bat_nr, Battery_Info *bat_info, int verbose)
{
    ifstream file_in;
    char *dirname, filename[4][60], str[100], temp[5];
    int bat_count = 0, start = 0, findex = 0;
    DIR *battery_dir;
    char *name;
       
    dirname = "/proc/acpi/battery/";    //find all entries in this dir //
    battery_dir = opendir(dirname);
    if(battery_dir)                     // we can read this dir //
    {
      struct dirent **namelist;
      int n;

      n = scandir(dirname, &namelist, 0, alphasort);
      if(n<0)
          perror("scandir");
      else
      {
          while(n--)
          {
            name = namelist[n]->d_name;
            // skip . and .. //
            if (!strncmp (".", name, 1) || !strncmp ("..", name, 2)) continue;
            
            sprintf(filename[findex], "/proc/acpi/battery/%s/info", name);
            findex++;
            sprintf(filename[findex], "/proc/acpi/battery/%s/state", name);
            findex++;
            bat_count++;
                        
            free(namelist[n]);
          }
          free(namelist);
      }
    }       
    else
    {
      if(!verbose)
      {
          bat_info->Battery_Present = 2;     // 2 represents error value //
          return 0;
      }
      else
      {
          cout<<" Function Get_Battery_Info : Could not read directory : /proc/acpi/battery/"<<endl;
          cout<<" Make sure your kernel has ACPI battery support enabled."<<endl;
          return -1;
      }
    }
    closedir(battery_dir);  
    
    //we found all dir entries, now process them //
    switch(bat_nr)       // select battery first //
    {
      case 1 : if(bat_count==1)
                start = 0;
             if(bat_count==2)
                start = 2;    
             break;
      case 2 : start = 0;
             break;      
      default : cout<<"Invalid battery number, fix this"<<endl;
              return -1;
              break;
    } //NOTE : scandir returns entries in reverse order //
  
    // first get battery presence from 1st file//
            
    
    if(bat_count>0)
    {
      file_in.open(filename[start]);
      
      if (!file_in)
      {
          cout<<" Function Get_Battery_Info : could not open file "<<filename[start]<<endl;
          cout<<" Make sure your kernel has ACPI battery support enabled or check presence of a battery."<<endl;
          return -1;
      }
      
      file_in.getline(str, 100);
      strncpy(temp, str+25, 4);
      if(strncmp(temp,"yes",3)==0)
          bat_info->Battery_Present = 1;               //yes, we have a battery //
      else
      {
          bat_info->Battery_Present = 0;
          return 0;                  //bail out if battery is not present //
      }
      
      // then get the design capacity //
      file_in.getline(str, 100);
      strncpy(bat_info->Design_Cap, str+25, 9);
      
      // then get the last full capacity //
      file_in.getline(str, 100);
      strncpy(bat_info->LastFull_Cap, str+25, 9);
      
      if (strncmp(bat_info->LastFull_Cap,"unknown",7)==0)
      {
          bat_info->Battery_Present = 0;
          return 0;                  //bail out if battery is not present //
      }
      /* some Dell laptops seem to report a 2nd battery as being present, while it is NOT, but then report the 
         last full capacity and other values as "unknown". This sucks, Mr Dell ! If the last full capacity
         is unknown, the battery is considered as being unavailable. */  
      
    
      // then get the technology //
      file_in.getline(str, 100);
      strncpy(bat_info->Technology, str+25, 12);
    
      // then get the model number //
      for(int t=0; t<5; t++)
      file_in.getline(str, 100);            //skip 5 lines //
      file_in.getline(str, 100);
      strncpy(bat_info->Model, str+25, 12);
    
      // then get the serial number //
      file_in.getline(str, 100);
      strncpy(bat_info->Serial, str+25, 12);
    
      // then get the battery type //
      file_in.getline(str, 100);
      strncpy(bat_info->Bat_Type, str+25, 12);
    
      file_in.close();
      
      // then open 2nd file = /proc/acpi/.../state //

      file_in.open(filename[start+1]);
      if (!file_in)
      {
          cout<<" Function Get_Battery_Info : could not open file "<<filename[start+1]<<endl;
          cout<<" Make sure your kernel has ACPI battery support enabled or check presence of a battery."<<endl;
          return -1;
      }
      
      // then get the charging state //
      file_in.getline(str, 100); file_in.getline(str, 100);     // skip first 2 lines //
      file_in.getline(str, 100);
      strncpy(bat_info->Charging_State, str+25, 12);
      if (strncmp(bat_info->Charging_State,"unknown",7)==0) strncpy(bat_info->Charging_State, "charged",7);
      /* on older kernels, like 2.4.22, the charging state is reported as "unknown", whereas in recent kernels
         this was changed to "charged". */  

      // then get the charging rate //
      file_in.getline(str, 100);
      strncpy(bat_info->Present_Rate, str+25, 9);
      if (strncmp(bat_info->Charging_State,"charged",7)==0)
      {
          if (strncmp(bat_info->Present_Rate, "unknown",7)==0) strncpy(bat_info->Present_Rate, "0      ",7);
      }    
      /* some batteries report the present rate as "unknown", even when they report the battery as being charged.
         If the battery is charged, the rate should be 0 */     
        

      // then get the remaining capacity //
      file_in.getline(str, 100);
      strncpy(bat_info->Remaining_Cap, str+25, 9);
    
      file_in.close();
      }
      else      // battery dir is readable but empty : only . and .. at most //
          bat_info->Battery_Present = 3;   
      
      return 0;
}


int Count_Batteries()
{
    DIR *battery_dir;
    char *name, *dirname;
    int t = 0;
       
    dirname = "/proc/acpi/battery/";    
    battery_dir = opendir(dirname);
    if(battery_dir)                  
    {
      struct dirent **namelist;
      int n = 0;

      n = scandir(dirname, &namelist, 0, alphasort);
      if(n<0)
        t = -1;
      else
      {
          while(n--)
          {
            name = namelist[n]->d_name;
            // skip . and .. //
            if (!strncmp (".", name, 1) || !strncmp ("..", name, 2))
                continue;
            else
            {
                t++;}
            free(namelist[n]);
          }
          free(namelist);
      }
    }
    else
    {
      t = 0;
    }
    closedir(battery_dir);
    return t;
}


int Do_Suspend(int State)                     //put system in sleep state 3 or 4 (standby) //
{
    ofstream file_out;
    char *filename, *str;
    
    Set_Kernel_Version();
    
    filename = "/proc/acpi/sleep";   // nice default values //
    str = "3";
    
    switch(State)
    {
      case 3 : if(Kernel_26)
             {
                filename = "/sys/power/state";
                str = "mem";
             }
             break;
      case 4 : if(Kernel_24) str = "4";
             if(Kernel_26)
             {
                filename = "/sys/power/state";
                str = "disk";
             }
             break;
      default : cout<<" Function Do_Suspend : unsupported sleep state, fix this"<<endl;
              return -1; break;
    }
    
    file_out.open(filename);
    if (!file_out)
    {
      cout<<" Function Do_Suspend : could not open file : "<<filename<<". \n"
            " You must have write access to "<<filename<<" to suspend your computer."<<endl;
      return -1;
    } 
       
    file_out<<str;     // sleep tight //
    
    return 0;
}


int Show_Help()
{
    cout<<" Usage: acpitool [option] . . . \n"
    " Shows ACPI information from the /proc/acpi filesystem, like battery status,\n"
    " temperature, or ac power. Can also suspend your machine (if supported).\n"
    "\n"
    "   -a      AC adapter information\n"    //Added by ufoalien:
    "   -A      show supported Asus ACPI extensions (LCD brightness level, video out routing DSTD/acpi4asus info)\n"
    "   -b      battery status, available batteries only\n"
    "   -c      CPU information\n"
    "   -B      battery status, all info on all battery entries\n"
    "   -e      show just about everything\n"
    "   -f      show fan status\n"
    "   -F x    force fan on (x=1) or switch back to auto mode (x=0). (Toshiba only)\n"
    "   -h      show this help screen\n"
    "   -j      eject ultrabay device (Thinkpad only)\n"
    "   -l x    set LCD brightness level to x, where x is 0..7 (Toshiba and Thinkpad only)\n"
    "   -m x    switch the mail led on (x=1) or off (x=0) (Asus only)\n"
    "   -n x    switch the wireless led on (x=1) or off (x=0). (Asus only)\n"
    "   -o x    set LCD on (x=1) or off (x=0). (Asus only)\n" //added by ufoalien 
    "   -s      suspend (sleep state S3), if supported\n"
    "   -S      suspend (sleep state S4), if supported\n"
    "   -t      thermal information, including trip_points\n"
    "   -T      show supported Toshiba ACPI extensions (LCD brightness level, video out routing, fan status)\n"
    "   -v      be more verbose (more detailed error messages, only usefull combined with other options)\n"
    "   -V      show application version number and release date\n"
    "   -w      show wakeup capable devices\n"
    "   -W x    enable/disable wakeup capable device x. The x can be seen when invoking -w first.\n"
    "   -z x    set Asus LCD brightness level to x, where x is 0..15 (Asus only).\n"       //added by ufoalien 
    "\n"
    " If invoked without options, acpitool displays information about available batteries,\n"
    " AC adapter and thermal information.\n\n"
    " For more info, type man acpitool at the prompt.\n\n";
    
    cout<<" "<<App_Version<<", "<<"released "<<Release_Date<<endl;
    cout<<" Homepage: http://freeunix.dyndns.org:8000/site2/acpitool.shtml \n\n";
    return 0;
}


int Show_App_Version()
{
    cout<<" "<<App_Version<<", "<<"released "<<Release_Date<<endl;
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index