From bd74aa23900d701044e0b84acbb1b8aaae686f22 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 10 Apr 2007 11:51:07 +0000 Subject: [PATCH] -rewrite dyn chip code, it now uses sensors_feature_get_type() to identify sysfs entries. Reasons for this rewrite / bugs fixed: -Don't give features like alarms / sensor type / fault flag a compute mapping only a normal mapping -Don't generate features for sysfs entries like uvent, modalias, etc. instead only generate features for features known by sensors_feature_get_type() -Sort the list of found features logically instead of sorted in alphabet order of the sysfs entry. So now it starts with all in entries, then all fan and then all temp. Just like the order of most entries in lib/chips.c. Also this means that it now contains in0 - in10 in that order and not in0, in10, in1 - in9 git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@4368 7894878c-1315-0410-8ee3-d5d059ff63e0 --- lib/access.c | 23 ++--- lib/sensors.h | 44 ++++---- lib/sysfs.c | 192 ++++++++++++++++++----------------- prog/sensors/chips_generic.c | 8 +- 4 files changed, 140 insertions(+), 127 deletions(-) diff --git a/lib/access.c b/lib/access.c index ce951e39..3285468d 100644 --- a/lib/access.c +++ b/lib/access.c @@ -515,27 +515,24 @@ struct feature_type_match }; static struct feature_type_match temp_matches[] = { - { "max", SENSORS_FEATURE_TEMP_MAX }, - { "min", SENSORS_FEATURE_TEMP_MIN }, - { "type", SENSORS_FEATURE_TEMP_SENS }, { "hyst", SENSORS_FEATURE_TEMP_HYST }, { "over", SENSORS_FEATURE_TEMP_OVER }, { "max", SENSORS_FEATURE_TEMP_MAX }, { "min", SENSORS_FEATURE_TEMP_MIN }, { "low", SENSORS_FEATURE_TEMP_LOW }, { "crit", SENSORS_FEATURE_TEMP_CRIT }, - { "fault", SENSORS_FEATURE_TEMP_FAULT }, { "alarm", SENSORS_FEATURE_TEMP_ALARM }, + { "fault", SENSORS_FEATURE_TEMP_FAULT }, { "type", SENSORS_FEATURE_TEMP_SENS }, { 0 } }; static struct feature_type_match in_matches[] = { - { "max", SENSORS_FEATURE_IN_MAX }, - { "max_alarm", SENSORS_FEATURE_IN_MAX_ALARM }, { "min", SENSORS_FEATURE_IN_MIN }, - { "min_alarm", SENSORS_FEATURE_IN_MIN_ALARM }, + { "max", SENSORS_FEATURE_IN_MAX }, { "alarm", SENSORS_FEATURE_IN_ALARM }, + { "min_alarm", SENSORS_FEATURE_IN_MIN_ALARM }, + { "max_alarm", SENSORS_FEATURE_IN_MAX_ALARM }, { 0 } }; @@ -562,10 +559,11 @@ sensors_feature_type sensors_feature_get_type( const sensors_feature_data *feature) { const char *name; - regex_t preg; regmatch_t pmatch[4]; int size_first, size_second, retval, i; struct feature_type_match *submatches; + static regex_t reg; + static regex_t *preg = NULL; /* use sysname if exists */ if (container_of(feature, const struct sensors_chip_feature, data)->sysname) @@ -573,11 +571,12 @@ sensors_feature_type sensors_feature_get_type( else name = feature->name; - regcomp(&preg, GET_TYPE_REGEX, 0); + if (!preg) { + regcomp(®, GET_TYPE_REGEX, 0); + preg = ® + } - retval = regexec(&preg, name, 4, pmatch, 0); - - regfree(&preg); + retval = regexec(preg, name, 4, pmatch, 0); if (retval == -1) return SENSORS_FEATURE_UNKNOWN; diff --git a/lib/sensors.h b/lib/sensors.h index 8e50482b..29c560cb 100644 --- a/lib/sensors.h +++ b/lib/sensors.h @@ -147,11 +147,25 @@ typedef struct sensors_feature_data { extern const sensors_feature_data *sensors_get_all_features (sensors_chip_name name, int *nr1,int *nr2); +/* This enum contains some "magic" used by sensors_read_dynamic_chip() from + lib/sysfs.c . All the sensor-types (in, fan, temp, misc) are a multiple of + 0x100 apart, and sensor features which should not have a compute_mapping to + the _input feature start at 0x?10. */ typedef enum sensors_feature_type { - SENSORS_FEATURE_TEMP = 0x0, - SENSORS_FEATURE_TEMP_ALARM, - SENSORS_FEATURE_TEMP_FAULT, - SENSORS_FEATURE_TEMP_SENS, + SENSORS_FEATURE_IN = 0x000, + SENSORS_FEATURE_IN_MIN, + SENSORS_FEATURE_IN_MAX, + SENSORS_FEATURE_IN_ALARM = 0x010, + SENSORS_FEATURE_IN_MIN_ALARM, + SENSORS_FEATURE_IN_MAX_ALARM, + + SENSORS_FEATURE_FAN = 0x100, + SENSORS_FEATURE_FAN_MIN, + SENSORS_FEATURE_FAN_ALARM = 0x110, + SENSORS_FEATURE_FAN_FAULT, + SENSORS_FEATURE_FAN_DIV, + + SENSORS_FEATURE_TEMP = 0x200, SENSORS_FEATURE_TEMP_HYST, SENSORS_FEATURE_TEMP_OVER, SENSORS_FEATURE_TEMP_MAX, @@ -160,24 +174,18 @@ typedef enum sensors_feature_type { SENSORS_FEATURE_TEMP_LOW, SENSORS_FEATURE_TEMP_LIM, SENSORS_FEATURE_TEMP_CRIT, - - SENSORS_FEATURE_IN = 0x100, - SENSORS_FEATURE_IN_ALARM, - SENSORS_FEATURE_IN_MIN, - SENSORS_FEATURE_IN_MAX, - SENSORS_FEATURE_IN_MIN_ALARM, - SENSORS_FEATURE_IN_MAX_ALARM, - - SENSORS_FEATURE_FAN = 0x200, - SENSORS_FEATURE_FAN_ALARM, - SENSORS_FEATURE_FAN_FAULT, - SENSORS_FEATURE_FAN_MIN, - SENSORS_FEATURE_FAN_DIV, + SENSORS_FEATURE_TEMP_ALARM = 0x210, + SENSORS_FEATURE_TEMP_FAULT, + SENSORS_FEATURE_TEMP_SENS, SENSORS_FEATURE_VID = 0x300, SENSORS_FEATURE_VRM, - SENSORS_FEATURE_UNKNOWN = INT_MAX + SENSORS_FEATURE_UNKNOWN = INT_MAX, + + /* special the largest number of subfeatures used, iow the + highest ## from all the 0x?## above + 1*/ + SENSORS_FEATURE_MAX_SUB_FEATURES = 19 } sensors_feature_type; sensors_feature_type sensors_feature_get_type diff --git a/lib/sysfs.c b/lib/sysfs.c index 52880b44..ce9c109f 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -21,10 +21,10 @@ #define _GNU_SOURCE #include +#include #include #include #include -#include #include "data.h" #include "error.h" #include "access.h" @@ -35,130 +35,136 @@ int sensors_found_sysfs = 0; char sensors_sysfs_mount[NAME_MAX]; -#define DYNAMIC_CHIP_REGEX "\\([[:alpha:]]\\{1,\\}[[:digit:]]\\{0,\\}\\)\\(\\_[[:alpha:]]\\{1,\\}\\)\\{0,1\\}" - -static int sensors_read_dynamic_chip_check_mapping( - sensors_chip_feature *minor, - sensors_chip_feature *major, - regmatch_t *pmatch) -{ - if (pmatch[1].rm_so == -1 || pmatch[2].rm_so == -1 || - strncmp(minor->data.name, major->data.name, - pmatch[1].rm_eo - pmatch[1].rm_so)) { - return 0; - } else { - minor->data.mapping = - minor->data.compute_mapping = - major->data.number; - - return 1; - } -} +#define MAX_SENSORS_PER_TYPE 16 static sensors_chip_features sensors_read_dynamic_chip(struct sysfs_device *sysdir) { - int fnum = 1, i, last_major = -1; + int i, type, fnum = 1; struct sysfs_attribute *attr; struct dlist *attrs; sensors_chip_features ret = {0, 0}; - sensors_chip_feature features[256], *dyn_features; - regex_t preg; - regmatch_t pmatch[3]; + /* room for all 3 (in, fan, temp) types, with all their subfeatures + + misc features. We use a large sparse table at first to store all + found features, so that we can store them sorted at type and index + and then later create a dense sorted table */ + sensors_chip_feature features[MAX_SENSORS_PER_TYPE * + SENSORS_FEATURE_MAX_SUB_FEATURES * 3 + + SENSORS_FEATURE_MAX_SUB_FEATURES]; + sensors_chip_feature *dyn_features; char *name; attrs = sysfs_get_device_attributes(sysdir); if (attrs == NULL) return ret; - - regcomp(&preg, DYNAMIC_CHIP_REGEX, 0); + memset(features, 0, sizeof(features)); + dlist_for_each_data(attrs, attr, struct sysfs_attribute) { - sensors_chip_feature feature = { { 0, }, 0, }; + sensors_chip_feature feature = { { 0, }, 0, }; name = attr->name; if (!strcmp(name, "name")) { ret.prefix = strndup(attr->value, strlen(attr->value) - 1); continue; - } else if (regexec(&preg, name, 3, pmatch, 0) != 0) { + } + + /* check for _input extension and remove */ + i = strlen(name); + if (i > 6 && !strcmp(name + i - 6, "_input")) + feature.data.name = strndup(name, i-6); + else + feature.data.name = strdup(name); + + type = sensors_feature_get_type(&feature.data); + if (type == SENSORS_FEATURE_UNKNOWN) { + free((char *)feature.data.name); + continue; + } + + /* Get N as in this is the N-th in / fan / temp sensor */ + switch (type & 0xFF00) { + case SENSORS_FEATURE_IN: + i = strtol(name + 2, NULL, 10); + break; + case SENSORS_FEATURE_FAN: + i = strtol(name + 3, NULL, 10); + if (i) i--; + break; + case SENSORS_FEATURE_TEMP: + i = strtol(name + 4, NULL, 10); + if (i) i--; + break; + case SENSORS_FEATURE_VID: /* first misc feature */ + i = 0; + break; + } + + if (i >= MAX_SENSORS_PER_TYPE) { + fprintf(stderr, "libsensors error, more sensors of one" + " type then MAX_SENSORS_PER_TYPE, ignoring " + "feature: %s\n", name); + free((char *)feature.data.name); continue; } - feature.data.number = fnum; - feature.data.mode = (attr->method & (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE)) == - (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE) ? - SENSORS_MODE_RW : - (attr->method & SYSFS_METHOD_SHOW) ? SENSORS_MODE_R : - (attr->method & SYSFS_METHOD_STORE) ? SENSORS_MODE_W : - SENSORS_MODE_NO_RW; - feature.data.mapping = SENSORS_NO_MAPPING; - feature.data.compute_mapping = SENSORS_NO_MAPPING; - - if (pmatch[2].rm_so != -1) { - if (!strcmp(name + pmatch[2].rm_so, "_input")) { - int last_match; - - /* copy only the part before the _ */ - feature.data.name = strndup(name, - pmatch[1].rm_eo - pmatch[1].rm_so); - - /* check if the features previously read are sub devices of this major - and update their mapping accordingly */ - last_match = fnum - 1; - for(i = fnum - 2; i >= 0; i--) { - if (regexec(&preg, features[i].data.name, 3, pmatch, 0) == -1 || - !sensors_read_dynamic_chip_check_mapping(&features[i], - &feature, pmatch)) { - break; - } else { - last_match = i; - } - } - - /* if so the major should be in the list before any minor feature, - so swap with the oldest read */ - if (last_match < fnum - 1) { - sensors_chip_feature tmp = features[last_match]; - features[last_match] = feature; - features[fnum - 1] = tmp; - - last_major = last_match; - - goto NEXT_NUM; /* NOTE: goto used */ - } else { - last_major = fnum - 1; - } - - } else { - feature.data.name = strdup(name); - - if (last_major != -1 && - !sensors_read_dynamic_chip_check_mapping(&feature, - &features[last_major], pmatch)) { - last_major = -1; /* no more features for current major */ - } - } - } else { - feature.data.name = strdup(name); + /* "calculate" a place to store the feature in our sparse, + sorted table */ + i = (type >> 8) * MAX_SENSORS_PER_TYPE * + SENSORS_FEATURE_MAX_SUB_FEATURES + + i * SENSORS_FEATURE_MAX_SUB_FEATURES + (type & 0xFF); + + if (features[i].data.name) { + fprintf(stderr, "libsensors error, trying to add dupli" + "cate feature: %s to dynamic feature table\n", + name); + free((char *)feature.data.name); + continue; } + + /* fill in the other feature members */ + feature.data.number = i + 1; - features[fnum - 1] = feature; -NEXT_NUM: + if ( (type & 0xFF00) == SENSORS_FEATURE_VID || + (type & 0x00FF) == 0) { + /* misc sensor or main feature */ + feature.data.mapping = SENSORS_NO_MAPPING; + feature.data.compute_mapping = SENSORS_NO_MAPPING; + } else if (type & 0x10) { + /* sub feature without compute mapping */ + feature.data.mapping = i - + i % SENSORS_FEATURE_MAX_SUB_FEATURES + 1; + feature.data.compute_mapping = SENSORS_NO_MAPPING; + } else { + feature.data.mapping = i - + i % SENSORS_FEATURE_MAX_SUB_FEATURES + 1; + feature.data.compute_mapping = feature.data.mapping; + } + + feature.data.mode = + (attr->method & (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE)) + == (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE) ? + SENSORS_MODE_RW : (attr->method & SYSFS_METHOD_SHOW) ? + SENSORS_MODE_R : (attr->method & SYSFS_METHOD_STORE) ? + SENSORS_MODE_W : SENSORS_MODE_NO_RW; + + features[i] = feature; fnum++; } - - regfree(&preg); - - dyn_features = malloc(sizeof(sensors_chip_feature) * fnum); + + dyn_features = calloc(fnum, sizeof(sensors_chip_feature)); if (dyn_features == NULL) { sensors_fatal_error(__FUNCTION__,"Out of memory"); } - for(i = 0; i < fnum - 1; i++) { - dyn_features[i] = features[i]; + fnum = 0; + for(i = 0; i < sizeof(features)/sizeof(sensors_chip_feature); i++) { + if (features[i].data.name) { + dyn_features[fnum] = features[i]; + fnum++; + } } - dyn_features[fnum - 1].data.name = 0; ret.feature = dyn_features; diff --git a/prog/sensors/chips_generic.c b/prog/sensors/chips_generic.c index b2bfb2f8..fed9cf6c 100644 --- a/prog/sensors/chips_generic.c +++ b/prog/sensors/chips_generic.c @@ -110,9 +110,9 @@ static void print_generic_chip_temp(const sensors_chip_name *name, double val, max, min, lim = 0.0; char *label; int valid, type; - const int size = SENSORS_FEATURE_TEMP_CRIT - SENSORS_FEATURE_TEMP; - short has_features[SENSORS_FEATURE_TEMP_CRIT - SENSORS_FEATURE_TEMP] = {0, 0, 0, 0, 0, 0, 0, 0, 0 }; - double feature_vals[SENSORS_FEATURE_TEMP_CRIT - SENSORS_FEATURE_TEMP] = {0.0, }; + const int size = SENSORS_FEATURE_TEMP_SENS - SENSORS_FEATURE_TEMP; + short has_features[SENSORS_FEATURE_TEMP_SENS - SENSORS_FEATURE_TEMP] = {0, }; + double feature_vals[SENSORS_FEATURE_TEMP_SENS - SENSORS_FEATURE_TEMP] = {0.0, }; if (sensors_get_label_and_valid(*name, feature->number, &label, &valid)) { free(label); @@ -254,7 +254,7 @@ static void print_generic_chip_in(const sensors_chip_name *name, { const int size = SENSORS_FEATURE_IN_MAX_ALARM - SENSORS_FEATURE_IN; int valid; - short has_features[SENSORS_FEATURE_IN_MAX_ALARM - SENSORS_FEATURE_IN] = {0, 0, 0, 0, 0 }; + short has_features[SENSORS_FEATURE_IN_MAX_ALARM - SENSORS_FEATURE_IN] = {0, }; double feature_vals[SENSORS_FEATURE_IN_MAX_ALARM - SENSORS_FEATURE_IN] = {0.0, }; double val, alarm_max, alarm_min; char *label;