diff options
Diffstat (limited to 'regulator.c')
-rw-r--r-- | regulator.c | 360 |
1 files changed, 205 insertions, 155 deletions
diff --git a/regulator.c b/regulator.c index 18c9777..0da924a 100644 --- a/regulator.c +++ b/regulator.c @@ -11,191 +11,241 @@ * Contributors: * Amit Arora <amit.arora@linaro.org> (IBM Corporation) * - initial API and implementation + * Daniel Lezcano <daniel.lezcano@linaro.org> (IBM Corporation) + * - rewrote code and API based on the tree *******************************************************************************/ #include "regulator.h" -int init_regulator_ds(void) +#define SYSFS_REGULATOR "/sys/class/regulator" +#define VALUE_MAX 16 + +#define _GNU_SOURCE +#include <stdio.h> +#undef _GNU_SOURCE +#include <sys/types.h> +#include <stdbool.h> +#include <dirent.h> +#include <string.h> +#include <stdlib.h> +#include "display.h" +#include "powerdebug.h" +#include "tree.h" +#include "utils.h" + +struct regulator_info { + char name[NAME_MAX]; + char state[VALUE_MAX]; + char status[VALUE_MAX]; + char type[VALUE_MAX]; + char opmode[VALUE_MAX]; + int microvolts; + int min_microvolts; + int max_microvolts; + int microamps; + int min_microamps; + int max_microamps; + int requested_microamps; + int num_users; +}; + +struct regulator_data { + const char *name; + const char *ifmt; + const char *ofmt; + bool derefme; +}; + +static struct regulator_data regdata[] = { + { "name", "%s", "\tname: %s\n" }, + { "status", "%s", "\tstatus: %s\n" }, + { "state", "%s", "\tstate: %s\n" }, + { "type", "%s", "\ttype: %s\n" }, + { "num_users", "%d", "\tnum_users: %d\n", true }, + { "microvolts", "%d", "\tmicrovolts: %d\n", true }, + { "max_microvolts", "%d", "\tmax_microvolts: %d\n", true }, + { "min_microvolts", "%d", "\tmin_microvolts: %d\n", true }, +}; + +static struct tree *reg_tree; + +static struct regulator_info *regulator_alloc(void) { - DIR *regdir; - struct dirent *item; - - regdir = opendir("/sys/class/regulator"); - if (!regdir) - return(1); - while ((item = readdir(regdir))) { - if (strncmp(item->d_name, "regulator", 9)) + struct regulator_info *regi; + + regi = malloc(sizeof(*regi)); + if (regi) + memset(regi, 0, sizeof(*regi)); + + return regi; +} + +static int regulator_dump_cb(struct tree *tree, void *data) +{ + int i; + char buffer[NAME_MAX]; + size_t nregdata = sizeof(regdata) / sizeof(regdata[0]); + + if (!strncmp("regulator.", tree->name, strlen("regulator."))) + printf("\n%s:\n", tree->name); + + for (i = 0; i < nregdata; i++) { + int val; + + if (file_read_value(tree->path, regdata[i].name, + regdata[i].ifmt, buffer)) continue; - numregulators++; - } - closedir(regdir); - - regulators_info = (struct regulator_info *)malloc(numregulators* - sizeof(struct regulator_info)); - if (!regulators_info) { - fprintf(stderr, "init_regulator_ds: Not enough memory to " - "read information for %d regulators!\n", numregulators); - return(1); + if (regdata[i].derefme) { + val = atoi(buffer); + printf(regdata[i].ofmt, val); + } else + printf(regdata[i].ofmt, buffer); } - return(0); + return 0; } -void print_string_val(char *name, char *val) +int regulator_dump(void) { - printf("\t%s=%s", name, val); - if (!strchr(val, '\n')) - printf("\n"); + printf("\nRegulator Information:\n"); + printf("*********************\n\n"); + + return tree_for_each(reg_tree, regulator_dump_cb, NULL); } -void print_regulator_info(int verbose) +static int regulator_display_cb(struct tree *t, void *data) { - int i; + struct regulator_info *reg = t->private; + int *line = data; + char *buf; - printf("\nRegulator Information:\n"); - printf("*********************\n\n"); + /* we skip the root node of the tree */ + if (!t->parent) + return 0; - for (i = 0; i < numregulators; i++) { - printf("Regulator %d:\n", i + 1); - print_string_val("name", regulators_info[i].name); - if (strcmp(regulators_info[i].status, "")) - print_string_val("status", regulators_info[i].status); - if (strcmp(regulators_info[i].state, "")) - print_string_val("state", regulators_info[i].state); + if (!strlen(reg->name)) + return 0; - if (!verbose) - continue; + if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11d %-11d %-11d %-12d", + reg->name, reg->status, reg->state, reg->type, + reg->num_users, reg->microvolts, reg->min_microvolts, + reg->max_microvolts) < 0) + return -1; - if (strcmp(regulators_info[i].type, "")) - print_string_val("type", regulators_info[i].type); - if (strcmp(regulators_info[i].opmode, "")) - print_string_val("opmode", regulators_info[i].opmode); - - if (regulators_info[i].microvolts) - printf("\tmicrovolts=%d\n", - regulators_info[i].microvolts); - if (regulators_info[i].min_microvolts) - printf("\tmin_microvolts=%d\n", - regulators_info[i].min_microvolts); - if (regulators_info[i].max_microvolts) - printf("\tmax_microvolts=%d\n", - regulators_info[i].max_microvolts); - - if (regulators_info[i].microamps) - printf("\tmicroamps=%d\n", - regulators_info[i].microamps); - if (regulators_info[i].min_microamps) - printf("\tmin_microamps=%d\n", - regulators_info[i].min_microamps); - if (regulators_info[i].max_microamps) - printf("\tmax_microamps=%d\n", - regulators_info[i].max_microamps); - if (regulators_info[i].requested_microamps) - printf("\trequested_microamps=%d\n", - regulators_info[i].requested_microamps); - - if (regulators_info[i].num_users) - printf("\tnum_users=%d\n", - regulators_info[i].num_users); - printf("\n"); - } + display_print_line(REGULATOR, *line, buf, reg->num_users, t); - if (!numregulators && verbose) { - printf("Could not find regulator information!"); - printf(" Looks like /sys/class/regulator is empty.\n\n"); - } + (*line)++; + + free(buf); - printf("\n\n"); + return 0; } -void read_info_from_dirent(struct dirent *ritem, char *str, int idx) +static int regulator_print_header(void) { - if (!strcmp(ritem->d_name, "name")) - strcpy(regulators_info[idx].name, str); - if (!strcmp(ritem->d_name, "state")) - strcpy(regulators_info[idx].state, str); - if (!strcmp(ritem->d_name, "status")) - strcpy(regulators_info[idx].status, str); - - if (!strcmp(ritem->d_name, "type")) - strcpy(regulators_info[idx].type, str); - if (!strcmp(ritem->d_name, "opmode")) - strcpy(regulators_info[idx].opmode, str); - - if (!strcmp(ritem->d_name, "microvolts")) - regulators_info[idx].microvolts = atoi(str); - if (!strcmp(ritem->d_name, "min_microvolts")) - regulators_info[idx].min_microvolts = atoi(str); - if (!strcmp(ritem->d_name, "max_microvolts")) - regulators_info[idx].max_microvolts = atoi(str); - - if (!strcmp(ritem->d_name, "microamps")) - regulators_info[idx].microamps = atoi(str); - if (!strcmp(ritem->d_name, "min_microamps")) - regulators_info[idx].min_microamps = atoi(str); - if (!strcmp(ritem->d_name, "max_microamps")) - regulators_info[idx].max_microamps = atoi(str); - if (!strcmp(ritem->d_name, "requested_microamps")) - regulators_info[idx].requested_microamps = atoi(str); - - if (!strcmp(ritem->d_name, "num_users")) - regulators_info[idx].num_users = atoi(str); + char *buf; + int ret; + + if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11s %-11s %-11s %-12s", + "Name", "Status", "State", "Type", "Users", "Microvolts", + "Min u-volts", "Max u-volts") < 0) + return -1; + + ret = display_column_name(buf); + + free(buf); + + return ret; + } -int read_regulator_info(void) +static int regulator_display(bool refresh) { - FILE *file = NULL; - DIR *regdir, *dir; - int len, count = 0, ret = 0; - char line[1024], filename[1024], *fptr; - struct dirent *item, *ritem; - - regdir = opendir("/sys/class/regulator"); - if (!regdir) - return(1); - while ((item = readdir(regdir))) { - if (strlen(item->d_name) < 3) - continue; + int ret, line = 0; - if (strncmp(item->d_name, "regulator", 9)) - continue; + display_reset_cursor(REGULATOR); - len = sprintf(filename, "/sys/class/regulator/%s", - item->d_name); + regulator_print_header(); - dir = opendir(filename); - if (!dir) - continue; - count++; - - if (count > numregulators) { - ret = 1; - goto exit; - } - - strcpy(regulators_info[count-1].name, item->d_name); - while ((ritem = readdir(dir))) { - if (strlen(ritem->d_name) < 3) - continue; - - sprintf(filename + len, "/%s", ritem->d_name); - file = fopen(filename, "r"); - if (!file) - continue; - memset(line, 0, 1024); - fptr = fgets(line, 1024, file); - fclose(file); - if (!fptr) - continue; - read_info_from_dirent(ritem, fptr, count - 1); - } - exit: - closedir(dir); - if (ret) - break; - } - closedir(regdir); + ret = tree_for_each(reg_tree, regulator_display_cb, &line); + + display_refresh_pad(REGULATOR); return ret; } + +static int regulator_filter_cb(const char *name) +{ + /* let's ignore some directories in order to avoid to be + * pulled inside the sysfs circular symlinks mess/hell + * (choose the word which fit better) + */ + if (!strcmp(name, "device")) + return 1; + + if (!strcmp(name, "subsystem")) + return 1; + + if (!strcmp(name, "driver")) + return 1; + + return 0; +} + +static inline int read_regulator_cb(struct tree *t, void *data) +{ + struct regulator_info *reg = t->private; + + file_read_value(t->path, "name", "%s", reg->name); + file_read_value(t->path, "state", "%s", reg->state); + file_read_value(t->path, "status", "%s", reg->status); + file_read_value(t->path, "type", "%s", reg->type); + file_read_value(t->path, "opmode", "%s", reg->opmode); + file_read_value(t->path, "num_users", "%d", ®->num_users); + file_read_value(t->path, "microvolts", "%d", ®->microvolts); + file_read_value(t->path, "min_microvolts", "%d", ®->min_microvolts); + file_read_value(t->path, "max_microvolts", "%d", ®->max_microvolts); + file_read_value(t->path, "microamps", "%d", ®->microamps); + file_read_value(t->path, "min_microamps", "%d", ®->min_microamps); + file_read_value(t->path, "max_microamps", "%d", ®->max_microamps); + + return 0; +} + +static int fill_regulator_cb(struct tree *t, void *data) +{ + struct regulator_info *reg; + + reg = regulator_alloc(); + if (!reg) + return -1; + t->private = reg; + + /* we skip the root node but we set it expanded for its children */ + if (!t->parent) + return 0; + + return read_regulator_cb(t, data); +} + +static int fill_regulator_tree(void) +{ + return tree_for_each(reg_tree, fill_regulator_cb, NULL); +} + +static struct display_ops regulator_ops = { + .display = regulator_display, +}; + +int regulator_init(void) +{ + reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb, false); + if (!reg_tree) + return -1; + + if (fill_regulator_tree()) + return -1; + + return display_register(REGULATOR, ®ulator_ops); +} |