@@ -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);
@@ -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);
@@ -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();
+}
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(-)