Fix display error on screen

The previous patch was reverted and is replaced by this one.

Instead of dancing around with global flag telling if a subsys succeed
or not and write a error, let's try to initialize the subsystem each
time a display is requested and output an error occurs.

That makes the code a bit nicer and give the opportunity to fix the
problem at the system level (eg. mount debugfs) without restarting
powerdebug.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
diff --git a/clocks.c b/clocks.c
index b57de3d..c115d8e 100644
--- a/clocks.c
+++ b/clocks.c
@@ -360,6 +360,39 @@
 	return 0;
 }
 
+static int clock_info_load(void)
+{
+        char clk_dir_path[MAX+1][PATH_MAX];
+
+	if (clock_tree) 
+		return 0;
+
+        if (locate_debugfs(clk_dir_path[CCF]) || locate_debugfs(clk_dir_path[OCF]))
+                return -1;
+
+        sprintf(clk_dir_path[CCF], "%s/clk", clk_dir_path[CCF]);
+        sprintf(clk_dir_path[OCF], "%s/clock", clk_dir_path[OCF]);
+        if (!access(clk_dir_path[CCF], F_OK)) {
+                clock_fw = CCF;
+                strcpy(clk_dir_path[MAX],clk_dir_path[CCF]);
+        }
+        else if(!access(clk_dir_path[OCF], F_OK)) {
+                clock_fw = OCF;
+                strcpy(clk_dir_path[MAX],clk_dir_path[OCF]);
+        }
+        else
+                return -1;
+
+        clock_tree = tree_load(clk_dir_path[MAX], NULL, false);
+        if (!clock_tree)
+                return -1;
+
+        if (fill_clock_tree())
+                return -1;
+
+	return 0;
+}
+
 /*
  * Read the clock information and fill the tree with the information
  * found in the files. Then print the result to the text based interface
@@ -367,6 +400,12 @@
  */
 static int clock_display(bool refresh)
 {
+	if (clock_info_load()) {
+                display_print_error(CLOCK, 0, "Failed to read clock info");
+                return 0; /* we don't want this to be a critical error */
+	}
+
+
 	if (refresh && read_clock_info(clock_tree))
 		return -1;
 
@@ -449,33 +488,8 @@
  */
 int clock_init(struct powerdebug_options *options)
 {
-	char clk_dir_path[MAX+1][PATH_MAX];
-
 	if (!(options->flags & CLOCK_OPTION))
 		return 0;
 
-	if (locate_debugfs(clk_dir_path[CCF]) || locate_debugfs(clk_dir_path[OCF]))
-		return -1;
-
-	sprintf(clk_dir_path[CCF], "%s/clk", clk_dir_path[CCF]);
-	sprintf(clk_dir_path[OCF], "%s/clock", clk_dir_path[OCF]);
-	if (!access(clk_dir_path[CCF], F_OK)) {
-		clock_fw = CCF;
-		strcpy(clk_dir_path[MAX],clk_dir_path[CCF]);
-	}
-	else if(!access(clk_dir_path[OCF], F_OK)) {
-		clock_fw = OCF;
-		strcpy(clk_dir_path[MAX],clk_dir_path[OCF]);
-	}
-	else
-		return -1;
-
-	clock_tree = tree_load(clk_dir_path[MAX], NULL, false);
-	if (!clock_tree)
-		return -1;
-
-	if (fill_clock_tree())
-		return -1;
-
 	return display_register(CLOCK, &clock_ops);
 }
diff --git a/display.c b/display.c
index 8f44334..e34d083 100644
--- a/display.c
+++ b/display.c
@@ -303,6 +303,15 @@
 	return 0;
 }
 
+int display_print_error(int window, int line, char *str)
+{
+	display_reset_cursor(window);
+	display_print_line(window, line, str, 0, NULL);
+	display_refresh_pad(window);
+
+	return 0;
+}
+
 static int display_find_keystroke(int fd, void *data);
 
 struct find_data {
diff --git a/display.h b/display.h
index 46095cb..6083c53 100644
--- a/display.h
+++ b/display.h
@@ -34,6 +34,8 @@
 extern int display_print_line(int window, int line, char *str,
 			      int bold, void *data);
 
+extern int display_print_error(int window, int line, char *str);
+
 extern int display_refresh_pad(int window);
 extern int display_reset_cursor(int window);
 extern void *display_get_row_data(int window);
diff --git a/gpio.c b/gpio.c
index 7024347..d7df0e3 100644
--- a/gpio.c
+++ b/gpio.c
@@ -262,8 +262,76 @@
 	return ret;
 }
 
+void export_free_gpios(void)
+{
+	FILE *fgpio, *fgpio_export;
+	int i, gpio_max = 0;
+	char *line = NULL;
+	ssize_t nrread;
+	size_t len = 0;
+
+	fgpio = fopen("/sys/kernel/debug/gpio", "r");
+	if (!fgpio) {
+		printf("failed to read debugfs gpio file\n");
+		return;
+	}
+
+	fgpio_export = fopen("/sys/class/gpio/export", "w");
+	if (!fgpio_export) {
+		printf("failed to write open gpio-export file\n");
+		goto out;
+	}
+
+	/* export the gpios */
+	while ((nrread = getline(&line, &len, fgpio)) != -1) {
+		if (strstr(line, "GPIOs"))
+			sscanf(line, "%*[^-]-%d", &gpio_max);
+	}
+
+	printf("log: total gpios = %d\n", gpio_max);
+	for (i = 0 ; i <= gpio_max ; i++) {
+		char command[50] = "";
+
+		sprintf(command, "echo %d > /sys/class/gpio/export", i);
+		if (system(command) < 0)
+			printf("error: failed to export gpio-%d\n", i);
+	}
+
+	free(line);
+
+	if (fgpio)
+		fclose(fgpio);
+out:
+	if (fgpio_export)
+		fclose(fgpio_export);
+
+	return;
+}
+
+static int gpio_load_info(void)
+{
+	if (gpio_tree)
+		return 0;
+
+	export_free_gpios();
+
+	gpio_tree = tree_load(SYSFS_GPIO, gpio_filter_cb, false);
+	if (!gpio_tree)
+		return -1;
+
+	if (fill_gpio_tree())
+		return -1;
+
+	return 0;
+}
+
 static int gpio_display(bool refresh)
 {
+	if (gpio_load_info()) {
+                display_print_error(GPIO, 0, "Failed to read gpio info");
+                return 0; /* we don't want this to be a critical error */
+	}
+
 	if (refresh && read_gpio_info(gpio_tree))
 		return -1;
 
@@ -320,52 +388,6 @@
 	.change = gpio_change,
 };
 
-void export_free_gpios(void)
-{
-	FILE *fgpio, *fgpio_export;
-	int i, gpio_max = 0;
-	char *line = NULL;
-	ssize_t nrread;
-	size_t len = 0;
-
-	fgpio = fopen("/sys/kernel/debug/gpio", "r");
-	if (!fgpio) {
-		printf("failed to read debugfs gpio file\n");
-		return;
-	}
-
-	fgpio_export = fopen("/sys/class/gpio/export", "w");
-	if (!fgpio_export) {
-		printf("failed to write open gpio-export file\n");
-		goto out;
-	}
-
-	/* export the gpios */
-	while ((nrread = getline(&line, &len, fgpio)) != -1) {
-		if (strstr(line, "GPIOs"))
-			sscanf(line, "%*[^-]-%d", &gpio_max);
-	}
-
-	printf("log: total gpios = %d\n", gpio_max);
-	for (i = 0 ; i <= gpio_max ; i++) {
-		char command[50] = "";
-
-		sprintf(command, "echo %d > /sys/class/gpio/export", i);
-		if (system(command) < 0)
-			printf("error: failed to export gpio-%d\n", i);
-	}
-
-	free(line);
-
-	if (fgpio)
-		fclose(fgpio);
-out:
-	if (fgpio_export)
-		fclose(fgpio_export);
-
-	return;
-}
-
 /*
  * Initialize the gpio framework
  */
