[powerdebug,04/22] Rewrite the sensor code with the tree

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

Commit Message

Daniel Lezcano June 15, 2011, 1:50 p.m.
Use the tree to build a sensor tree and make the code consistent
with the other pm blocks.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 powerdebug.c |    7 ++-
 powerdebug.h |    2 +-
 sensor.c     |  261 ++++++++++++++++++++++++++++++++--------------------------
 3 files changed, 150 insertions(+), 120 deletions(-)

Patch

diff --git a/powerdebug.c b/powerdebug.c
index a303757..641673b 100644
--- a/powerdebug.c
+++ b/powerdebug.c
@@ -335,7 +335,7 @@  static int powerdebug_dump(struct powerdebug_options *options)
 		read_and_dump_clock_info(options->clkname);
 
 	if (options->sensors)
-		read_and_print_sensor_info(options->verbose);
+		sensor_dump();
 
 	return 0;
 }
@@ -392,6 +392,11 @@  int main(int argc, char **argv)
 		options->clocks = false;
 	}
 
+	if (sensor_init()) {
+		printf("failed to initialize sensors\n");
+		options->sensors = false;
+	}
+
 	ret = options->dump ? powerdebug_dump(options) :
 		powerdebug_display(options);
 
diff --git a/powerdebug.h b/powerdebug.h
index ab1e6f0..7175839 100644
--- a/powerdebug.h
+++ b/powerdebug.h
@@ -49,7 +49,7 @@  extern int display_clock_select(int window, int line);
 extern int display_clock_unselect(int window, int line, bool bold);
 
 extern void get_sensor_info(char *path, char *name, char *sensor, int verbose);
-extern int  read_and_print_sensor_info(int verbose);
+extern int  sensor_dump(void);
 extern void print_sensor_header(void);
 
 extern void killall_windows(int all);
diff --git a/sensor.c b/sensor.c
index df07593..f386f0c 100644
--- a/sensor.c
+++ b/sensor.c
@@ -15,164 +15,189 @@ 
 
 #include "powerdebug.h"
 #include "sensor.h"
+#include "tree.h"
+#include "utils.h"
 
-static char *items_temp[32] = {"min", "max", "input", "label", ""};
-static char *suffix_temp[32] = {"°C", "°C", "°C", "", ""};
-static char *items_in[32] = {"min", "max", "input", "label", ""};
-static char *suffix_in[32] = {"Volts", "Volts", "Volts", "", ""};
-static char *items_fan[32] = {"min", "max", "input", "label", "div", "target", ""};
-static char *suffix_fan[32] = {"RPM", "RPM", "RPM", "", "", "RPM", ""};
-static char *items_pwm[32] = {"freq", "enable", "mode", ""};
-static char *suffix_pwm[32] = {"Hz", "", "", ""};
+#define SYSFS_SENSOR "/sys/class/hwmon"
 
-char *get_num(char *fname, char *sensor)
-{
-	char tmpstr[NAME_MAX];
-	char *str;
+static struct tree *sensor_tree;
 
-	strcpy(tmpstr, (fname+strlen(sensor)));
+struct temp_info {
+	char name[NAME_MAX];
+	int temp;
+};
 
-	str = strrchr(tmpstr, '_');
-	str[0] = '\0';
+struct fan_info {
+	char name[NAME_MAX];
+	int rpms;
+};
 
-	str = strdup(tmpstr);
-	return str;
-}
+struct sensor_info {
+	char name[NAME_MAX];
+	struct temp_info *temperatures;
+	struct fan_info *fans;
+	short nrtemps;
+	short nrfans;
+};
 
-void get_sensor_info(char *path, char *fname, char *sensor, int verbose)
+static int sensor_dump_cb(struct tree *tree, void *data)
 {
-	FILE *filep;
-	char filename[PATH_MAX];
-	char **items = NULL, **suffix = NULL;
-	char *item, result[NAME_MAX], *num;
-	int ret, count = 0;
+	int i;
+	struct sensor_info *sensor = tree->private;
 
-	(void)verbose; // get rid of warning
+	if (!strlen(sensor->name))
+		return 0;
 
-	sprintf(filename, "%s/%s", path, fname);
+	printf("%s\n", sensor->name);
 
-	if (!strcmp(sensor, "in")) {
-		items = (char **)items_in;
-		suffix = (char **)suffix_in;
-	}
+	for (i = 0; i < sensor->nrtemps; i++)
+		printf(" %s %.1f °C\n", sensor->temperatures[i].name,
+		       (float)sensor->temperatures[i].temp / 1000);
 
-	if (!strcmp(sensor, "temp")) {
-		items = (char **)items_temp;
-		suffix = (char **)suffix_temp;
-	}
-
-	if (!strcmp(sensor, "fan")) {
-		items = (char **)items_fan;
-		suffix = (char **)suffix_fan;
-	}
-	if (!strcmp(sensor, "pwm")) {
-		items = (char **)items_pwm;
-		suffix = (char **)suffix_pwm;
-	}
+	for (i = 0; i < sensor->nrfans; i++)
+		printf(" %s %d rpm\n", sensor->fans[i].name,
+		       sensor->fans[i].rpms);
 
+	return 0;
+}
 
-	if (!items || !suffix)
-		return;
-
-	item = strrchr(fname, '_');
-	if (!item)
-		return;
-
-	if (item)
-		item++;
-
-	if (item > (fname + strlen(fname)))
-		return;
+int sensor_dump(void)
+{
+	printf("\nSensor Information:\n");
+	printf("*******************\n\n");
 
-	num = get_num(fname, sensor);
-	filep = fopen(filename, "r");
+	return tree_for_each(sensor_tree, sensor_dump_cb, NULL);
+}
 
