From bb840c486cf096093beb48d4060609b08a34f289 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 17 Apr 2008 01:27:22 +0000 Subject: [PATCH] Subject: [PATCH 1/3 v3] libsensors: Support energy and power meters Add power and sensor meters to libsensors, with minor tweaks and documentation updates as suggested by Jean Delvare. Signed-off-by: Darrick J. Wong git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@5183 7894878c-1315-0410-8ee3-d5d059ff63e0 --- CHANGES | 1 + doc/libsensors-API.txt | 10 ++++++++ lib/sensors.h | 10 ++++++++ lib/sysfs.c | 57 ++++++++++++++++++++++++++++++++---------- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 3be60a30..8235d3be 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ SVN-HEAD Parse the configuration file in C locale Late compute statements override early ones Support virtual hwmon devices (#2309) + Support power and energy sensors pwmconfig: Don't create the configuration file before it's needed Don't preserve configuration file customizations Fix permissions of the configuration file diff --git a/doc/libsensors-API.txt b/doc/libsensors-API.txt index 49da35e5..a1a6f3c1 100644 --- a/doc/libsensors-API.txt +++ b/doc/libsensors-API.txt @@ -6,6 +6,16 @@ over time. This document summarizes these evolutions so that application authors can quickly figure out how to test for the availability of a given new feature. +0x402 lm-sensors SVN +* Added support for power and energy sensors +SENSORS_FEATURE_POWER = 3 +SENSORS_FEATURE_ENERGY = 4 +SENSORS_SUBFEATURE_POWER_AVERAGE +SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST +SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST +SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL +SENSORS_SUBFEATURE_ENERGY_INPUT + 0x401 lm-sensors SVN * Added bus type "virtual": #define SENSORS_BUS_TYPE_VIRTUAL 4 diff --git a/lib/sensors.h b/lib/sensors.h index 7fb0d809..2375753a 100644 --- a/lib/sensors.h +++ b/lib/sensors.h @@ -132,6 +132,8 @@ typedef enum sensors_feature_type { SENSORS_FEATURE_IN = 0x00, SENSORS_FEATURE_FAN = 0x01, SENSORS_FEATURE_TEMP = 0x02, + SENSORS_FEATURE_POWER = 0x03, + SENSORS_FEATURE_ENERGY = 0x04, SENSORS_FEATURE_VID = 0x10, SENSORS_FEATURE_BEEP_ENABLE = 0x18, SENSORS_FEATURE_UNKNOWN = INT_MAX, @@ -170,6 +172,14 @@ typedef enum sensors_subfeature_type { SENSORS_SUBFEATURE_TEMP_OFFSET, SENSORS_SUBFEATURE_TEMP_BEEP, + SENSORS_SUBFEATURE_POWER_AVERAGE = SENSORS_FEATURE_POWER << 8, + SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, + SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, + + SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL = (SENSORS_FEATURE_POWER << 8) | 0x80, + + SENSORS_SUBFEATURE_ENERGY_INPUT = SENSORS_FEATURE_ENERGY << 8, + SENSORS_SUBFEATURE_VID = SENSORS_FEATURE_VID << 8, SENSORS_SUBFEATURE_BEEP_ENABLE = SENSORS_FEATURE_BEEP_ENABLE << 8, diff --git a/lib/sysfs.c b/lib/sysfs.c index 949d32e0..39f51220 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -138,24 +138,33 @@ char sensors_sysfs_mount[NAME_MAX]; #define MAX_SENSORS_PER_TYPE 20 #define MAX_SUBFEATURES 8 -/* Room for all 3 types (in, fan, temp) with all their subfeatures + VID - + misc features */ +#define MAX_SENSOR_TYPES 5 +/* Room for all 5 types (in, fan, temp, power, energy) with all their + subfeatures + VID + misc features */ #define ALL_POSSIBLE_SUBFEATURES \ - (MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 \ - + MAX_SENSORS_PER_TYPE + 1) + (MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * \ + MAX_SENSOR_TYPES * 2 + \ + MAX_SENSORS_PER_TYPE + 1) static int get_type_scaling(sensors_subfeature_type type) { + /* Multipliers for subfeatures */ switch (type & 0xFF80) { case SENSORS_SUBFEATURE_IN_INPUT: case SENSORS_SUBFEATURE_TEMP_INPUT: return 1000; case SENSORS_SUBFEATURE_FAN_INPUT: return 1; + case SENSORS_SUBFEATURE_POWER_AVERAGE: + case SENSORS_SUBFEATURE_ENERGY_INPUT: + return 1000000; } + /* Multipliers for second class subfeatures + that need their own multiplier */ switch (type) { + case SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL: case SENSORS_SUBFEATURE_VID: case SENSORS_SUBFEATURE_TEMP_OFFSET: return 1000; @@ -173,6 +182,8 @@ char *get_feature_name(sensors_feature_type ftype, char *sfname) case SENSORS_FEATURE_IN: case SENSORS_FEATURE_FAN: case SENSORS_FEATURE_TEMP: + case SENSORS_FEATURE_POWER: + case SENSORS_FEATURE_ENERGY: underscore = strchr(sfname, '_'); name = strndup(sfname, underscore - sfname); break; @@ -232,6 +243,19 @@ static const struct subfeature_type_match fan_matches[] = { { NULL, 0 } }; +static const struct subfeature_type_match power_matches[] = { + { "average", SENSORS_SUBFEATURE_POWER_AVERAGE }, + { "average_highest", SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST }, + { "average_lowest", SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST }, + { "average_interval", SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL }, + { NULL, 0 } +}; + +static const struct subfeature_type_match energy_matches[] = { + { "input", SENSORS_SUBFEATURE_ENERGY_INPUT }, + { NULL, 0 } +}; + static const struct subfeature_type_match cpu_matches[] = { { "vid", SENSORS_SUBFEATURE_VID }, { NULL, 0 } @@ -242,6 +266,8 @@ static struct feature_type_match matches[] = { { "in%d%c", in_matches }, { "fan%d%c", fan_matches }, { "cpu%d%c", cpu_matches }, + { "power%d%c", power_matches }, + { "energy%d%c", energy_matches }, }; /* Return the subfeature type and channel number based on the subfeature @@ -327,10 +353,12 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, /* Adjust the channel number */ switch (sftype & 0xFF00) { - case SENSORS_SUBFEATURE_FAN_INPUT: - case SENSORS_SUBFEATURE_TEMP_INPUT: - nr--; - break; + case SENSORS_SUBFEATURE_FAN_INPUT: + case SENSORS_SUBFEATURE_TEMP_INPUT: + case SENSORS_SUBFEATURE_POWER_AVERAGE: + case SENSORS_SUBFEATURE_ENERGY_INPUT: + nr--; + break; } if (nr < 0 || nr >= MAX_SENSORS_PER_TYPE) { @@ -347,11 +375,12 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, sorted table */ switch (sftype) { case SENSORS_SUBFEATURE_VID: - i = nr + MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6; + i = nr + MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * + MAX_SENSOR_TYPES * 2; break; case SENSORS_SUBFEATURE_BEEP_ENABLE: - i = MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 + - MAX_SENSORS_PER_TYPE; + i = MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * + MAX_SENSOR_TYPES * 2 + MAX_SENSORS_PER_TYPE; break; default: i = (sftype >> 8) * MAX_SENSORS_PER_TYPE * @@ -389,7 +418,8 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, if (!all_subfeatures[i].name) continue; - if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 || + if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * + MAX_SENSOR_TYPES * 2 || i / (MAX_SUBFEATURES * 2) != prev_slot) { fnum++; prev_slot = i / (MAX_SUBFEATURES * 2); @@ -410,7 +440,8 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, continue; /* New main feature? */ - if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 || + if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * + MAX_SENSOR_TYPES * 2 || i / (MAX_SUBFEATURES * 2) != prev_slot) { ftype = all_subfeatures[i].type >> 8; fnum++;