[powerdebug,03/22] Rewrite the regulator code based on the tree

Message ID 1308145856-6112-3-git-send-email-daniel.lezcano@linaro.org
State Accepted
Headers show

Commit Message

Daniel Lezcano June 15, 2011, 1:50 p.m.
Make the code consistent with the clocks and use the tree to
build the regulators.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 display.c    |   50 ++++++----
 powerdebug.c |   50 +++++----
 powerdebug.h |    4 +-
 regulator.c  |  322 ++++++++++++++++++++++++++++++----------------------------
 regulator.h  |   29 +-----
 5 files changed, 227 insertions(+), 228 deletions(-)

Patch

diff --git a/display.c b/display.c
index 8712023..3795547 100644
--- a/display.c
+++ b/display.c
@@ -190,13 +190,8 @@  void show_header(int selectedwindow)
 	wrefresh(footer_win);
 }
 
-
-void show_regulator_info(struct regulator_info *reg_info, int nr_reg, int verbose)
+void print_regulator_header(void)
 {
-	int i, count = 1;
-
-	(void)verbose;
-
 	werase(regulator_win);
 	wattron(regulator_win, A_BOLD);
 	print(regulator_win, 0, 0, "Name");
@@ -208,6 +203,34 @@  void show_regulator_info(struct regulator_info *reg_info, int nr_reg, int verbos
 	print(regulator_win, 72, 0, "Min u-volts");
 	print(regulator_win, 84, 0, "Max u-volts");
 	wattroff(regulator_win, A_BOLD);
+	wrefresh(regulator_win);
+}
+
+void print_clock_header(void)
+{
+	werase(clock_labels);
+	wattron(clock_labels, A_BOLD);
+	print(clock_labels, 0, 0, "Name");
+	print(clock_labels, 56, 0, "Flags");
+	print(clock_labels, 75, 0, "Rate");
+	print(clock_labels, 88, 0, "Usecount");
+	print(clock_labels, 98, 0, "Children");
+	wattroff(clock_labels, A_BOLD);
+	wrefresh(clock_labels);
+}
+
+#if 0
+void show_regulator_info(struct regulator_info *reg_info, int nr_reg, int verbose)
+{
+	int i, count = 1;
+
+	print_regulator_header();
+
+	wrefresh(regulator_win);
+
+	return;
+
+	(void)verbose;
 
 	for (i = 0; i < nr_reg; i++) {
 		int col = 0;
@@ -248,20 +271,7 @@  void show_regulator_info(struct regulator_info *reg_info, int nr_reg, int verbos
 	}
 	wrefresh(regulator_win);
 }
-
-
-void print_clock_header(void)
-{
-	werase(clock_labels);
-	wattron(clock_labels, A_BOLD);
-	print(clock_labels, 0, 0, "Name");
-	print(clock_labels, 56, 0, "Flags");
-	print(clock_labels, 75, 0, "Rate");
-	print(clock_labels, 88, 0, "Usecount");
-	print(clock_labels, 98, 0, "Children");
-	wattroff(clock_labels, A_BOLD);
-	wrefresh(clock_labels);
-}
+#endif
 
 void print_sensor_header(void)
 {
diff --git a/powerdebug.c b/powerdebug.c
index 3a2edac..a303757 100644
--- a/powerdebug.c
+++ b/powerdebug.c
@@ -174,6 +174,21 @@  int keystroke_callback(bool *enter_hit, bool *findparent_ncurses,
 			options->selectedwindow = TOTAL_FEATURE_WINS - 1;
 	}
 
+#if 0 /* TODO */
+	if (options->selectedwindow == REGULATOR) {
+
+		if (keystroke == KEY_DOWN) {
+			display_next_line();
+			*cont = true;
+		}
+
+		if (keystroke == KEY_UP) {
+			display_prev_line();
+			*cont = true;
+		}
+
+	}
+#endif
 	if (options->selectedwindow == CLOCK) {
 
 		if (keystroke == KEY_DOWN) {
@@ -242,8 +257,7 @@  int keystroke_callback(bool *enter_hit, bool *findparent_ncurses,
 	return 0;
 }
 
-int mainloop(struct powerdebug_options *options,
-	     struct regulator_info *reg_info, int nr_reg)
+int mainloop(struct powerdebug_options *options)
 {
 	bool findparent_ncurses = false;
 	bool refreshwin = false;
@@ -264,11 +278,8 @@  int mainloop(struct powerdebug_options *options,
 			create_selectedwindow(options->selectedwindow);
 		}
 
-		if (options->selectedwindow == REGULATOR) {
-			regulator_read_info(reg_info, nr_reg);
-			show_regulator_info(reg_info, nr_reg,
-					    options->verbose);
-		}
+		if (options->selectedwindow == REGULATOR)
+			regulator_display();
 
 		if (options->selectedwindow == CLOCK) {
 
@@ -315,13 +326,10 @@  int mainloop(struct powerdebug_options *options,
 	return 0;
 }
 
-static int powerdebug_dump(struct powerdebug_options *options,
-			   struct regulator_info *reg_info, int nr_reg)
+static int powerdebug_dump(struct powerdebug_options *options)
 {
-	if (options->regulators) {
-		regulator_read_info(reg_info, nr_reg);
-		regulator_print_info(reg_info, nr_reg, options->verbose);
-	}
+	if (options->regulators)
+		regulator_dump();
 
 	if (options->clocks)
 		read_and_dump_clock_info(options->clkname);
@@ -332,15 +340,14 @@  static int powerdebug_dump(struct powerdebug_options *options,
 	return 0;
 }
 
-static int powerdebug_display(struct powerdebug_options *options,
-			      struct regulator_info *reg_info, int nr_reg)
+static int powerdebug_display(struct powerdebug_options *options)
 {
 	if (display_init()) {
 		printf("failed to initialize display\n");
 		return -1;
 	}
 
-	if (mainloop(options, reg_info, nr_reg))
+	if (mainloop(options))
 		return -1;
 
 	return 0;
@@ -362,8 +369,7 @@  static struct powerdebug_options *powerdebug_init(void)
 int main(int argc, char **argv)
 {
 	struct powerdebug_options *options;
-	struct regulator_info *regulators_info;
-	int numregulators, ret;
+	int ret;
 
 	options = powerdebug_init();
 	if (!options) {
@@ -376,8 +382,7 @@  int main(int argc, char **argv)
 		return 1;
 	}
 
-	regulators_info = regulator_init(&numregulators);
-	if (!regulators_info) {
+	if (regulator_init()) {
 		printf("not enough memory to allocate regulators info\n");
 		options->regulators = false;
 	}
@@ -387,9 +392,8 @@  int main(int argc, char **argv)
 		options->clocks = false;
 	}
 
-	ret = options->dump ?
-		powerdebug_dump(options, regulators_info, numregulators) :
-		powerdebug_display(options, regulators_info, numregulators);
+	ret = options->dump ? powerdebug_dump(options) :
+		powerdebug_display(options);
 
 	return ret < 0;
 }
diff --git a/powerdebug.h b/powerdebug.h
index 8fd2775..ab1e6f0 100644
--- a/powerdebug.h
+++ b/powerdebug.h
@@ -57,6 +57,4 @@  extern void show_header(int selectedwindow);
 extern void create_windows(int selectedwindow);
 extern void create_selectedwindow(int selectedwindow);
 
-struct regulator_info;
-extern void show_regulator_info(struct regulator_info *reg_info,
-				int nr_reg, int verbose);
+extern int regulator_display(void);
diff --git a/regulator.c b/regulator.c
index 60529ed..d4b41e1 100644
--- a/regulator.c
+++ b/regulator.c
@@ -11,197 +11,209 @@ 
  * 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"
 
 #define SYSFS_REGULATOR "/sys/class/regulator"
-
-struct regulator_info *regulator_init(int *nr_regulators)
+#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 "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;
+	struct regulator_info *regi;
 
-	*nr_regulators = 0;
+	regi = malloc(sizeof(*regi));
+	if (regi)
+		memset(regi, 0, sizeof(*regi));
 
-	regdir = opendir(SYSFS_REGULATOR);
-	if (!regdir) {
-		fprintf(stderr, "failed to open '%s': %m\n", SYSFS_REGULATOR);
-		return NULL;
-	}
+	return regi;
+}
 
-	while ((item = readdir(regdir))) {
+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 (!strcmp(item->d_name, "."))
-			continue;
+	if (!strncmp("regulator.", tree->name, strlen("regulator.")))
+		printf("\n%s:\n", tree->name);
 
-		if (!strcmp(item->d_name, ".."))
+	for (i = 0; i < nregdata; i++) {
+
+		if (file_read_value(tree->path, regdata[i].name,
+				    regdata[i].ifmt, buffer))
 			continue;
 
-		(*nr_regulators)++;
+		printf(regdata[i].ofmt, regdata[i].derefme ?
+		       *((int *)buffer) : buffer);
 	}
 
-	closedir(regdir);
+	return 0;
+}
 
-	return malloc(*nr_regulators * sizeof(struct regulator_info));
+int regulator_dump(void)
+{
+	printf("\nRegulator Information:\n");
+	printf("*********************\n\n");
+
+	return tree_for_each(reg_tree, regulator_dump_cb, NULL);
 }
 
-static void print_string_val(char *name, char *val)
+static int regulator_display_cb(struct tree *t, void *data)
 {
-	printf("\t%s=%s", name, val);
-	if (!strchr(val, '\n'))
-		printf("\n");
+	struct regulator_info *reg = t->private;
+	int *line = data;
+	char *buf;
+
+        /* we skip the root node of the tree */
+	if (!t->parent)
+		return 0;
+
+	if (!strlen(reg->name))
+		return 0;
+
+	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;
+
+	display_print_line(REGULATOR, *line, buf, reg->num_users, t);
+
+	(*line)++;
+
+	free(buf);
+
+	return 0;
 }
 
-void regulator_print_info(struct regulator_info *reg_info, int nr_reg, int verbose)
+int regulator_display(void)
 {
-	int i;
+	int ret, line = 0;
 
-	printf("\nRegulator Information:\n");
-	printf("*********************\n\n");
+	display_reset_cursor(REGULATOR);
 
-	for (i = 0; i < nr_reg; i++) {
-		printf("Regulator %d:\n", i + 1);
-		print_string_val("name", reg_info[i].name);
-		if (strcmp(reg_info[i].status, ""))
-			print_string_val("status", reg_info[i].status);
-		if (strcmp(reg_info[i].state, ""))
-			print_string_val("state", reg_info[i].state);
+	print_regulator_header();
 
-		if (!verbose)
-			continue;
+	ret = tree_for_each(reg_tree, regulator_display_cb, &line);
 
-		if (strcmp(reg_info[i].type, ""))
-			print_string_val("type", reg_info[i].type);
-		if (strcmp(reg_info[i].opmode, ""))
-			print_string_val("opmode", reg_info[i].opmode);
-
-		if (reg_info[i].microvolts)
-			printf("\tmicrovolts=%d\n",
-				reg_info[i].microvolts);
-		if (reg_info[i].min_microvolts)
-			printf("\tmin_microvolts=%d\n",
-				reg_info[i].min_microvolts);
-		if (reg_info[i].max_microvolts)
-			printf("\tmax_microvolts=%d\n",
-				reg_info[i].max_microvolts);
-
-		if (reg_info[i].microamps)
-			printf("\tmicroamps=%d\n",
-				reg_info[i].microamps);
-		if (reg_info[i].min_microamps)
-			printf("\tmin_microamps=%d\n",
-				reg_info[i].min_microamps);
-		if (reg_info[i].max_microamps)
-			printf("\tmax_microamps=%d\n",
-				reg_info[i].max_microamps);
-		if (reg_info[i].requested_microamps)
-			printf("\trequested_microamps=%d\n",
-				reg_info[i].requested_microamps);
-
-		if (reg_info[i].num_users)
-			printf("\tnum_users=%d\n",
-				reg_info[i].num_users);
-		printf("\n");
-	}
+	display_refresh_pad(REGULATOR);
 
-	if (!nr_reg && verbose) {
-		printf("Could not find regulator information!");
-		printf(" Looks like %s is empty.\n\n", SYSFS_REGULATOR);
-	}
+	return ret;
+}
 
-	printf("\n\n");
+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 void read_info_from_dirent(struct regulator_info *reg_info,
-				  struct dirent *ritem, char *str, int idx)
+static inline int read_regulator_cb(struct tree *t, void *data)
 {
-	if (!strcmp(ritem->d_name, "name"))
-		strcpy(reg_info[idx].name, str);
-	if (!strcmp(ritem->d_name, "state"))
-		strcpy(reg_info[idx].state, str);
-	if (!strcmp(ritem->d_name, "status"))
-		strcpy(reg_info[idx].status, str);
-
-	if (!strcmp(ritem->d_name, "type"))
-		strcpy(reg_info[idx].type, str);
-	if (!strcmp(ritem->d_name, "opmode"))
-		strcpy(reg_info[idx].opmode, str);
-
-	if (!strcmp(ritem->d_name, "microvolts"))
-		reg_info[idx].microvolts = atoi(str);
-	if (!strcmp(ritem->d_name, "min_microvolts"))
-		reg_info[idx].min_microvolts = atoi(str);
-	if (!strcmp(ritem->d_name, "max_microvolts"))
-		reg_info[idx].max_microvolts = atoi(str);
-
-	if (!strcmp(ritem->d_name, "microamps"))
-		reg_info[idx].microamps = atoi(str);
-	if (!strcmp(ritem->d_name, "min_microamps"))
-		reg_info[idx].min_microamps = atoi(str);
-	if (!strcmp(ritem->d_name, "max_microamps"))
-		reg_info[idx].max_microamps = atoi(str);
-	if (!strcmp(ritem->d_name, "requested_microamps"))
-		reg_info[idx].requested_microamps = atoi(str);
-
-	if (!strcmp(ritem->d_name, "num_users"))
-		reg_info[idx].num_users = atoi(str);
+	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", &reg->num_users);
+	file_read_value(t->path, "microvolts", "%d", &reg->microvolts);
+	file_read_value(t->path, "min_microvolts", "%d", &reg->min_microvolts);
+	file_read_value(t->path, "max_microvolts", "%d", &reg->max_microvolts);
+	file_read_value(t->path, "microamps", "%d", &reg->microamps);
+	file_read_value(t->path, "min_microamps", "%d", &reg->min_microamps);
+	file_read_value(t->path, "max_microamps", "%d", &reg->max_microamps);
+
+	return 0;
 }
 
-int regulator_read_info(struct regulator_info *reg_info, int nr_reg)
+static int fill_regulator_cb(struct tree *t, void *data)
 {
-	FILE *file = NULL;
-	DIR *regdir, *dir;
-	int len, count = 0, ret = 0;
-	char line[1024], filename[1024], *fptr;
-	struct dirent *item, *ritem;
-
-	regdir = opendir(SYSFS_REGULATOR);
-	if (!regdir)
-		return(1);
-	while ((item = readdir(regdir))) {
-		if (strlen(item->d_name) < 3)
-			continue;
+	struct regulator_info *reg;
 
-		if (strncmp(item->d_name, "regulator", 9))
-			continue;
+	reg = regulator_alloc();
+	if (!reg)
+		return -1;
+	t->private = reg;
 
-		len = sprintf(filename, "%s/%s", SYSFS_REGULATOR, item->d_name);
+        /* we skip the root node but we set it expanded for its children */
+	if (!t->parent)
+		return 0;
 
-		dir = opendir(filename);
-		if (!dir)
-			continue;
-		count++;
-
-		if (count > nr_reg) {
-			ret = 1;
-			goto exit;
-		}
-
-		strcpy(reg_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(reg_info, ritem,
-					      fptr, count - 1);
-		}
-	exit:
-		closedir(dir);
-		if (ret)
-			break;
-	}
-	closedir(regdir);
+	return read_regulator_cb(t, data);
+}
 
-	return ret;
+static int fill_regulator_tree(void)
+{
+	return tree_for_each(reg_tree, fill_regulator_cb, NULL);
+}
+
+int regulator_init(void)
+{
+	reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb);
+	if (!reg_tree)
+		return -1;
+
+	return fill_regulator_tree();
 }
diff --git a/regulator.h b/regulator.h
index 1633cfd..5f8c473 100644
--- a/regulator.h
+++ b/regulator.h
@@ -13,32 +13,7 @@ 
  *       - initial API and implementation
  *******************************************************************************/
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-#include <getopt.h>
-
 #define VALUE_MAX 16
 
-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;
-};
-
-extern struct regulator_info *regulator_init(int *nr_regulators);
-extern int regulator_read_info(struct regulator_info *reg_info, int nr_reg);
-extern void regulator_print_info(struct regulator_info *reg_info,
-				 int nr_reg, int verbose);
+extern int regulator_init(void);
+extern int regulator_dump(void);