From: Sebastien GODARD Date: Wed, 28 Dec 2022 09:31:27 +0000 (+0100) Subject: A_PWR_BAT: Add f_count and f_read functions X-Git-Tag: v12.7.2~38 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d0dc3ea708223ad9e18bce9a223d320215e4afb;p=sysstat A_PWR_BAT: Add f_count and f_read functions Add functions used to count number of batteries installed and to read batteries statistics. Signed-off-by: Sebastien GODARD --- diff --git a/count.c b/count.c index a66764e..744761c 100644 --- 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 97dc708..b4fa26e 100644 --- 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 */ diff --git a/rd_stats.c b/rd_stats.c index 3b11598..716723b 100644 --- a/rd_stats.c +++ b/rd_stats.c @@ -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 */ diff --git a/rd_stats.h b/rd_stats.h index e9560d4..02bb9ba 100644 --- a/rd_stats.h +++ b/rd_stats.h @@ -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 */ diff --git a/sa_wrap.c b/sa_wrap.c index acbf57f..4d8cb0c 100644 --- 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; +}