aboutsummaryrefslogtreecommitdiff
path: root/sensor.c
diff options
context:
space:
mode:
Diffstat (limited to 'sensor.c')
-rw-r--r--sensor.c327
1 files changed, 220 insertions, 107 deletions
diff --git a/sensor.c b/sensor.c
index f5fcd40..bd8c354 100644
--- a/sensor.c
+++ b/sensor.c
@@ -13,157 +13,270 @@
* - initial API and implementation
*******************************************************************************/
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#include <sys/types.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+
#include "powerdebug.h"
+#include "display.h"
#include "sensor.h"
+#include "tree.h"
+#include "utils.h"
+
+#define SYSFS_SENSOR "/sys/class/hwmon"
+
+static struct tree *sensor_tree;
+
+struct temp_info {
+ char name[NAME_MAX];
+ int temp;
+};
+
+struct fan_info {
+ char name[NAME_MAX];
+ int rpms;
+};
-char *get_num(char *fname, char *sensor)
+struct sensor_info {
+ char name[NAME_MAX];
+ struct temp_info *temperatures;
+ struct fan_info *fans;
+ short nrtemps;
+ short nrfans;
+};
+
+static int sensor_dump_cb(struct tree *tree, void *data)
{
- char tmpstr[NAME_MAX];
- char *str;
+ int i;
+ struct sensor_info *sensor = tree->private;
+
+ if (!strlen(sensor->name))
+ return 0;
+
+ printf("%s\n", sensor->name);
- strcpy(tmpstr, (fname+strlen(sensor)));
+ for (i = 0; i < sensor->nrtemps; i++)
+ printf(" %s %.1f °C/V\n", sensor->temperatures[i].name,
+ (float)sensor->temperatures[i].temp / 1000);
- str = strrchr(tmpstr, '_');
- str[0] = '\0';
+ for (i = 0; i < sensor->nrfans; i++)
+ printf(" %s %d rpm\n", sensor->fans[i].name,
+ sensor->fans[i].rpms);
- str = strdup(tmpstr);
- return str;
+ return 0;
}
-void get_sensor_info(char *path, char *fname, char *sensor, int verbose)
+int sensor_dump(void)
{
- FILE *filep;
- char filename[PATH_MAX];
- char **items = NULL, **suffix = NULL;
- char *item, result[NAME_MAX], *num;
- int ret, count = 0;
+ printf("\nSensor Information:\n");
+ printf("*******************\n\n");
- (void)verbose; // get rid of warning
+ return tree_for_each(sensor_tree, sensor_dump_cb, NULL);
+}
- sprintf(filename, "%s/%s", path, fname);
+static struct sensor_info *sensor_alloc(void)
+{
+ struct sensor_info *sensor;
- if (!strcmp(sensor, "in")) {
- items = (char **)items_in;
- suffix = (char **)suffix_in;
- }
+ sensor = malloc(sizeof(*sensor));
+ if (sensor)
+ memset(sensor, 0, sizeof(*sensor));
- if (!strcmp(sensor, "temp")) {
- items = (char **)items_temp;
- suffix = (char **)suffix_temp;
- }
+ return sensor;
+}
- if (!strcmp(sensor, "fan")) {
- items = (char **)items_fan;
- suffix = (char **)suffix_fan;
- }
- if (!strcmp(sensor, "pwm")) {
- items = (char **)items_pwm;
- suffix = (char **)suffix_pwm;
- }
+static int read_sensor_cb(struct tree *tree, void *data)
+{
+ DIR *dir;
+ int value;
+ struct dirent dirent, *direntp;
+ struct sensor_info *sensor = tree->private;
+
+ int nrtemps = 0;
+ int nrfans = 0;
+ dir = opendir(tree->path);
+ if (!dir)
+ return -1;
+
+ file_read_value(tree->path, "name", "%s", sensor->name);
+
+ while (!readdir_r(dir, &dirent, &direntp)) {
+
+ if (!direntp)
+ break;
+
+ if (direntp->d_type != DT_REG)
+ continue;
- if (!items || !suffix)
- return;
+ if (!strncmp(direntp->d_name, "temp", 4)) {
- item = strrchr(fname, '_');
- if (!item)
- return;
+ if (file_read_value(tree->path, direntp->d_name, "%d",
+ &value))
+ continue;
- if (item)
- item++;
+ sensor->temperatures =
+ realloc(sensor->temperatures,
+ sizeof(struct temp_info) * (nrtemps + 1));
+ if (!sensor->temperatures)
+ continue;
- if (item > (fname + strlen(fname)))
- return;
+ strcpy(sensor->temperatures[nrtemps].name,
+ direntp->d_name);
+ sensor->temperatures[nrtemps].temp = value;
- num = get_num(fname, sensor);
- filep = fopen(filename, "r");
+ nrtemps++;
+ }
- if (!filep)
- goto exit;
- ret = fscanf(filep, "%s", result);
- fclose(filep);
+ if (!strncmp(direntp->d_name, "fan", 3)) {
- if (ret != 1)
- goto exit;
+ if (file_read_value(tree->path, direntp->d_name, "%d",
+ &value))
+ continue;
- 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++;
+ sensor->fans =
+ realloc(sensor->fans,
+ sizeof(struct temp_info) * (nrfans + 1));
+ if (!sensor->fans)
+ continue;
+
+ strcpy(sensor->fans[nrfans].name,
+ direntp->d_name);
+ sensor->fans[nrfans].rpms = value;
+
+ nrfans++;
+ }
}
-exit:
- free(num);
- return;
+
+ sensor->nrtemps = nrtemps;
+ sensor->nrfans = nrfans;
+
+ closedir(dir);
+
+ return 0;
}
-int read_and_print_sensor_info(int verbose)
+static int fill_sensor_cb(struct tree *t, void *data)
{
- DIR *dir, *subdir;
- int len, found = 0;
- char filename[PATH_MAX], devpath[PATH_MAX];
- char device[PATH_MAX];
- struct dirent *item, *subitem;
+ struct sensor_info *sensor;
- printf("\nSensor Information:\n");
- printf("******************\n");
+ sensor = sensor_alloc();
+ if (!sensor)
+ return -1;
- sprintf(filename, "%s", "/sys/class/hwmon");
- dir = opendir(filename);
- if (!dir)
- return errno;
+ t->private = sensor;
- while ((item = readdir(dir))) {
- if (item->d_name[0] == '.') /* skip the hidden files */
- continue;
+ if (!t->parent)
+ return 0;
- found = 1;
+ return read_sensor_cb(t, data);
+}
- sprintf(filename, "/sys/class/hwmon/%s", item->d_name);
- sprintf(devpath, "%s/device", filename);
+static int fill_sensor_tree(void)
+{
+ return tree_for_each(sensor_tree, fill_sensor_cb, NULL);
+}
- len = readlink(devpath, device, PATH_MAX - 1);
+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 (len < 0)
- strcpy(devpath, filename);
- else
- device[len] = '\0';
+ if (!strcmp(name, "driver"))
+ return 1;
- subdir = opendir(devpath);
+ if (!strcmp(name, "hwmon"))
+ return 1;
- printf("\nSensor Information for %s :\n", item->d_name);
- fflush(stdin);
+ if (!strcmp(name, "power"))
+ return 1;
- while ((subitem = readdir(subdir))) {
- if (subitem->d_name[0] == '.') /* skip hidden files */
- continue;
+ return 0;
+}
- 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);
+static int sensor_display_cb(struct tree *t, void *data)
+{
+ struct sensor_info *sensor = t->private;
+ int *line = data;
+ char buf[1024];
+ int i;
- }
+ if (!strlen(sensor->name))
+ return 0;
- closedir(subdir);
- }
- closedir(dir);
+ sprintf(buf, "%s", sensor->name);
+ display_print_line(SENSOR, *line, buf, 1, t);
+
+ (*line)++;
- if (!found && verbose) {
- printf("Could not find sensor information!");
- printf(" Looks like /sys/class/hwmon is empty.\n");
+ for (i = 0; i < sensor->nrtemps; i++) {
+ sprintf(buf, " %-35s%.1f", sensor->temperatures[i].name,
+ (float)sensor->temperatures[i].temp / 1000);
+ display_print_line(SENSOR, *line, buf, 0, t);
+ (*line)++;
}
- printf("\n");
+ for (i = 0; i < sensor->nrfans; i++) {
+ sprintf(buf, " %-35s%d rpm", sensor->fans[i].name,
+ sensor->fans[i].rpms);
+ display_print_line(SENSOR, *line, buf, 0, t);
+ (*line)++;
+ }
return 0;
}
+
+static int sensor_print_header(void)
+{
+ char *buf;
+ int ret;
+
+ if (asprintf(&buf, "%-36s%s", "Name", "Value") < 0)
+ return -1;
+
+ ret = display_column_name(buf);
+
+ free(buf);
+
+ return ret;
+}
+
+static int sensor_display(bool refresh)
+{
+ int ret, line = 0;
+
+ display_reset_cursor(SENSOR);
+
+ sensor_print_header();
+
+ ret = tree_for_each(sensor_tree, sensor_display_cb, &line);
+
+ display_refresh_pad(SENSOR);
+
+ return ret;
+}
+
+static struct display_ops sensor_ops = {
+ .display = sensor_display,
+};
+
+int sensor_init(void)
+{
+ 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);
+}