]> granicus.if.org Git - sysstat/commitdiff
A_PWR_BAT: Add f_count and f_read functions
authorSebastien GODARD <sysstat@users.noreply.github.com>
Wed, 28 Dec 2022 09:31:27 +0000 (10:31 +0100)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Wed, 28 Dec 2022 09:31:27 +0000 (10:31 +0100)
Add functions used to count number of batteries installed and to read
batteries statistics.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
count.c
count.h
rd_stats.c
rd_stats.h
sa_wrap.c

diff --git a/count.c b/count.c
index a66764e4a91c55ff15d1e1c5d7d659abdca639a9..744761c3cd8da73f541b4d0df4f6b10843d541d9 100644 (file)
--- a/count.c
+++ b/count.c
@@ -533,5 +533,40 @@ __nr_t get_fchost_nr(void)
        return fc;
 }
 
+/*
+ * **************************************************************************
+ * Find number of batteries in /sys/class/power_supply/.
+ * Assume that batteries keep their id number (0, 1...) as long as the
+ * computer is not restarted.
+ *
+ * RETURNS:
+ * Number of batteries.
+ * Return -1 if directory doesn't exist in sysfs.
+ ***************************************************************************
+ */
+__nr_t get_bat_nr(void)
+{
+       DIR *dir;
+       struct dirent *drd;
+       __nr_t bat = 0;
+
+       if ((dir = opendir(SYSFS_PWR_SUPPLY)) == NULL) {
+               /* Directory non-existent */
+               return -1;
+       }
+
+       while ((drd = readdir(dir)) != NULL) {
+
+               if (!strncmp(drd->d_name, "BAT", 3) && isdigit(drd->d_name[3])) {
+                       bat++;
+               }
+       }
+
+       /* Close directory */
+       closedir(dir);
+
+       return bat;
+}
+
 /*------------------ END: FUNCTIONS USED BY SADC ONLY ---------------------*/
 #endif /* SOURCE_SADC */
diff --git a/count.h b/count.h
index 97dc708ac33c97166214aa669cf7cbaf3e84aecd..b4fa26ebabe6e32eae897eb3d47e80ebd0bfb8af 100644 (file)
--- a/count.h
+++ b/count.h
@@ -35,5 +35,7 @@ __nr_t get_filesystem_nr
        (void);
 __nr_t get_fchost_nr
        (void);
+__nr_t get_bat_nr
+       (void);
 
 #endif /* _COUNT_H */
index 3b11598c1298a8f59a0b52db39d1a8a051dc0c40..716723b3875dadaf9ef2e25d35bd013479ec931e 100644 (file)
@@ -3012,5 +3012,98 @@ __nr_t read_psimem(struct stats_psi_mem *st_psi_mem)
        return 1;
 }
 
+/*
+ * **************************************************************************
+ * Read batteries statistics.
+ *
+ * IN:
+ * @st_bat     Structure where stats will be saved.
+ * @nr_alloc   Total number of structures allocated. Value is >= 0.
+ *
+ * OUT:
+ * @st_bat     Structure with statistics.
+ *
+ * RETURNS:
+ * Number of batteries read, or -1 if the buffer was too small and needs to
+ * be reallocated.
+ ***************************************************************************
+ */
+__nr_t read_bat(struct stats_pwr_bat *st_bat, __nr_t nr_alloc)
+{
+       DIR *dir;
+       FILE *fp;
+       struct dirent *drd;
+       struct stats_pwr_bat *st_bat_i;
+       __nr_t bat_read = 0;
+       unsigned int capacity, bat_id;
+       char bat_filename[MAX_PF_NAME];
+       char line[256], status[64];
+
+       /* Each battery, if present, will have its own BATx entry within SYSFS_PWR_SUPPLY */
+       if ((dir = __opendir(SYSFS_PWR_SUPPLY)) == NULL)
+               return 0; /* No batteries */
+
+       /*
+        * Read each of the counters via sysfs, where they are
+        * returned as hex values (e.g. 0x72400).
+        */
+       while ((drd = __readdir(dir)) != NULL) {
+               capacity = 0;
+               status[0] = '\0';
+
+               if (!strncmp(drd->d_name, "BAT", 3) && isdigit(drd->d_name[3])) {
+
+                       if (bat_read + 1 > nr_alloc) {
+                               bat_read = -1;
+                               break;
+                       }
+
+                       /* Get battery id number */
+                       sscanf(drd->d_name + 3, "%u", &bat_id);
+
+                       /* Read battery capcity */
+                       snprintf(bat_filename, MAX_PF_NAME, BAT_CAPACITY,
+                                SYSFS_PWR_SUPPLY, drd->d_name);
+                       if ((fp = fopen(bat_filename, "r"))) {
+                               if (fgets(line, sizeof(line), fp)) {
+                                       sscanf(line, "%u", &capacity);
+                               }
+                               fclose(fp);
+                       }
+
+                       /* Read battery status */
+                       snprintf(bat_filename, MAX_PF_NAME, BAT_STATUS,
+                                SYSFS_PWR_SUPPLY, drd->d_name);
+                       if ((fp = fopen(bat_filename, "r"))) {
+                               fgets(status, sizeof(status), fp);
+                               fclose(fp);
+                       }
+
+                       st_bat_i = st_bat + bat_read++;
+                       st_bat_i->bat_id = (char) bat_id;
+                       st_bat_i->capacity = (char) capacity;
+
+                       if (!strncmp(status, "Charging", 8)) {
+                               st_bat_i->status = BAT_STS_CHARGING;
+                       }
+                       else if (!strncmp(status, "Discharging", 11)) {
+                               st_bat_i->status = BAT_STS_DISCHARGING;
+                       }
+                       else if (!strncmp(status, "Not charging", 12)) {
+                               st_bat_i->status = BAT_STS_NOTCHARGING;
+                       }
+                       else if (!strncmp(status, "Full", 4)) {
+                               st_bat_i->status = BAT_STS_FULL;
+                       }
+                       else {
+                               st_bat_i->status = BAT_STS_UNKNOWN;
+                       }
+               }
+       }
+
+       __closedir(dir);
+       return bat_read;
+}
+
 /*------------------ END: FUNCTIONS USED BY SADC ONLY ---------------------*/
 #endif /* SOURCE_SADC */
