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 : 14-05-2006                                                  */
/*---------------------------------------------------------------------------*/
/*                                                                           */
/* 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.5"
#define Release_Date "14-May-2006"

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[2];
    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 Is_Discharging = 0;
    int AC_Online = 0;
    int Present_Batteries = 0;
    
    int Nr_Batteries = Count_Batteries();   // this actually only counts battery entries found in /proc/acpi/battery  //
    
    //printf("Number of battery entries found : %d \n", Nr_Batteries);//
    
    if(Nr_Batteries>0)
    {
        for(int i=0; i<Nr_Batteries; i++)
      {
          Bat_Nr = i+1;
          Batt_Info[i] = new Battery_Info;
                  
          Batt_Info[i]->Battery_Present = 0;
          bzero(Batt_Info[i]->Remaining_Cap, 10);
          bzero(Batt_Info[i]->Design_Cap, 10);
          bzero(Batt_Info[i]->LastFull_Cap, 10);
          bzero(Batt_Info[i]->Present_Rate, 10);
          bzero(Batt_Info[i]->Charging_State, 12);
          bzero(Batt_Info[i]->Technology, 13);
          bzero(Batt_Info[i]->Model, 13);
          bzero(Batt_Info[i]->Serial, 13);
          bzero(Batt_Info[i]->Bat_Type, 13); 
          // initialize all struct members to blanks --> avoid rubbish in output //
                  
          Get_Battery_Info(Bat_Nr, Batt_Info[i], verbose);
          Show_Time = atoi(Batt_Info[i]->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[i]->Battery_Present)
          {
            case 1 : 
            {     
                Present_Batteries++;
                Remaining_Percentage = float(atoi(Batt_Info[i]->Remaining_Cap)) / float(atoi(Batt_Info[i]->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[i]->Charging_State,"char",4)==0) 
                {
                  Is_Charging = 1;
                }
                else
                {
                  if(strncmp(Batt_Info[i]->Charging_State,"disch",5)==0) Is_Discharging = 1;
                }
                            
                if(Show_Time)      // calculate remaining or charging time only if present battery rate != 0 //
                {
                  if(Is_Charging)
                    Remaining_Time = (float(atoi(Batt_Info[i]->LastFull_Cap)) - float(atoi(Batt_Info[i]->Remaining_Cap))) / float(atoi(Batt_Info[i]->Present_Rate)); 
                  else
                    Remaining_Time = float(atoi(Batt_Info[i]->Remaining_Cap)) / float(atoi(Batt_Info[i]->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[i]->Design_Cap) > 0)
                  Battery_Left_Percent = float(atoi(Batt_Info[i]->LastFull_Cap)) / float(atoi(Batt_Info[i]->Design_Cap)) * 100.0;
                else
                  Battery_Left_Percent = -1.0;
                                      
          
                switch(info_level)
                {
                  case 0 : cout.precision(Precision);
                           cout<<"  Battery #"<<Bat_Nr<<"     : "<<Batt_Info[i]->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[i]->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[i]->Design_Cap<<endl;
                         cout<<"    Last full capacity : "<<Batt_Info[i]->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[i]->Present_Rate<<endl;
                           cout<<"    Charging state     : "<<Batt_Info[i]->Charging_State<<endl;
                           cout<<"    Battery type       : "<<Batt_Info[i]->Technology<<", "<<Batt_Info[i]->Bat_Type<<endl;
                         
                         if (strlen(Batt_Info[i]->Model)!=0)
                              cout<<"    Model number       : "<<Batt_Info[i]->Model<<endl;
                           if (strlen(Batt_Info[i]->Serial)!=0)
                            cout<<"    Serial number      : "<<Batt_Info[i]->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[i]->Battery_Present<<endl;
                    break;
          }    
      
      }
      
      if(Is_Discharging)
          AC_Online = 0;    // assume AC must be  offline if at least 1 battery is discharging //
      else
          AC_Online = 1;    // assume (possibly dangerous) AC is online if all batteries report being charging or charged //
      
      /* printf(" Number of batteries present : %d \n", Present_Batteries); 
      printf(" AC_Online =  %d \n", AC_Online); */
      
      // calculate total battery time left if more than 1 battery is present and AC is offline //
      if(Present_Batteries>1 && AC_Online==0)  
      {
          int Total_Remaining_Cap, Total_LastFull_Cap, Total_Rate;
          
          Total_LastFull_Cap = 0;
          Total_Remaining_Cap = 0;
          Total_Rate = 0;
          
          for(int t=0; t<Present_Batteries; t++)
          {
            Total_Remaining_Cap = Total_Remaining_Cap + (atoi(Batt_Info[t]->Remaining_Cap));
            Total_LastFull_Cap = Total_LastFull_Cap + (atoi(Batt_Info[t]->LastFull_Cap));
            Total_Rate = Total_Rate + (atoi(Batt_Info[t]->Present_Rate));
          }  
          
          if(Total_Rate > 0)    // unlikely to happen if we got here but avoid possible division by 0 //
          {
            Remaining_Percentage = float(Total_Remaining_Cap) / float(Total_LastFull_Cap) * 100.0;
            
            if( Remaining_Percentage > 100.0) Remaining_Percentage = 100.0;
                                  
            if( int(Remaining_Percentage) < 10)
                      Precision = 3;
            else
                Precision = 4;
            
            Remaining_Time = float(Total_Remaining_Cap) / float(Total_Rate); 
            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);
            
            cout.precision(Precision);
            cout<<"  All batteries  : "<<showpoint<<Remaining_Percentage<<"%";
            cout<<", "<<setfill('0')<<setw(2)<<Hours<<":"<<setfill('0')<<setw(2)<<Minutes<<":"
            <<setfill('0')<<setw(2)<<Time_In_Seconds<<endl; 
          }
      }
      for(int t=0; t<Nr_Batteries; t++) delete Batt_Info[t];
    }
    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[15][75], str[120];
    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, 120);
            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, 120);
            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, 120);
                  fgets(str, 120, 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;
      long int max_cstate = 0, cst_cnt = 0, cst_usage_abs[8],
             cst_usage_notC0 = 0;
      long long int bm_activity;
      float cst_usage_rel[8];
      DIR *cpu_dir;
      char *name;

      //file_in.open("/home/david/dropzone/devel/acpi/processor/CPU0/cpuinfo");//
      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;
            
            int skip = 10;
            if(strncmp(temp,"AMD Athlon(tm) 64",17)==0) skip = 6;    // cpuinfo returns diiferent info for AMD64 cpu's //     
            
            file_in.getline(str, 100);
            file_in.getline(str, 100);
            bzero(temp, 80);
            strncpy(temp, str+11, 10);
            cout<<"  CPU speed              : "<<temp<<" MHz"<<endl;
            
            file_in.getline(str, 100);
            bzero(temp, 80);
            strncpy(temp, str+13, 10);
            cout<<"  Cache size             : "<<temp<<endl;
            
            for(int t=0; t<skip; t++) file_in.getline(str,199);        // skip "skip" lines to reach Bogomips line//
            
            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]);      // acpi/processor/%s/info
                  
                  //file_in.open("/home/david/dropzone/devel/acpi/processor/CPU0/info");//
                  
                  if(file_in)                   
                  {
                        file_in.getline(str, 90); // processor id
                        bzero(temp, 80);
                        strncpy(temp, str+25, 5);
                        cout<<"  Processor ID           : "<<temp<<endl;

                        file_in.getline(str, 100); // acpi id
                        file_in.getline(str, 100); // bus mastering control
                        bzero(temp, 80);
                        strncpy(temp, str+25, 5);
                        cout<<"  Bus mastering control  : "<<temp<<endl;

                        file_in.getline(str, 100); // power management
                        bzero(temp, 80);
                        strncpy(temp, str+25, 5);
                        cout<<"  Power management       : "<<temp<<endl;

                        file_in.getline(str, 100); // throttling control
                        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);    // limit interface (beware: on linux2.4
                                                                  // this line yields "perf mgmt")
                        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]); // acpi/processor/%s/power
                  //file2_in.open("/home/david/dropzone/devel/acpi/processor/CPU0/power");//
                  
                  if(file2_in)                   
                  {
                        file2_in.getline(str, 100); // active state
                        bzero(temp, 80);
                        strncpy(temp, str+25, 5);
                        cout<<"  Active C-state         : "<<temp<<endl;

                  // next code added by Niko Ehrenfeuchter (University of  Freiburg, Germany) //
                  
                        file2_in.getline(str, 100); // max_cstate
                        memset(&temp, 0, sizeof(temp));
                        strncpy(temp, str+26, 2);
                        max_cstate = strtol(temp, NULL, 10);
                        // no output since cstate-count isn't set properly by kernel,
                        // maybe this will be fixed at some later time...
                        // cout << "  Supported C-states     : " << max_cstate << endl;


                        file2_in.getline(str, 100); // bus master activity
                        memset(&temp, 0, sizeof(temp));
                        strncpy(temp, str+25, 8);
                        bm_activity = strtoll(temp, NULL, 16);
                        // cout << "  Bus Master Activity hx : 0x" << temp << endl;
                        // cout << "  Bus Master Activity dc : " << bm_activity << endl;

                        file2_in.getline(str, 100); // states (line contains no information)
                        while(!file2_in.eof())
                        {
                              file2_in.getline(str, 130);  // cstate Cx
                                                     // reading up to 130 char here for AMD64 cpu's  //
                              if (strlen(str)!=0)
                              {
                                    cst_cnt++; // NOTE: we have no usage cnter for C0!!!
                                    memset(&temp, 0, sizeof(temp));
                                    strncpy(temp, str+80, 8);
                                    cst_usage_abs[cst_cnt] = strtol(temp, NULL, 10);
                                    cst_usage_notC0 += cst_usage_abs[cst_cnt];
                              }
                        }     
                        // now we can set max_cstate to the correct value
                        max_cstate = cst_cnt;
                        cout << "  C-states (incl. C0)    : " << (max_cstate + 1) << endl;

                        // calculate usage etc.
                        if(cst_usage_notC0!=0)  // avoid possible division by 0, happens if usage is 00000000 //
                        {
                            for (int cst=1; cst <= max_cstate ; cst++)
                            {
                              cst_usage_rel[cst] = float(cst_usage_abs[cst]) / cst_usage_notC0;
                              fprintf(stdout, "  Usage of state C%d      : %li (%.1f %%)\n", cst,
                                          cst_usage_abs[cst], (cst_usage_rel[cst] * 100));
                            }
                        }

                        file2_in.close();
                      // end code added by Niko Ehrenfeuchter (University of  Freiburg, Germany) //
                  }
                  else
                  {
                        cout<<"  could not open file "<<filename[i-1]<<endl;
                  }


                  if(thrott)
                  {
                        file_in.open(filename[i]); // acpi/processor/%s/throttling
                        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][65], 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 
    // dirname = "/home/david/dropzone/data/devel/acpi/battery/";    // keep this for testing //    

    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);
            //sprintf(filename[findex], "/home/david/dropzone/data/devel/acpi/battery/%s/info", name);//
            findex++;
            
            sprintf(filename[findex], "/proc/acpi/battery/%s/state", name);
            //sprintf(filename[findex], "/home/david/dropzone/data/devel/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   AC adapter information\n"    //Added by ufoalien:
    "   -A, --Asus         show supported Asus ACPI extensions (LCD brightness level, video out routing DSTD/acpi4asus info)\n"
    "   -b                 battery status, available batteries only\n"
    "   -c, --cpu          CPU information\n"
    "   -B, --battery      battery status, all info on all battery entries\n"
    "   -e                 show just about everything\n"
    "   -f, --fan          show fan status\n"
    "   -F x               force fan on (x=1) or switch back to auto mode (x=0). (Toshiba only)\n"
    "   -h, --help         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      suspend to memory (sleep state S3), if supported\n"
    "   -S                 suspend to disk (sleep state S4), if supported\n"
    "   -t, --thermal      thermal information, including trip_points\n"
    "   -T, --Toshiba      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, --version      show application version number and release date\n"
    "   -w, --wakeup       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;
}

int Usage()
{
    cout<<" You invoked acpitool with an unknown option. Type 'acpitool -h' or 'acpitool --help' for info. "<<endl;
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index