root/lm-sensors/branches/lm-sensors-3.0.0/lib/access.c @ 4545

Revision 4545, 17.7 KB (checked in by khali, 7 years ago)

Add some more warning flags, and fix these warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    access.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23#include "access.h"
24#include "sensors.h"
25#include "data.h"
26#include "error.h"
27#include "proc.h"
28#include "general.h"
29
30static int sensors_eval_expr(sensors_chip_name chipname, 
31                             const sensors_expr *expr,
32                             double val, double *result);
33
34/* Compare two chips name descriptions, to see whether they could match.
35   Return 0 if it does not match, return 1 if it does match. */
36int sensors_match_chip(sensors_chip_name chip1, sensors_chip_name chip2)
37{
38        if ((chip1.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
39            (chip2.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
40            strcasecmp(chip1.prefix, chip2.prefix))
41                return 0;
42
43        if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY) &&
44            (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY) &&
45            (chip1.bus != chip2.bus)) {
46
47                if ((chip1.bus == SENSORS_CHIP_NAME_BUS_ISA) ||
48                    (chip2.bus == SENSORS_CHIP_NAME_BUS_ISA))
49                        return 0;
50
51                if ((chip1.bus == SENSORS_CHIP_NAME_BUS_PCI) ||
52                    (chip2.bus == SENSORS_CHIP_NAME_BUS_PCI))
53                        return 0;
54
55                if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C) &&
56                    (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
57                        return 0;
58        }
59
60        if ((chip1.addr != chip2.addr) &&
61            (chip1.addr != SENSORS_CHIP_NAME_ADDR_ANY) &&
62            (chip2.addr != SENSORS_CHIP_NAME_ADDR_ANY))
63                return 0;
64
65        return 1;
66}
67
68/* Returns, one by one, a pointer to all sensor_chip structs of the
69   config file which match with the given chip name. Last should be
70   the value returned by the last call, or NULL if this is the first
71   call. Returns NULL if no more matches are found. Do not modify
72   the struct the return value points to!
73   Note that this visits the list of chips from last to first. Usually,
74   you want the match that was latest in the config file. */
75static sensors_chip *
76sensors_for_all_config_chips(sensors_chip_name chip_name,
77                             const sensors_chip *last)
78{
79        int nr, i;
80        sensors_chip_name_list chips;
81
82        for (nr = last ? last - sensors_config_chips - 1 :
83                         sensors_config_chips_count - 1; nr >= 0; nr--) {
84
85                chips = sensors_config_chips[nr].chips;
86                for (i = 0; i < chips.fits_count; i++) {
87                        if (sensors_match_chip(chips.fits[i], chip_name))
88                                return sensors_config_chips + nr;
89                }
90        }
91        return NULL;
92}
93
94/* Look up a resource in the intern chip list, and return a pointer to it.
95   Do not modify the struct the return value points to! Returns NULL if
96   not found.*/
97const sensors_chip_feature *sensors_lookup_feature_nr(const sensors_chip_name *chip,
98                                                      int feature)
99{
100        int i, j;
101        const sensors_chip_feature *features;
102
103        for (i = 0; i < sensors_proc_chips_count; i++)
104                if (sensors_match_chip(sensors_proc_chips[i].chip, *chip)) {
105                        features = sensors_proc_chips[i].feature;
106                        for (j = 0; features[j].data.name; j++)
107                                if (features[j].data.number == feature)
108                                        return features + j;
109                }
110        return NULL;
111}
112
113/* Look up a resource in the intern chip list, and return a pointer to it.
114   Do not modify the struct the return value points to! Returns NULL if
115   not found.*/
116static const sensors_chip_feature *
117sensors_lookup_feature_name(const sensors_chip_name *chip, const char *feature)
118{
119        int i, j;
120        const sensors_chip_feature *features;
121
122        for (i = 0; i < sensors_proc_chips_count; i++)
123                if (sensors_match_chip(sensors_proc_chips[i].chip, *chip)) {
124                        features = sensors_proc_chips[i].feature;
125                        for (j = 0; features[j].data.name; j++)
126                                if (!strcasecmp(features[j].data.name, feature))
127                                        return features + j;
128                }
129        return NULL;
130}
131
132/* Check whether the chip name is an 'absolute' name, which can only match
133   one chip, or whether it has wildcards. Returns 0 if it is absolute, 1
134   if there are wildcards. */
135int sensors_chip_name_has_wildcards(sensors_chip_name chip)
136{
137        if ((chip.prefix == SENSORS_CHIP_NAME_PREFIX_ANY) ||
138            (chip.bus == SENSORS_CHIP_NAME_BUS_ANY) ||
139            (chip.bus == SENSORS_CHIP_NAME_BUS_ANY_I2C) ||
140            (chip.addr == SENSORS_CHIP_NAME_ADDR_ANY))
141                return 1;
142        else
143                return 0;
144}
145
146/* Look up the label which belongs to this chip. Note that chip should not
147   contain wildcard values! *result is newly allocated (free it yourself).
148   This function will return 0 on success, and <0 on failure.
149   If no label exists for this feature, its name is returned itself. */
150int sensors_get_label(sensors_chip_name name, int feature, char **result)
151{
152        const sensors_chip *chip;
153        const sensors_chip_feature *featureptr;
154        int i;
155
156        *result = NULL;
157        if (sensors_chip_name_has_wildcards(name))
158                return -SENSORS_ERR_WILDCARDS;
159        if (!(featureptr = sensors_lookup_feature_nr(&name, feature)))
160                return -SENSORS_ERR_NO_ENTRY;
161
162        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
163                for (i = 0; i < chip->labels_count; i++)
164                        if (!strcasecmp(featureptr->data.name,chip->labels[i].name)){
165                                if (*result)
166                                        free(*result);
167                                if (!(*result = strdup(chip->labels[i].value)))
168                                        sensors_fatal_error("sensors_get_label",
169                                                            "Allocating label text");
170                                return 0;
171                        }
172
173        /* No label, return the feature name instead */
174        if (!(*result = strdup(featureptr->data.name)))
175                sensors_fatal_error("sensors_get_label",
176                                    "Allocating label text");
177        return 0;
178}
179
180int sensors_get_ignored(sensors_chip_name name, int feature)
181{
182        const sensors_chip *chip;
183        const sensors_chip_feature *featureptr;
184        const sensors_chip_feature *alt_featureptr;
185        int i, res;
186
187        /* Default: valid */
188        res = 1;
189        if (sensors_chip_name_has_wildcards(name))
190                return -SENSORS_ERR_WILDCARDS;
191        if (!(featureptr = sensors_lookup_feature_nr(&name, feature)))
192                return -SENSORS_ERR_NO_ENTRY;
193        if (featureptr->data.mapping == SENSORS_NO_MAPPING)
194                alt_featureptr = NULL;
195        else if (!(alt_featureptr =
196                   sensors_lookup_feature_nr(&name,
197                                             featureptr->data.mapping)))
198                return -SENSORS_ERR_NO_ENTRY;
199        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
200                for (i = 0; i < chip->ignores_count; i++)
201                        if (!strcasecmp(featureptr->data.name, chip->ignores[i].name))
202                                return 0; /* Exact match always overrules! */
203                        else if (alt_featureptr &&
204                                 !strcasecmp(alt_featureptr->data.name,
205                                             chip->ignores[i].name))
206                                res = 0;
207        return res;
208}
209
210/* Read the value of a feature of a certain chip. Note that chip should not
211   contain wildcard values! This function will return 0 on success, and <0
212   on failure. */
213int sensors_get_feature(sensors_chip_name name, int feature, double *result)
214{
215        const sensors_chip_feature *main_feature;
216        const sensors_chip_feature *alt_feature;
217        const sensors_chip *chip;
218        const sensors_expr *expr = NULL;
219        double val;
220        int res, i;
221        int final_expr = 0;
222
223        if (sensors_chip_name_has_wildcards(name))
224                return -SENSORS_ERR_WILDCARDS;
225        if (!(main_feature = sensors_lookup_feature_nr(&name, feature)))
226                return -SENSORS_ERR_NO_ENTRY;
227        if (main_feature->data.compute_mapping == SENSORS_NO_MAPPING)
228                alt_feature = NULL;
229        else if (!(alt_feature = sensors_lookup_feature_nr(&name,
230                                        main_feature->data.compute_mapping)))
231                return -SENSORS_ERR_NO_ENTRY;
232        if (!(main_feature->data.mode & SENSORS_MODE_R))
233                return -SENSORS_ERR_ACCESS_R;
234        for (chip = NULL;
235             !expr && (chip = sensors_for_all_config_chips(name, chip));)
236                for (i = 0; !final_expr && (i < chip->computes_count); i++) {
237                        if (!strcasecmp(main_feature->data.name, chip->computes[i].name)) {
238                                expr = chip->computes[i].from_proc;
239                                final_expr = 1;
240                        } else if (alt_feature && !strcasecmp(alt_feature->data.name,
241                                               chip->computes[i].name)) {
242                                expr = chip->computes[i].from_proc;
243                        }
244                }
245        if (sensors_read_proc(name, feature, &val))
246                return -SENSORS_ERR_PROC;
247        if (!expr)
248                *result = val;
249        else if ((res = sensors_eval_expr(name, expr, val, result)))
250                return res;
251        return 0;
252}
253
254/* Set the value of a feature of a certain chip. Note that chip should not
255   contain wildcard values! This function will return 0 on success, and <0
256   on failure. */
257int sensors_set_feature(sensors_chip_name name, int feature, double value)
258{
259        const sensors_chip_feature *main_feature;
260        const sensors_chip_feature *alt_feature;
261        const sensors_chip *chip;
262        const sensors_expr *expr = NULL;
263        int i, res;
264        int final_expr = 0;
265        double to_write;
266
267        if (sensors_chip_name_has_wildcards(name))
268                return -SENSORS_ERR_WILDCARDS;
269        if (!(main_feature = sensors_lookup_feature_nr(&name, feature)))
270                return -SENSORS_ERR_NO_ENTRY;
271        if (main_feature->data.compute_mapping == SENSORS_NO_MAPPING)
272                alt_feature = NULL;
273        else if (!(alt_feature = sensors_lookup_feature_nr(&name,
274                                             main_feature->data.compute_mapping)))
275                return -SENSORS_ERR_NO_ENTRY;
276        if (!(main_feature->data.mode & SENSORS_MODE_W))
277                return -SENSORS_ERR_ACCESS_W;
278        for (chip = NULL;
279             !expr && (chip = sensors_for_all_config_chips(name, chip));)
280                for (i = 0; !final_expr && (i < chip->computes_count); i++)
281                        if (!strcasecmp(main_feature->data.name, chip->computes[i].name)) {
282                                expr = chip->computes->to_proc;
283                                final_expr = 1;
284                        } else if (alt_feature && !strcasecmp(alt_feature->data.name,
285                                               chip->computes[i].name)) {
286                                expr = chip->computes[i].to_proc;
287                        }
288
289        to_write = value;
290        if (expr)
291                if ((res = sensors_eval_expr(name, expr, value, &to_write)))
292                        return res;
293        if (sensors_write_proc(name, feature, to_write))
294                return -SENSORS_ERR_PROC;
295        return 0;
296}
297
298const sensors_chip_name *sensors_get_detected_chips(int *nr)
299{
300        const sensors_chip_name *res;
301        res = (*nr >= sensors_proc_chips_count ?
302                        NULL : &sensors_proc_chips[*nr].chip);
303        (*nr)++;
304        return res;
305}
306
307const char *sensors_get_adapter_name(int bus_nr)
308{
309        int i;
310
311        if (bus_nr == SENSORS_CHIP_NAME_BUS_ISA)
312                return "ISA adapter";
313        if (bus_nr == SENSORS_CHIP_NAME_BUS_PCI)
314                return "PCI adapter";
315        if (bus_nr == SENSORS_CHIP_NAME_BUS_DUMMY)
316                return "Dummy adapter";
317        for (i = 0; i < sensors_proc_bus_count; i++)
318                if (sensors_proc_bus[i].number == bus_nr)
319                        return sensors_proc_bus[i].adapter;
320        return NULL;
321}
322
323/* nr1-1 is the last main feature found; nr2-1 is the last subfeature found */
324const sensors_feature_data *sensors_get_all_features(sensors_chip_name name,
325                                                     int *nr1, int *nr2)
326{
327        sensors_chip_feature *feature_list;
328        int i;
329
330        for (i = 0; i < sensors_proc_chips_count; i++)
331                if (sensors_match_chip(sensors_proc_chips[i].chip, name)) {
332                        feature_list = sensors_proc_chips[i].feature;
333                        if (!*nr1 && !*nr2) {   /* Return the first entry */
334                                if (!feature_list[0].data.name) /* The list may be empty */
335                                        return NULL;
336                                *nr1 = *nr2 = 1;
337                                return &feature_list->data;
338                        }
339                        for ((*nr2)++; feature_list[*nr2 - 1].data.name; (*nr2)++)
340                                if (feature_list[*nr2 - 1].data.mapping ==
341                                    feature_list[*nr1 - 1].data.number)
342                                        return &((feature_list + *nr2 - 1)->data);
343                        for ((*nr1)++;
344                             feature_list[*nr1 - 1].data.name
345                             && (feature_list[*nr1 - 1].data.mapping !=
346                                 SENSORS_NO_MAPPING); (*nr1)++) ;
347                        *nr2 = *nr1;
348                        if (!feature_list[*nr1 - 1].data.name)
349                                return NULL;
350                        return &((feature_list + *nr1 - 1)->data);
351                }
352        return NULL;
353}
354
355/* Evaluate an expression */
356int sensors_eval_expr(sensors_chip_name chipname, const sensors_expr * expr,
357                      double val, double *result)
358{
359        double res1, res2;
360        int res;
361        const sensors_chip_feature *feature;
362
363        if (expr->kind == sensors_kind_val) {
364                *result = expr->data.val;
365                return 0;
366        }
367        if (expr->kind == sensors_kind_source) {
368                *result = val;
369                return 0;
370        }
371        if (expr->kind == sensors_kind_var) {
372                if (!(feature = sensors_lookup_feature_name(&chipname,
373                                                            expr->data.var)))
374                        return SENSORS_ERR_NO_ENTRY;
375                if (!(res = sensors_get_feature(chipname, feature->data.number, result)))
376                        return res;
377                return 0;
378        }
379        if ((res = sensors_eval_expr(chipname, expr->data.subexpr.sub1, val, &res1)))
380                return res;
381        if (expr->data.subexpr.sub2 &&
382            (res = sensors_eval_expr(chipname, expr->data.subexpr.sub2, val, &res2)))
383                return res;
384        switch (expr->data.subexpr.op) {
385        case sensors_add:
386                *result = res1 + res2;
387                return 0;
388        case sensors_sub:
389                *result = res1 - res2;
390                return 0;
391        case sensors_multiply:
392                *result = res1 * res2;
393                return 0;
394        case sensors_divide:
395                if (res2 == 0.0)
396                        return -SENSORS_ERR_DIV_ZERO;
397                *result = res1 / res2;
398                return 0;
399        case sensors_negate:
400                *result = -res1;
401                return 0;
402        case sensors_exp:
403                *result = exp(res1);
404                return 0;
405        case sensors_log:
406                if (res1 < 0.0)
407                        return -SENSORS_ERR_DIV_ZERO;
408                *result = log(res1);
409                return 0;
410        }
411        return 0;
412}
413
414/* Execute all set statements for this particular chip. The chip may not
415   contain wildcards!  This function will return 0 on success, and <0 on
416   failure. */
417static int sensors_do_this_chip_sets(sensors_chip_name name)
418{
419        sensors_chip *chip;
420        double value;
421        int i, j;
422        int err = 0, res;
423        const sensors_chip_feature *feature;
424        int *feature_list = NULL;
425        int feature_count = 0;
426        int feature_max = 0;
427        int feature_nr;
428
429        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
430                for (i = 0; i < chip->sets_count; i++) {
431                        feature = sensors_lookup_feature_name(&name,
432                                                        chip->sets[i].name);
433                        if (!feature) {
434                                sensors_parse_error("Unknown feature name",
435                                                    chip->sets[i].lineno);
436                                err = SENSORS_ERR_NO_ENTRY;
437                                continue;
438                        }
439                        feature_nr = feature->data.number;
440
441                        /* Check whether we already set this feature */
442                        for (j = 0; j < feature_count; j++)
443                                if (feature_list[j] == feature_nr)
444                                        break;
445                        if (j != feature_count)
446                                continue;
447                        sensors_add_array_el(&feature_nr, &feature_list,
448                                             &feature_count, &feature_max,
449                                             sizeof(int));
450
451                        res = sensors_eval_expr(name, chip->sets[i].value, 0,
452                                              &value);
453                        if (res) {
454                                sensors_parse_error("Error parsing expression",
455                                                    chip->sets[i].lineno);
456                                err = res;
457                                continue;
458                        }
459                        if ((res = sensors_set_feature(name, feature_nr, value))) {
460                                sensors_parse_error("Failed to set feature",
461                                                chip->sets[i].lineno);
462                                err = res;
463                                continue;
464                        }
465                }
466        free(feature_list);
467        return err;
468}
469
470/* Execute all set statements for this particular chip. The chip may contain
471   wildcards!  This function will return 0 on success, and <0 on failure. */
472int sensors_do_chip_sets(sensors_chip_name name)
473{
474        int nr, this_res;
475        const sensors_chip_name *found_name;
476        int res = 0;
477
478        for (nr = 0; (found_name = sensors_get_detected_chips(&nr));)
479                if (sensors_match_chip(name, *found_name)) {
480                        this_res = sensors_do_this_chip_sets(*found_name);
481                        if (!res)
482                                res = this_res;
483                }
484        return res;
485}
486
487/* Execute all set statements for all detected chips. This is the same as
488   calling sensors_do_chip_sets with an all wildcards chip name */
489int sensors_do_all_sets(void)
490{
491        static const sensors_chip_name name = {
492                .prefix = SENSORS_CHIP_NAME_PREFIX_ANY,
493                .bus    = SENSORS_CHIP_NAME_BUS_ANY,
494                .addr   = SENSORS_CHIP_NAME_ADDR_ANY,
495        };
496        return sensors_do_chip_sets(name);
497}
498
499/* Static mappings for use by sensors_feature_get_type() */
500struct feature_subtype_match
501{
502        const char *name;
503        sensors_feature_type type;
504};
505
506struct feature_type_match
507{
508        const char *name;
509        sensors_feature_type type;
510       
511        const struct feature_subtype_match *submatches;
512};
513
514static const struct feature_subtype_match temp_matches[] = {
515        { "max", SENSORS_FEATURE_TEMP_MAX },
516        { "max_hyst", SENSORS_FEATURE_TEMP_MAX_HYST },
517        { "min", SENSORS_FEATURE_TEMP_MIN },
518        { "crit", SENSORS_FEATURE_TEMP_CRIT },
519        { "crit_hyst", SENSORS_FEATURE_TEMP_CRIT_HYST },
520        { "alarm", SENSORS_FEATURE_TEMP_ALARM },
521        { "min_alarm", SENSORS_FEATURE_TEMP_MIN_ALARM },
522        { "max_alarm", SENSORS_FEATURE_TEMP_MAX_ALARM },
523        { "crit_alarm", SENSORS_FEATURE_TEMP_CRIT_ALARM },
524        { "fault", SENSORS_FEATURE_TEMP_FAULT },
525        { "type", SENSORS_FEATURE_TEMP_SENS },
526        { NULL, 0 }
527};
528
529static const struct feature_subtype_match in_matches[] = {
530        { "min", SENSORS_FEATURE_IN_MIN },
531        { "max", SENSORS_FEATURE_IN_MAX },
532        { "alarm", SENSORS_FEATURE_IN_ALARM },
533        { "min_alarm", SENSORS_FEATURE_IN_MIN_ALARM },
534        { "max_alarm", SENSORS_FEATURE_IN_MAX_ALARM },
535        { NULL, 0 }
536};
537
538static const struct feature_subtype_match fan_matches[] = {
539        { "min", SENSORS_FEATURE_FAN_MIN },
540        { "div", SENSORS_FEATURE_FAN_DIV },
541        { "alarm", SENSORS_FEATURE_FAN_ALARM },
542        { "fault", SENSORS_FEATURE_FAN_FAULT },
543        { NULL, 0 }
544};
545
546static const struct feature_subtype_match cpu_matches[] = {
547        { "vid", SENSORS_FEATURE_VID },
548        { NULL, 0 }
549};
550
551static struct feature_type_match matches[] = { 
552        { "temp%d%c", SENSORS_FEATURE_TEMP, temp_matches },
553        { "in%d%c", SENSORS_FEATURE_IN, in_matches },
554        { "fan%d%c", SENSORS_FEATURE_FAN, fan_matches },
555        { "cpu%d%c", SENSORS_FEATURE_UNKNOWN, cpu_matches },
556};
557
558/* Return the feature type based on the feature name */
559sensors_feature_type sensors_feature_get_type(
560        const sensors_feature_data *feature)
561{
562        char c;
563        int i, nr, count;
564        const struct feature_subtype_match *submatches;
565       
566        for (i = 0; i < ARRAY_SIZE(matches); i++)
567                if ((count = sscanf(feature->name, matches[i].name, &nr, &c)))
568                        break;
569       
570        if (i == ARRAY_SIZE(matches)) /* no match */
571                return SENSORS_FEATURE_UNKNOWN;
572        else if (count == 1) /* single type */
573                return matches[i].type;
574
575        /* assert: count == 2 */
576        if (c != '_')
577                return SENSORS_FEATURE_UNKNOWN;
578
579        submatches = matches[i].submatches;
580        for (i = 0; submatches[i].name != NULL; i++)
581                if (!strcmp(strchr(feature->name, '_') + 1, submatches[i].name))
582                        return submatches[i].type;
583       
584        return SENSORS_FEATURE_UNKNOWN;
585}
Note: See TracBrowser for help on using the browser.