@@ -374,14 +396,5 @@
 	if (!(options->flags & GPIO_OPTION))
 		return 0;
 
-	export_free_gpios();
-
-	gpio_tree = tree_load(SYSFS_GPIO, gpio_filter_cb, false);
-	if (!gpio_tree)
-		return -1;
-
-	if (fill_gpio_tree())
-		return -1;
-
 	return display_register(GPIO, &gpio_ops);
 }
diff --git a/regulator.c b/regulator.c
index 1f7aefd..5fba6f1 100644
--- a/regulator.c
+++ b/regulator.c
@@ -223,14 +223,6 @@
 	return ret;
 }
 
-static int regulator_display(bool refresh)
-{
-	if (refresh && read_regulator_info(reg_tree))
-		return -1;
-
-	return regulator_print_info(reg_tree);
-}
-
 static int fill_regulator_cb(struct tree *t, void *data)
 {
 	struct regulator_info *reg;
@@ -254,6 +246,34 @@
 	return tree_for_each(reg_tree, fill_regulator_cb, NULL);
 }
 
+static int regulator_info_load(void)
+{
+	if (reg_tree)
+		return 0;
+
+	reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb, false);
+	if (!reg_tree)
+		return -1;
+        
+	if (fill_regulator_tree())
+		return -1;
+
+	return 0;
+}
+
+static int regulator_display(bool refresh)
+{
+	if (regulator_info_load()) {
+		display_print_error(REGULATOR, 0, "Failed to read regulator info");
+		return 0; /* we don't want this to be a critical error */
+	}
+
+        if (refresh && read_regulator_info(reg_tree))
+                return -1;
+
+        return regulator_print_info(reg_tree);
+}
+
 static struct display_ops regulator_ops = {
 	.display = regulator_display,
 };
@@ -263,12 +283,5 @@
 	if (!(options->flags & REGULATOR_OPTION))
 		return 0;
 
-	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, &regulator_ops);
 }
diff --git a/sensor.c b/sensor.c
index fd8100e..cdc86b2 100644
--- a/sensor.c
+++ b/sensor.c
@@ -276,9 +276,29 @@
 	return ret;
 }
 
+static int sensor_load_info(void)
+{
+        if (sensor_tree)
+		return 0;
+
+	sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb, false);
+        if (!sensor_tree)
+		return -1;
+
+	if (fill_sensor_tree())
+		return -1;
+
+	return 0;
+}
+
 static int sensor_display(bool refresh)
 {
-	if (refresh && read_sensor_info(sensor_tree))
+	if (sensor_load_info()) {
+		display_print_error(SENSOR, 0, "Failed to read sensor info");
+		return 0;
+	}
+
+	if (refresh && read_sensor_info(sensor_tree)) 
 		return -1;
 
 	return sensor_print_info(sensor_tree);
@@ -293,12 +313,5 @@
 	if (!(options->flags & SENSOR_OPTION))
 		return 0;
 
-	sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb, false);
-	if (!sensor_tree)
-		return -1;
-
-	if (fill_sensor_tree())
-		return -1;
-
 	return display_register(SENSOR, &sensor_ops);
 }
diff --git a/tree.c b/tree.c
index 2728a2d..76f132f 100644
--- a/tree.c
+++ b/tree.c
@@ -127,10 +127,8 @@
 	int ret = 0;
 
 	dir = opendir(tree->path);
-	if (!dir) {
-		printf("error: unable to open directory %s\n", tree->path);
+	if (!dir) 
 		return -1;
-	}
 
 	while (!readdir_r(dir, &dirent, &direntp)) {