-	if (!filep)
-		goto exit;
-	ret = fscanf(filep, "%s", result);
-	fclose(filep);
+static struct sensor_info *sensor_alloc(void)
+{
+	struct sensor_info *sensor;
 
-	if (ret != 1)
-		goto exit;
+	sensor = malloc(sizeof(*sensor));
+	if (sensor)
+		memset(sensor, 0, sizeof(*sensor));
 
-	while (strcmp(items[count], "")) {
-		if (!strcmp(items[count], item))
-			printf("\'temp\' %s sensor %s\t\t%d%s\n",
-				num, items[count], atoi(result)/1000,
-				suffix[count]);
-		count++;
-	}
-exit:
-	free(num);
-	return;
+	return sensor;
 }
 
-int read_and_print_sensor_info(int verbose)
+static int read_sensor_cb(struct tree *tree, void *data)
 {
-	DIR *dir, *subdir;
-	int len, found = 0;
-	char filename[PATH_MAX], devpath[PATH_MAX];
-	char device[PATH_MAX];
-	struct dirent *item, *subitem;
+	DIR *dir;
+	int value;
+        struct dirent dirent, *direntp;
+	struct sensor_info *sensor = tree->private;
 
-	printf("\nSensor Information:\n");
-	printf("******************\n");
+	int nrtemps = 0;
+	int nrfans = 0;
 
-	sprintf(filename, "%s", "/sys/class/hwmon");
-	dir = opendir(filename);
+	dir = opendir(tree->path);
 	if (!dir)
-		return errno;
+		return -1;
+
+	file_read_value(tree->path, "name", "%s", sensor->name);
 
-	while ((item = readdir(dir))) {
-		if (item->d_name[0] == '.')  /* skip the hidden files */
+	while (!readdir_r(dir, &dirent, &direntp)) {
+
+                if (!direntp)
+                        break;
+
+		if (direntp->d_type != DT_REG)
 			continue;
 
-		found = 1;
+		if (!strncmp(direntp->d_name, "temp", 4)) {
+
+			if (file_read_value(tree->path, direntp->d_name, "%d",
+					    &value))
+				continue;
 
-		sprintf(filename, "/sys/class/hwmon/%s", item->d_name);
-		sprintf(devpath, "%s/device", filename);
+			sensor->temperatures =
+				realloc(sensor->temperatures,
+					sizeof(struct temp_info) * (nrtemps + 1));
+			if (!sensor->temperatures)
+				continue;
 
-		len = readlink(devpath, device, PATH_MAX - 1);
+			strcpy(sensor->temperatures[nrtemps].name,
+			       direntp->d_name);
+			sensor->temperatures[nrtemps].temp = value;
 
-		if (len < 0)
-			strcpy(devpath, filename);
-		else
-			device[len] = '\0';
+			nrtemps++;
+		}
 
-		subdir = opendir(devpath);
+		if (!strncmp(direntp->d_name, "fan", 3)) {
 
-		printf("\nSensor Information for %s :\n", item->d_name);
-		fflush(stdin);
+			if (file_read_value(tree->path, direntp->d_name, "%d",
+					    &value))
+				continue;
 
-		while ((subitem = readdir(subdir))) {
-			if (subitem->d_name[0] == '.') /* skip hidden files */
+			sensor->fans =
+				realloc(sensor->fans,
+					sizeof(struct temp_info) * (nrfans + 1));
+			if (!sensor->fans)
 				continue;
 
-			if (!strncmp(subitem->d_name, "in", 2))
-				get_sensor_info(devpath, subitem->d_name, "in",
-						verbose);
-			else if (!strncmp(subitem->d_name, "temp", 4))
-				get_sensor_info(devpath, subitem->d_name,
-						"temp", verbose);
-			else if (!strncmp(subitem->d_name, "fan", 4))
-				get_sensor_info(devpath, subitem->d_name,
-						"fan", verbose);
-			else if (!strncmp(subitem->d_name, "pwm", 4))
-				get_sensor_info(devpath, subitem->d_name,
-						"pwm", verbose);
+			strcpy(sensor->fans[nrfans].name,
+			       direntp->d_name);
+			sensor->fans[nrfans].rpms = value;
 
+			nrfans++;
 		}
-
-		closedir(subdir);
 	}
+
+	sensor->nrtemps = nrtemps;
+	sensor->nrfans = nrfans;
+
 	closedir(dir);
 
-	if (!found && verbose) {
-		printf("Could not find sensor information!");
-		printf(" Looks like /sys/class/hwmon is empty.\n");
-	}
+	return 0;
+}
 
-	printf("\n");
+static int fill_sensor_cb(struct tree *t, void *data)
+{
+	struct sensor_info *sensor;
+
+	sensor = sensor_alloc();
+	if (!sensor)
+		return -1;
+
+	t->private = sensor;
+
+	if (!t->parent)
+		return 0;
+
+	return read_sensor_cb(t, data);
+}
+
+static int fill_sensor_tree(void)
+{
+	return tree_for_each(sensor_tree, fill_sensor_cb, NULL);
+}
+
+static int sensor_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, "subsystem"))
+		return 1;
+
+	if (!strcmp(name, "driver"))
+		return 1;
+
+	if (!strcmp(name, "hwmon"))
+		return 1;
+
+	if (!strcmp(name, "power"))
+		return 1;
 
 	return 0;
 }
+
+int sensor_init(void)
+{
+	sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb);
+	if (!sensor_tree)
+		return -1;
+
+	return fill_sensor_tree();
+}