index e9560d4d271deabaf0b1812615031781b58373ee..02bb9ba5c4cdfb109a79a1d44afffd89db51272c 100644 (file)
@@ -76,6 +76,9 @@
 #define FC_TX_FRAMES   "%s/%s/statistics/tx_frames"
 #define FC_RX_WORDS    "%s/%s/statistics/rx_words"
 #define FC_TX_WORDS    "%s/%s/statistics/tx_words"
+#define SYSFS_PWR_SUPPLY PRE "/sys/class/power_supply"
+#define BAT_CAPACITY   "%s/%s/capacity"
+#define BAT_STATUS     "%s/%s/status"
 
 /*
  ***************************************************************************
@@ -766,6 +769,18 @@ struct stats_psi_mem {
 #define STATS_PSI_MEM_UL       6
 #define STATS_PSI_MEM_U                0
 
+/* Structure for batteries statistics */
+struct stats_pwr_bat {
+       char    bat_id;
+       char    capacity;
+       char    status;
+};
+
+#define STATS_PWR_BAT_SIZE     (sizeof(struct stats_pwr_bat))
+#define STATS_PWR_BAT_ULL      0
+#define STATS_PWR_BAT_UL       0
+#define STATS_PWR_BAT_U                0
+
 /*
  ***************************************************************************
  * Prototypes for functions used to read system statistics
@@ -862,6 +877,8 @@ __nr_t read_psiio
        (struct stats_psi_io *);
 __nr_t read_psimem
        (struct stats_psi_mem *);
+__nr_t read_bat
+       (struct stats_pwr_bat *, __nr_t);
 
 #endif /* SOURCE_SADC */
 
index acbf57f9243148e3cb47ad0dc08e33891e9cae0b..4d8cb0c2f440dcaa09ee898d22443f06a2d075b1 100644 (file)
--- a/sa_wrap.c
+++ b/sa_wrap.c
@@ -1058,6 +1058,39 @@ __read_funct_t wrap_read_fchost(struct activity *a)
        return;
 }
 
+/*
+ * **************************************************************************
+ * Read batteries statistics.
+ *
+ * IN:
+ * @a  Activity structure.
+ *
+ * OUT:
+ * @a  Activity structure with statistics.
+ ***************************************************************************
+ */
+__read_funct_t wrap_read_bat(struct activity *a)
+{
+       struct stats_pwr_bat *st_bat
+       = (struct stats_pwr_bat *) a->_buf0;
+       __nr_t nr_read = 0;
+
+       /* Read batteries statistics */
+       do {
+               nr_read = read_bat(st_bat, a->nr_allocated);
+
+               if (nr_read < 0) {
+                       /* Buffer needs to be reallocated */
+                       st_bat = (struct stats_pwr_bat *) reallocate_buffer(a);
+               }
+       }
+       while (nr_read < 0);
+
+       a->_nr0 = nr_read;
+
+       return;
+}
+
 /*
  ***************************************************************************
  * Look for online CPU and fill corresponding bitmap.
@@ -1528,3 +1561,28 @@ __nr_t wrap_detect_psi(struct activity *a)
 {
        return (check_dir(PRESSURE));
 }
+
+/*
+ * **************************************************************************
+ * Get number of batteries.
+ *
+ * IN:
+ * @a  Activity structure.
+ *
+ * RETURNS:
+ * Number of batteries installed. Number cannot exceed MAX_NR_BAT.
+ ***************************************************************************
+ */
+__nr_t wrap_get_bat_nr(struct activity *a)
+{
+       __nr_t n = 0;
+
+       if ((n = get_bat_nr()) > 0) {
+               if (n > MAX_NR_BATS)
+                       return MAX_NR_BATS;
+               else
+                       return n;
+       }
+
+       return 0;
+}