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