@@ -611,133 +611,85 @@ bool Platform_getNetworkIO(NetworkIOData* data) {
611611
612612// Linux battery reading by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
613613
614- #define MAX_BATTERIES 64
615614#define PROC_BATTERY_DIR PROCDIR "/acpi/battery"
616615#define PROC_POWERSUPPLY_DIR PROCDIR "/acpi/ac_adapter"
616+ #define PROC_POWERSUPPLY_ACSTATE_FILE PROC_POWERSUPPLY_DIR "/AC/state"
617617#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply"
618618
619619// ----------------------------------------
620620// READ FROM /proc
621621// ----------------------------------------
622622
623- static unsigned long int parseBatInfo (const char * fileName , const unsigned short int lineNum , const unsigned short int wordNum ) {
624- const char batteryPath [] = PROC_BATTERY_DIR ;
625- DIR * batteryDir = opendir (batteryPath );
623+ static double Platform_Battery_getProcBatInfo (void ) {
624+ DIR * batteryDir = opendir (PROC_BATTERY_DIR );
626625 if (!batteryDir )
627- return 0 ;
628-
629- char * batteries [MAX_BATTERIES ];
630- unsigned int nBatteries = 0 ;
631- memset (batteries , 0 , MAX_BATTERIES * sizeof (char * ));
626+ return NAN ;
632627
633- while (nBatteries < MAX_BATTERIES ) {
634- const struct dirent * dirEntry = readdir (batteryDir );
635- if (!dirEntry )
636- break ;
628+ uint64_t totalFull = 0 ;
629+ uint64_t totalRemain = 0 ;
637630
631+ struct dirent * dirEntry = NULL ;
632+ while ((dirEntry = readdir (batteryDir ))) {
638633 const char * entryName = dirEntry -> d_name ;
639634 if (!String_startsWith (entryName , "BAT" ))
640635 continue ;
641636
642- batteries [nBatteries ] = xStrdup (entryName );
643- nBatteries ++ ;
644- }
645- closedir (batteryDir );
637+ char filePath [256 ];
638+ char bufInfo [1024 ] = {0 };
639+ xSnprintf (filePath , sizeof (filePath ), "%s/%s/info" , PROC_BATTERY_DIR , entryName );
640+ ssize_t r = xReadfile (filePath , bufInfo , sizeof (bufInfo ));
641+ if (r < 0 )
642+ continue ;
646643
647- unsigned long int total = 0 ;
648- for (unsigned int i = 0 ; i < nBatteries ; i ++ ) {
649- char infoPath [30 ];
650- xSnprintf (infoPath , sizeof infoPath , "%s%s/%s" , batteryPath , batteries [i ], fileName );
644+ char bufState [1024 ] = {0 };
645+ xSnprintf (filePath , sizeof (filePath ), "%s/%s/state" , PROC_BATTERY_DIR , entryName );
646+ r = xReadfile (filePath , bufState , sizeof (bufState ));
647+ if (r < 0 )
648+ continue ;
651649
652- FILE * file = fopen (infoPath , "r" );
653- if (!file )
654- break ;
650+ const char * line ;
655651
656- char * line = NULL ;
657- for (unsigned short int j = 0 ; j < lineNum ; j ++ ) {
658- free (line );
659- line = String_readLine (file );
660- if (!line )
652+ //Getting total charge for all batteries
653+ char * buf = bufInfo ;
654+ while ((line = strsep (& buf , "\n" )) != NULL ) {
655+ char field [100 ] = {0 };
656+ int val = 0 ;
657+ if (2 != sscanf (line , "%99[^:]:%d" , field , & val ))
658+ continue ;
659+
660+ if (String_eq (field , "last full capacity" )) {
661+ totalFull += val ;
661662 break ;
663+ }
662664 }
663665
664- fclose (file );
665-
666- if (!line )
667- break ;
668-
669- char * foundNumStr = String_getToken (line , wordNum );
670- const unsigned long int foundNum = atoi (foundNumStr );
671- free (foundNumStr );
672- free (line );
666+ //Getting remaining charge for all batteries
667+ buf = bufState ;
668+ while ((line = strsep (& buf , "\n" )) != NULL ) {
669+ char field [100 ] = {0 };
670+ int val = 0 ;
671+ if (2 != sscanf (line , "%99[^:]:%d" , field , & val ))
672+ continue ;
673673
674- total += foundNum ;
674+ if (String_eq (field , "remaining capacity" )) {
675+ totalRemain += val ;
676+ break ;
677+ }
678+ }
675679 }
676680
677- for (unsigned int i = 0 ; i < nBatteries ; i ++ )
678- free (batteries [i ]);
681+ closedir (batteryDir );
679682
680- return total ;
683+ return totalFull > 0 ? (( double ) totalRemain * 100.0 ) / ( double ) totalFull : NAN ;
681684}
682685
683686static ACPresence procAcpiCheck (void ) {
684- ACPresence isOn = AC_ERROR ;
685- const char * power_supplyPath = PROC_POWERSUPPLY_DIR ;
686- DIR * dir = opendir (power_supplyPath );
687- if (!dir )
687+ char buffer [1024 ] = {0 };
688+ ssize_t r = xReadfile (PROC_POWERSUPPLY_ACSTATE_FILE , buffer , sizeof (buffer ));
689+ if (r < 1 )
688690 return AC_ERROR ;
689691
690- for (;;) {
691- const struct dirent * dirEntry = readdir (dir );
692- if (!dirEntry )
693- break ;
694-
695- const char * entryName = dirEntry -> d_name ;
696-
697- if (entryName [0 ] != 'A' )
698- continue ;
699-
700- char statePath [256 ];
701- xSnprintf (statePath , sizeof (statePath ), "%s/%s/state" , power_supplyPath , entryName );
702- FILE * file = fopen (statePath , "r" );
703- if (!file ) {
704- isOn = AC_ERROR ;
705- continue ;
706- }
707- char * line = String_readLine (file );
708-
709- fclose (file );
710-
711- if (!line )
712- continue ;
713-
714- char * isOnline = String_getToken (line , 2 );
715- free (line );
716-
717- if (String_eq (isOnline , "on-line" ))
718- isOn = AC_PRESENT ;
719- else
720- isOn = AC_ABSENT ;
721- free (isOnline );
722- if (isOn == AC_PRESENT )
723- break ;
724- }
725-
726- closedir (dir );
727-
728- return isOn ;
729- }
730-
731- static double Platform_Battery_getProcBatInfo (void ) {
732- const unsigned long int totalFull = parseBatInfo ("info" , 3 , 4 );
733- if (totalFull == 0 )
734- return NAN ;
735-
736- const unsigned long int totalRemain = parseBatInfo ("state" , 5 , 3 );
737- if (totalRemain == 0 )
738- return NAN ;
739-
740- return totalRemain * 100.0 / (double ) totalFull ;
692+ return String_eq (buffer , "on-line" ) ? AC_PRESENT : AC_ABSENT ;
741693}
742694
743695static void Platform_Battery_getProcData (double * percent , ACPresence * isOnAC ) {
@@ -750,100 +702,81 @@ static void Platform_Battery_getProcData(double* percent, ACPresence* isOnAC) {
750702// ----------------------------------------
751703
752704static void Platform_Battery_getSysData (double * percent , ACPresence * isOnAC ) {
753-
754705 * percent = NAN ;
755706 * isOnAC = AC_ERROR ;
756707
757708 DIR * dir = opendir (SYS_POWERSUPPLY_DIR );
758709 if (!dir )
759710 return ;
760711
761- unsigned long int totalFull = 0 ;
762- unsigned long int totalRemain = 0 ;
763-
764- for (;;) {
765- const struct dirent * dirEntry = readdir (dir );
766- if (!dirEntry )
767- break ;
712+ uint64_t totalFull = 0 ;
713+ uint64_t totalRemain = 0 ;
768714
715+ struct dirent * dirEntry = NULL ;
716+ while ((dirEntry = readdir (dir ))) {
769717 const char * entryName = dirEntry -> d_name ;
770- char filePath [256 ];
771718
772- xSnprintf (filePath , sizeof filePath , SYS_POWERSUPPLY_DIR "/%s/type" , entryName );
773-
774- char type [8 ];
775- ssize_t r = xReadfile (filePath , type , sizeof (type ));
776- if (r < 3 )
777- continue ;
778-
779- if (type [0 ] == 'B' && type [1 ] == 'a' && type [2 ] == 't' ) {
719+ if (String_startsWith (entryName , "BAT" )) {
720+ char buffer [1024 ] = {0 };
721+ char filePath [256 ];
780722 xSnprintf (filePath , sizeof filePath , SYS_POWERSUPPLY_DIR "/%s/uevent" , entryName );
781723
782- char buffer [1024 ];
783- r = xReadfile (filePath , buffer , sizeof (buffer ));
784- if (r < 0 ) {
785- closedir (dir );
786- return ;
787- }
724+ ssize_t r = xReadfile (filePath , buffer , sizeof (buffer ));
725+ if (r < 0 )
726+ continue ;
788727
789- char * buf = buffer ;
790- const char * line ;
791728 bool full = false;
792729 bool now = false;
793- int fullSize = 0 ;
794- double capacityLevel = NAN ;
795730
796- #define match (str ,prefix ) \
797- (String_startsWith(str,prefix) ? (str) + strlen(prefix) : NULL)
731+ double fullCharge = 0 ;
732+ double capacityLevel = NAN ;
733+ const char * line ;
798734
735+ char * buf = buffer ;
799736 while ((line = strsep (& buf , "\n" )) != NULL ) {
800- const char * ps = match (line , "POWER_SUPPLY_" );
801- if (!ps )
737+ char field [100 ] = {0 };
738+ int val = 0 ;
739+ if (2 != sscanf (line , "POWER_SUPPLY_%99[^=]=%d" , field , & val ))
802740 continue ;
803- const char * capacity = match (ps , "CAPACITY=" );
804- if (capacity )
805- capacityLevel = atoi (capacity ) / 100.0 ;
806- const char * energy = match (ps , "ENERGY_" );
807- if (!energy )
808- energy = match (ps , "CHARGE_" );
809- if (!energy )
741+
742+ if (String_eq (field , "CAPACITY" )) {
743+ capacityLevel = val / 100.0 ;
810744 continue ;
811- const char * value = (!full ) ? match (energy , "FULL=" ) : NULL ;
812- if (value ) {
813- fullSize = atoi (value );
814- totalFull += fullSize ;
745+ }
746+
747+ if (String_eq (field , "ENERGY_FULL" ) || String_eq (field , "CHARGE_FULL" )) {
748+ fullCharge = val ;
749+ totalFull += fullCharge ;
815750 full = true;
816751 if (now )
817752 break ;
818753 continue ;
819754 }
820- value = (! now ) ? match ( energy , "NOW=" ) : NULL ;
821- if (value ) {
822- totalRemain += atoi ( value ) ;
755+
756+ if (String_eq ( field , "ENERGY_NOW" ) || String_eq ( field , "CHARGE_NOW" ) ) {
757+ totalRemain += val ;
823758 now = true;
824759 if (full )
825760 break ;
826761 continue ;
827762 }
828763 }
829764
830- #undef match
831-
832765 if (!now && full && !isnan (capacityLevel ))
833- totalRemain += ( capacityLevel * fullSize ) ;
766+ totalRemain += capacityLevel * fullCharge ;
834767
835- } else if (entryName [0 ] == 'A' ) {
768+ } else if (String_eq (entryName , "AC" )) {
769+ char buffer [2 ] = {0 };
836770 if (* isOnAC != AC_ERROR )
837771 continue ;
838772
839- xSnprintf (filePath , sizeof filePath , SYS_POWERSUPPLY_DIR "/%s/online" , entryName );
840-
841- char buffer [2 ];
773+ char filePath [256 ];
774+ xSnprintf (filePath , sizeof (filePath ), SYS_POWERSUPPLY_DIR "/%s/online" , entryName );
842775
843- r = xReadfile (filePath , buffer , sizeof (buffer ));
776+ ssize_t r = xReadfile (filePath , buffer , sizeof (buffer ));
844777 if (r < 1 ) {
845- closedir ( dir ) ;
846- return ;
778+ * isOnAC = AC_ERROR ;
779+ continue ;
847780 }
848781
849782 if (buffer [0 ] == '0' )
@@ -852,6 +785,7 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
852785 * isOnAC = AC_PRESENT ;
853786 }
854787 }
788+
855789 closedir (dir );
856790
857791 * percent = totalFull > 0 ? ((double ) totalRemain * 100.0 ) / (double ) totalFull : NAN ;
0 commit comments