From 666fe95cdbe63e61f6fc7234c9c1cc20103ac6b0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 9 Apr 2007 14:09:21 +0000 Subject: [PATCH] dynamicly generate a sensors_chip_features_list entry for unknown chips based on their sysfs entries, by Bob Schlarmann and Luuk Kleiweg git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@4359 7894878c-1315-0410-8ee3-d5d059ff63e0 --- lib/chips.c | 3 ++ lib/data.h | 3 ++ lib/sysfs.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 158 insertions(+), 1 deletion(-) diff --git a/lib/chips.c b/lib/chips.c index 8d78b28d..8d4e5090 100644 --- a/lib/chips.c +++ b/lib/chips.c @@ -22,6 +22,8 @@ #include "sensors.h" #include "kernel/include/sensors.h" +#define PLACEHOLDER_ELEMENTS {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} + /* For each chip, a list of features; For each feature, the number, its name, the logical mapping (for example, fan1_div belongs to fan1), the compute mapping, an access field, the @@ -6161,5 +6163,6 @@ sensors_chip_features sensors_chip_features_list[] = { SENSORS_K8TEMP_PREFIX, k8temp_features }, { SENSORS_CORETEMP_PREFIX, coretemp_features }, { SENSORS_DME1737_PREFIX, dme1737_features }, + PLACEHOLDER_ELEMENTS, { 0 } }; diff --git a/lib/data.h b/lib/data.h index 8cb0ba73..af6017c3 100644 --- a/lib/data.h +++ b/lib/data.h @@ -191,4 +191,7 @@ extern int sensors_proc_bus_max; extern sensors_chip_features sensors_chip_features_list[]; +/* this should match the total number of elements in PLACEHOLDER_ELEMENTS */ +#define N_PLACEHOLDER_ELEMENTS 10 + #endif /* def LIB_SENSORS_DATA_H */ diff --git a/lib/sysfs.c b/lib/sysfs.c index bbb2b735..dadcb203 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "data.h" #include "error.h" #include "access.h" @@ -34,6 +35,137 @@ 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; + } +} + +static +sensors_chip_features sensors_read_dynamic_chip(struct sysfs_device *sysdir) +{ + int fnum = 1, i, last_major = -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]; + char *name; + + attrs = sysfs_get_device_attributes(sysdir); + + if (attrs == NULL) + return ret; + + regcomp(&preg, DYNAMIC_CHIP_REGEX, 0); + + dlist_for_each_data(attrs, attr, struct sysfs_attribute) { + 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) { + 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 (!strncmp(name + pmatch[2].rm_so, "_input", + pmatch[2].rm_eo - pmatch[2].rm_so)) { + 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); + } + + features[fnum - 1] = feature; +NEXT_NUM: + fnum++; + } + + regfree(&preg); + + dyn_features = malloc(sizeof(sensors_chip_feature) * fnum); + if (dyn_features == NULL) { + sensors_fatal_error(__FUNCTION__,"Out of memory"); + } + + for(i = 0; i < fnum - 1; i++) { + dyn_features[i] = features[i]; + } + dyn_features[fnum - 1].data.name = 0; + + ret.feature = dyn_features; + + return ret; +} + /* returns !0 if sysfs filesystem was found, 0 otherwise */ int sensors_init_sysfs(void) { @@ -46,7 +178,8 @@ int sensors_init_sysfs(void) /* returns: 0 if successful, !0 otherwise */ static int sensors_read_one_sysfs_chip(struct sysfs_device *dev) { - int domain, bus, slot, fn; + static int total_dynamic = 0; + int domain, bus, slot, fn, i; struct sysfs_attribute *attr, *bus_attr; char bus_path[SYSFS_PATH_MAX]; sensors_proc_chips_entry entry; @@ -102,7 +235,25 @@ static int sensors_read_one_sysfs_chip(struct sysfs_device *dev) entry.name.bus = SENSORS_CHIP_NAME_BUS_PCI; } else return -SENSORS_ERR_PARSE; + + /* check whether this chip is known in the static list */ + for (i = 0; sensors_chip_features_list[i].prefix; i++) + if (!strcasecmp(sensors_chip_features_list[i].prefix, entry.name.prefix)) + break; + /* if no chip definition matches */ + if (!sensors_chip_features_list[i].prefix && + total_dynamic < N_PLACEHOLDER_ELEMENTS) { + sensors_chip_features n_entry = sensors_read_dynamic_chip(dev); + + /* skip to end of list */ + for(i = 0; sensors_chip_features_list[i].prefix; i++); + + sensors_chip_features_list[i] = n_entry; + + total_dynamic++; + } + sensors_add_proc_chips(&entry); return 0;