From patchwork Wed Jun 15 13:50:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 1929 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 5C0CF24B35 for ; Wed, 15 Jun 2011 13:52:42 +0000 (UTC) Received: from mail-vw0-f52.google.com (mail-vw0-f52.google.com [209.85.212.52]) by fiordland.canonical.com (Postfix) with ESMTP id 15936A1897A for ; Wed, 15 Jun 2011 13:52:41 +0000 (UTC) Received: by mail-vw0-f52.google.com with SMTP id 16so416327vws.11 for ; Wed, 15 Jun 2011 06:52:41 -0700 (PDT) Received: by 10.52.98.97 with SMTP id eh1mr91503vdb.7.1308145961812; Wed, 15 Jun 2011 06:52:41 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.52.183.130 with SMTP id em2cs126633vdc; Wed, 15 Jun 2011 06:52:41 -0700 (PDT) Received: by 10.213.4.10 with SMTP id 10mr352513ebp.102.1308145958883; Wed, 15 Jun 2011 06:52:38 -0700 (PDT) Received: from smtp.smtpout.orange.fr (smtp05.smtpout.orange.fr [80.12.242.127]) by mx.google.com with ESMTP id c49si1380482wed.116.2011.06.15.06.52.37; Wed, 15 Jun 2011 06:52:37 -0700 (PDT) Received-SPF: neutral (google.com: 80.12.242.127 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) client-ip=80.12.242.127; Authentication-Results: mx.google.com; spf=neutral (google.com: 80.12.242.127 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) smtp.mail=daniel.lezcano@linaro.org Received: from monster.dhcp.lxc ([92.134.76.78]) by mwinf5d28 with ME id wDsa1g00D1hMfSL03DscBJ; Wed, 15 Jun 2011 15:52:37 +0200 From: Daniel Lezcano To: daniel.lezcano@linaro.org Cc: linaro-dev@lists.linaro.org, patches@linaro.org Subject: [powerdebug 04/22] Rewrite the sensor code with the tree Date: Wed, 15 Jun 2011 15:50:38 +0200 Message-Id: <1308145856-6112-4-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1308145856-6112-1-git-send-email-daniel.lezcano@linaro.org> References: <1308145856-6112-1-git-send-email-daniel.lezcano@linaro.org> Use the tree to build a sensor tree and make the code consistent with the other pm blocks. Signed-off-by: Daniel Lezcano --- 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(); +}