diff --git a/lib/access.c b/lib/access.c index e7a91b1a..d905bff1 100644 --- a/lib/access.c +++ b/lib/access.c @@ -105,6 +105,24 @@ sensors_lookup_subfeature_nr(const sensors_chip_name *chip, return NULL; } +/* Look up a feature in the intern chip list, and return a pointer to it. + Do not modify the struct the return value points to! Returns NULL if + not found.*/ +static const sensors_feature * +sensors_lookup_feature_nr(const sensors_chip_name *chip, int feat_nr) +{ + int i; + + for (i = 0; i < sensors_proc_chips_count; i++) + if (sensors_match_chip(&sensors_proc_chips[i].chip, chip)) { + if (feat_nr < 0 || + feat_nr >= sensors_proc_chips[i].feature_count) + return NULL; + return sensors_proc_chips[i].feature + feat_nr; + } + return NULL; +} + /* Look up a resource in the intern chip list, and return a pointer to it. Do not modify the struct the return value points to! Returns NULL if not found.*/ @@ -208,12 +226,11 @@ int sensors_get_value(const sensors_chip_name *name, int subfeat_nr, double *result) { const sensors_subfeature *subfeature; - const sensors_subfeature *alt_feature; + const sensors_feature *feature; const sensors_chip *chip; const sensors_expr *expr = NULL; double val; int res, i; - int final_expr = 0; if (sensors_chip_name_has_wildcards(name)) return -SENSORS_ERR_WILDCARDS; @@ -221,20 +238,17 @@ int sensors_get_value(const sensors_chip_name *name, int subfeat_nr, return -SENSORS_ERR_NO_ENTRY; if (subfeature->flags & SENSORS_COMPUTE_MAPPING) - alt_feature = sensors_lookup_subfeature_nr(name, + feature = sensors_lookup_feature_nr(name, subfeature->mapping); else - alt_feature = NULL; + feature = NULL; if (!(subfeature->flags & SENSORS_MODE_R)) return -SENSORS_ERR_ACCESS_R; for (chip = NULL; !expr && (chip = sensors_for_all_config_chips(name, chip));) - for (i = 0; !final_expr && (i < chip->computes_count); i++) { - if (!strcmp(subfeature->name, chip->computes[i].name)) { - expr = chip->computes[i].from_proc; - final_expr = 1; - } else if (alt_feature && !strcmp(alt_feature->name, + for (i = 0; !expr && (i < chip->computes_count); i++) { + if (feature && !strcmp(feature->name, chip->computes[i].name)) { expr = chip->computes[i].from_proc; } @@ -255,11 +269,10 @@ int sensors_set_value(const sensors_chip_name *name, int subfeat_nr, double value) { const sensors_subfeature *subfeature; - const sensors_subfeature *alt_feature; + const sensors_feature *feature; const sensors_chip *chip; const sensors_expr *expr = NULL; int i, res; - int final_expr = 0; double to_write; if (sensors_chip_name_has_wildcards(name)) @@ -268,23 +281,21 @@ int sensors_set_value(const sensors_chip_name *name, int subfeat_nr, return -SENSORS_ERR_NO_ENTRY; if (subfeature->flags & SENSORS_COMPUTE_MAPPING) - alt_feature = sensors_lookup_subfeature_nr(name, + feature = sensors_lookup_feature_nr(name, subfeature->mapping); else - alt_feature = NULL; + feature = NULL; if (!(subfeature->flags & SENSORS_MODE_W)) return -SENSORS_ERR_ACCESS_W; for (chip = NULL; !expr && (chip = sensors_for_all_config_chips(name, chip));) - for (i = 0; !final_expr && (i < chip->computes_count); i++) - if (!strcmp(subfeature->name, chip->computes[i].name)) { - expr = chip->computes->to_proc; - final_expr = 1; - } else if (alt_feature && !strcmp(alt_feature->name, + for (i = 0; !expr && (i < chip->computes_count); i++) { + if (feature && !strcmp(feature->name, chip->computes[i].name)) { expr = chip->computes[i].to_proc; } + } to_write = value; if (expr) @@ -367,8 +378,7 @@ sensors_get_all_subfeatures(const sensors_chip_name *name, if (*nr >= sensors_proc_chips[i].subfeature_count) return NULL; /* end of list */ subfeature = &sensors_proc_chips[i].subfeature[(*nr)++]; - if (subfeature->number == feature->first_subfeature || - subfeature->mapping == feature->first_subfeature) + if (subfeature->mapping == feature->number) return subfeature; return NULL; /* end of subfeature list */ } diff --git a/lib/libsensors.3 b/lib/libsensors.3 index d42247a0..09d7f57b 100644 --- a/lib/libsensors.3 +++ b/lib/libsensors.3 @@ -134,10 +134,9 @@ data structures. \fBconst sensors_subfeature *sensors_get_all_subfeatures(const sensors_chip_name *name, const sensors_feature *feature, int *nr);\fP .br -This returns all subfeatures of a given main feature (including that -main feature itself, in first position.) nr is an internally used -variable. Set it to zero to start at the begin of the list. If no more -subfeatures are found NULL is returned. +This returns all subfeatures of a given main feature. nr is an internally +used variable. Set it to zero to start at the begin of the list. If no +more subfeatures are found NULL is returned. Do not try to change the returned structure; you will corrupt internal data structures. diff --git a/lib/sensors.h b/lib/sensors.h index dc6dfd97..e6fc8414 100644 --- a/lib/sensors.h +++ b/lib/sensors.h @@ -124,6 +124,16 @@ const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name mapping is available */ #define SENSORS_NO_MAPPING -1 +/* These must match the subfeature constants below (shifted by 8 bits) */ +typedef enum sensors_feature_type { + SENSORS_FEATURE_IN = 0x00, + SENSORS_FEATURE_FAN = 0x01, + SENSORS_FEATURE_TEMP = 0x02, + SENSORS_FEATURE_VID = 0x10, + SENSORS_FEATURE_BEEP_ENABLE = 0x11, + SENSORS_FEATURE_UNKNOWN = INT_MAX, +} sensors_feature_type; + /* This enum contains some "magic" used by sensors_read_dynamic_chip() from lib/sysfs.c. All the sensor types (in, fan, temp, vid) are a multiple of 0x100 apart, and sensor subfeatures which should not have a compute @@ -169,8 +179,9 @@ typedef enum sensors_subfeature_type { /* Data about a single chip feature (or category leader) */ struct sensors_feature { char *name; + int number; + sensors_feature_type type; int first_subfeature; - sensors_subfeature_type type; }; /* Data about a single chip subfeature: @@ -201,10 +212,9 @@ typedef struct sensors_subfeature { const sensors_feature * sensors_get_features(const sensors_chip_name *name, int *nr); -/* This returns all subfeatures of a given main feature (including that - main feature itself, in first position.) nr is an internally used - variable. Set it to zero to start at the begin of the list. If no more - features are found NULL is returned. +/* This returns all subfeatures of a given main feature. nr is an internally + used variable. Set it to zero to start at the begin of the list. If no + more features are found NULL is returned. Do not try to change the returned structure; you will corrupt internal data structures. */ const sensors_subfeature * diff --git a/lib/sysfs.c b/lib/sysfs.c index 37ad62c9..f96cee95 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -65,6 +65,25 @@ int get_type_scaling(int type) } } +static +char *get_feature_name(sensors_feature_type ftype, char *sfname) +{ + char *name, *underscore; + + switch (ftype) { + case SENSORS_FEATURE_IN: + case SENSORS_FEATURE_FAN: + case SENSORS_FEATURE_TEMP: + underscore = strchr(sfname, '_'); + name = strndup(sfname, underscore - sfname); + break; + default: + name = strdup(sfname); + } + + return name; +} + /* Static mappings for use by sensors_subfeature_get_type() */ struct subfeature_type_match { @@ -160,12 +179,14 @@ sensors_subfeature_type sensors_subfeature_get_type(const char *name, int *nr) static int sensors_read_dynamic_chip(sensors_chip_features *chip, struct sysfs_device *sysdir) { - int i, type, fnum = 0; + int i, fnum = 0, sfnum = 0, prev_slot; struct sysfs_attribute *attr; struct dlist *attrs; sensors_subfeature *all_subfeatures; sensors_subfeature *dyn_subfeatures; sensors_feature *dyn_features; + sensors_feature_type ftype; + sensors_subfeature_type sftype; attrs = sysfs_get_device_attributes(sysdir); @@ -184,12 +205,12 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, char *name = attr->name; int nr; - type = sensors_subfeature_get_type(name, &nr); - if (type == SENSORS_SUBFEATURE_UNKNOWN) + sftype = sensors_subfeature_get_type(name, &nr); + if (sftype == SENSORS_SUBFEATURE_UNKNOWN) continue; /* Adjust the channel number */ - switch (type & 0xFF00) { + switch (sftype & 0xFF00) { case SENSORS_SUBFEATURE_FAN_INPUT: case SENSORS_SUBFEATURE_TEMP_INPUT: if (nr) @@ -206,7 +227,7 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, /* "calculate" a place to store the subfeature in our sparse, sorted table */ - switch (type) { + switch (sftype) { case SENSORS_SUBFEATURE_VID: i = nr + MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6; break; @@ -215,10 +236,10 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, MAX_SENSORS_PER_TYPE; break; default: - i = (type >> 8) * MAX_SENSORS_PER_TYPE * + i = (sftype >> 8) * MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 2 + nr * MAX_SUBFEATURES * 2 + - ((type & 0x10) >> 4) * MAX_SUBFEATURES + - (type & 0x0F); + ((sftype & 0x10) >> 4) * MAX_SUBFEATURES + + (sftype & 0x0F); } if (all_subfeatures[i].name) { @@ -229,93 +250,75 @@ static int sensors_read_dynamic_chip(sensors_chip_features *chip, } /* fill in the subfeature members */ - all_subfeatures[i].type = type; - - /* check for _input extension and remove */ - nr = strlen(name); - if (nr > 6 && !strcmp(name + nr - 6, "_input")) - all_subfeatures[i].name = strndup(name, nr - 6); - else - all_subfeatures[i].name = strdup(name); - - if ((type & 0x00FF) == 0) { - /* main subfeature */ - all_subfeatures[i].mapping = SENSORS_NO_MAPPING; - } else { - /* The mapping is set below after numbering */ - if (!(type & 0x10)) - all_subfeatures[i].flags |= SENSORS_COMPUTE_MAPPING; - } - + all_subfeatures[i].type = sftype; + all_subfeatures[i].name = strdup(name); + if (!(sftype & 0x10)) + all_subfeatures[i].flags |= SENSORS_COMPUTE_MAPPING; if (attr->method & SYSFS_METHOD_SHOW) all_subfeatures[i].flags |= SENSORS_MODE_R; if (attr->method & SYSFS_METHOD_STORE) all_subfeatures[i].flags |= SENSORS_MODE_W; - fnum++; + sfnum++; } - if (!fnum) { /* No subfeature */ + if (!sfnum) { /* No subfeature */ chip->subfeature = NULL; goto exit_free; } - dyn_subfeatures = calloc(fnum, sizeof(sensors_subfeature)); - if (dyn_subfeatures == NULL) { - sensors_fatal_error(__FUNCTION__, "Out of memory"); - } - - fnum = 0; + /* How many main features? */ + prev_slot = -1; for (i = 0; i < ALL_POSSIBLE_SUBFEATURES; i++) { - if (all_subfeatures[i].name) { - dyn_subfeatures[fnum] = all_subfeatures[i]; + if (!all_subfeatures[i].name) + continue; + + if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 || + i / (MAX_SUBFEATURES * 2) != prev_slot) { fnum++; + prev_slot = i / (MAX_SUBFEATURES * 2); } } - /* Number the subfeatures linearly, so that subfeature number N is at - position N in the array. This allows for O(1) look-ups. */ - for (i = 0; i < fnum; i++) { - int j; + dyn_subfeatures = calloc(sfnum, sizeof(sensors_subfeature)); + dyn_features = calloc(fnum, sizeof(sensors_feature)); + if (!dyn_subfeatures || !dyn_features) + sensors_fatal_error(__FUNCTION__, "Out of memory"); - dyn_subfeatures[i].number = i; - if (dyn_subfeatures[i].mapping == SENSORS_NO_MAPPING) { - /* Main feature, set the mapping field of all its - subfeatures */ - for (j = i + 1; j < fnum && - dyn_subfeatures[j].mapping != SENSORS_NO_MAPPING; - j++) - dyn_subfeatures[j].mapping = i; + /* Copy from the sparse array to the compact array */ + sfnum = 0; + fnum = -1; + prev_slot = -1; + for (i = 0; i < ALL_POSSIBLE_SUBFEATURES; i++) { + if (!all_subfeatures[i].name) + continue; + + /* New main feature? */ + if (i >= MAX_SENSORS_PER_TYPE * MAX_SUBFEATURES * 6 || + i / (MAX_SUBFEATURES * 2) != prev_slot) { + ftype = all_subfeatures[i].type >> 8; + fnum++; + prev_slot = i / (MAX_SUBFEATURES * 2); + + dyn_features[fnum].name = get_feature_name(ftype, + all_subfeatures[i].name); + dyn_features[fnum].number = fnum; + dyn_features[fnum].first_subfeature = sfnum; + dyn_features[fnum].type = ftype; } + + dyn_subfeatures[sfnum] = all_subfeatures[i]; + dyn_subfeatures[sfnum].number = sfnum; + /* Back to the feature */ + dyn_subfeatures[sfnum].mapping = fnum; + + sfnum++; } chip->subfeature = dyn_subfeatures; - chip->subfeature_count = fnum; - - /* And now the main features */ - fnum = 0; - for (i = 0; i < chip->subfeature_count; i++) { - if (chip->subfeature[i].mapping == SENSORS_NO_MAPPING) - fnum++; - } - - dyn_features = calloc(fnum, sizeof(sensors_feature)); - if (dyn_features == NULL) { - sensors_fatal_error(__FUNCTION__, "Out of memory"); - } - - fnum = 0; - for (i = 0; i < chip->subfeature_count; i++) { - if (chip->subfeature[i].mapping == SENSORS_NO_MAPPING) { - dyn_features[fnum].name = strdup(chip->subfeature[i].name); - dyn_features[fnum].first_subfeature = i; - dyn_features[fnum].type = chip->subfeature[i].type; - fnum++; - } - } - + chip->subfeature_count = sfnum; chip->feature = dyn_features; - chip->feature_count = fnum; + chip->feature_count = ++fnum; exit_free: free(all_subfeatures); @@ -544,19 +547,11 @@ int sensors_read_sysfs_attr(const sensors_chip_name *name, int subfeat_nr, const sensors_subfeature *subfeature; char n[NAME_MAX]; FILE *f; - const char *suffix = ""; if (!(subfeature = sensors_lookup_subfeature_nr(name, subfeat_nr))) return -SENSORS_ERR_NO_ENTRY; - /* REVISIT: this is a ugly hack */ - if (subfeature->type == SENSORS_SUBFEATURE_IN_INPUT - || subfeature->type == SENSORS_SUBFEATURE_FAN_INPUT - || subfeature->type == SENSORS_SUBFEATURE_TEMP_INPUT) - suffix = "_input"; - - snprintf(n, NAME_MAX, "%s/%s%s", name->path, subfeature->name, - suffix); + snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name); if ((f = fopen(n, "r"))) { int res = fscanf(f, "%lf", value); fclose(f); @@ -575,19 +570,11 @@ int sensors_write_sysfs_attr(const sensors_chip_name *name, int subfeat_nr, const sensors_subfeature *subfeature; char n[NAME_MAX]; FILE *f; - const char *suffix = ""; if (!(subfeature = sensors_lookup_subfeature_nr(name, subfeat_nr))) return -SENSORS_ERR_NO_ENTRY; - /* REVISIT: this is a ugly hack */ - if (subfeature->type == SENSORS_SUBFEATURE_IN_INPUT - || subfeature->type == SENSORS_SUBFEATURE_FAN_INPUT - || subfeature->type == SENSORS_SUBFEATURE_TEMP_INPUT) - suffix = "_input"; - - snprintf(n, NAME_MAX, "%s/%s%s", name->path, subfeature->name, - suffix); + snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name); if ((f = fopen(n, "w"))) { value *= get_type_scaling(subfeature->type); fprintf(f, "%d", (int) value); diff --git a/prog/sensord/chips.c b/prog/sensord/chips.c index 43b34960..e8b39886 100644 --- a/prog/sensord/chips.c +++ b/prog/sensord/chips.c @@ -373,19 +373,19 @@ FeatureDescriptor * generateChipFeatures (const sensors_chip_name *chip) nr = 0; while ((sensor = sensors_get_features(chip, &nr))) { switch (sensor->type) { - case SENSORS_SUBFEATURE_TEMP_INPUT: + case SENSORS_FEATURE_TEMP: fillChipTemperature(&features[count], chip, sensor); break; - case SENSORS_SUBFEATURE_IN_INPUT: + case SENSORS_FEATURE_IN: fillChipVoltage(&features[count], chip, sensor); break; - case SENSORS_SUBFEATURE_FAN_INPUT: + case SENSORS_FEATURE_FAN: fillChipFan(&features[count], chip, sensor); break; - case SENSORS_SUBFEATURE_VID: + case SENSORS_FEATURE_VID: fillChipVid(&features[count], chip, sensor); break; - case SENSORS_SUBFEATURE_BEEP_ENABLE: + case SENSORS_FEATURE_BEEP_ENABLE: fillChipBeepEnable(&features[count], chip, sensor); break; default: diff --git a/prog/sensors/chips.c b/prog/sensors/chips.c index b411820e..f367f68d 100644 --- a/prog/sensors/chips.c +++ b/prog/sensors/chips.c @@ -435,19 +435,19 @@ void print_chip(const sensors_chip_name *name) i = 0; while ((feature = sensors_get_features(name, &i))) { switch (feature->type) { - case SENSORS_SUBFEATURE_TEMP_INPUT: + case SENSORS_FEATURE_TEMP: print_chip_temp(name, feature, label_size); break; - case SENSORS_SUBFEATURE_IN_INPUT: + case SENSORS_FEATURE_IN: print_chip_in(name, feature, label_size); break; - case SENSORS_SUBFEATURE_FAN_INPUT: + case SENSORS_FEATURE_FAN: print_chip_fan(name, feature, label_size); break; - case SENSORS_SUBFEATURE_VID: + case SENSORS_FEATURE_VID: print_chip_vid(name, feature, label_size); break; - case SENSORS_SUBFEATURE_BEEP_ENABLE: + case SENSORS_FEATURE_BEEP_ENABLE: print_chip_beep_enable(name, feature, label_size); break; default: