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

Revision 5163, 15.2 KB (checked in by khali, 7 years ago)

Patch from Aurelien Jarno:

I have just noticed that the FSF address is the old one in all files
except COPYING. Please find a patch below to fix that.

  • 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    Copyright (C) 2007        Jean Delvare <khali@linux-fr.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19    MA 02110-1301 USA.
20*/
21
22#include <stdlib.h>
23#include <string.h>
24#include <math.h>
25#include "access.h"
26#include "sensors.h"
27#include "data.h"
28#include "error.h"
29#include "sysfs.h"
30#include "general.h"
31
32static int sensors_eval_expr(const sensors_chip_features *chip_features,
33                             const sensors_expr *expr,
34                             double val, double *result);
35
36/* Compare two chips name descriptions, to see whether they could match.
37   Return 0 if it does not match, return 1 if it does match. */
38static int sensors_match_chip(const sensors_chip_name *chip1,
39                       const sensors_chip_name *chip2)
40{
41        if ((chip1->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
42            (chip2->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
43            strcmp(chip1->prefix, chip2->prefix))
44                return 0;
45
46        if ((chip1->bus.type != SENSORS_BUS_TYPE_ANY) &&
47            (chip2->bus.type != SENSORS_BUS_TYPE_ANY) &&
48            (chip1->bus.type != chip2->bus.type))
49                return 0;
50
51        if ((chip1->bus.nr != SENSORS_BUS_NR_ANY) &&
52            (chip2->bus.nr != SENSORS_BUS_NR_ANY) &&
53            (chip1->bus.nr != chip2->bus.nr))
54                return 0;
55
56        if ((chip1->addr != chip2->addr) &&
57            (chip1->addr != SENSORS_CHIP_NAME_ADDR_ANY) &&
58            (chip2->addr != SENSORS_CHIP_NAME_ADDR_ANY))
59                return 0;
60
61        return 1;
62}
63
64/* Returns, one by one, a pointer to all sensor_chip structs of the
65   config file which match with the given chip name. Last should be
66   the value returned by the last call, or NULL if this is the first
67   call. Returns NULL if no more matches are found. Do not modify
68   the struct the return value points to!
69   Note that this visits the list of chips from last to first. Usually,
70   you want the match that was latest in the config file. */
71static sensors_chip *
72sensors_for_all_config_chips(const sensors_chip_name *name,
73                             const sensors_chip *last)
74{
75        int nr, i;
76        sensors_chip_name_list chips;
77
78        for (nr = last ? last - sensors_config_chips - 1 :
79                         sensors_config_chips_count - 1; nr >= 0; nr--) {
80
81                chips = sensors_config_chips[nr].chips;
82                for (i = 0; i < chips.fits_count; i++) {
83                        if (sensors_match_chip(&chips.fits[i], name))
84                                return sensors_config_chips + nr;
85                }
86        }
87        return NULL;
88}
89
90/* Look up a chip in the intern chip list, and return a pointer to it.
91   Do not modify the struct the return value points to! Returns NULL if
92   not found.*/
93static const sensors_chip_features *
94sensors_lookup_chip(const sensors_chip_name *name)
95{
96        int i;
97
98        for (i = 0; i < sensors_proc_chips_count; i++)
99                if (sensors_match_chip(&sensors_proc_chips[i].chip, name))
100                        return &sensors_proc_chips[i];
101
102        return NULL;
103}
104
105/* Look up a subfeature of the given chip, and return a pointer to it.
106   Do not modify the struct the return value points to! Returns NULL if
107   not found.*/
108static const sensors_subfeature *
109sensors_lookup_subfeature_nr(const sensors_chip_features *chip,
110                             int subfeat_nr)
111{
112        if (subfeat_nr < 0 ||
113            subfeat_nr >= chip->subfeature_count)
114                return NULL;
115        return chip->subfeature + subfeat_nr;
116}
117
118/* Look up a feature of the given chip, and return a pointer to it.
119   Do not modify the struct the return value points to! Returns NULL if
120   not found.*/
121static const sensors_feature *
122sensors_lookup_feature_nr(const sensors_chip_features *chip, int feat_nr)
123{
124        if (feat_nr < 0 ||
125            feat_nr >= chip->feature_count)
126                return NULL;
127        return chip->feature + feat_nr;
128}
129
130/* Look up a subfeature by name, and return a pointer to it.
131   Do not modify the struct the return value points to! Returns NULL if
132   not found.*/
133static const sensors_subfeature *
134sensors_lookup_subfeature_name(const sensors_chip_features *chip,
135                               const char *name)
136{
137        int j;
138
139        for (j = 0; j < chip->subfeature_count; j++)
140                if (!strcmp(chip->subfeature[j].name, name))
141                        return chip->subfeature + j;
142        return NULL;
143}
144
145/* Check whether the chip name is an 'absolute' name, which can only match
146   one chip, or whether it has wildcards. Returns 0 if it is absolute, 1
147   if there are wildcards. */
148int sensors_chip_name_has_wildcards(const sensors_chip_name *chip)
149{
150        if ((chip->prefix == SENSORS_CHIP_NAME_PREFIX_ANY) ||
151            (chip->bus.type == SENSORS_BUS_TYPE_ANY) ||
152            (chip->bus.nr == SENSORS_BUS_NR_ANY) ||
153            (chip->addr == SENSORS_CHIP_NAME_ADDR_ANY))
154                return 1;
155        else
156                return 0;
157}
158
159/* Look up the label for a given feature. Note that chip should not
160   contain wildcard values! The returned string is newly allocated (free it
161   yourself). On failure, NULL is returned.
162   If no label exists for this feature, its name is returned itself. */
163char *sensors_get_label(const sensors_chip_name *name,
164                        const sensors_feature *feature)
165{
166        char *label;
167        const sensors_chip *chip;
168        char buf[128], path[PATH_MAX];
169        FILE *f;
170        int i;
171
172        if (sensors_chip_name_has_wildcards(name))
173                return NULL;
174
175        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
176                for (i = 0; i < chip->labels_count; i++)
177                        if (!strcmp(feature->name, chip->labels[i].name)) {
178                                label = strdup(chip->labels[i].value);
179                                goto sensors_get_label_exit;
180                        }
181
182        /* No user specified label, check for a _label sysfs file */
183        snprintf(path, PATH_MAX, "%s/%s_label", name->path, feature->name);
184       
185        if ((f = fopen(path, "r"))) {
186                i = fread(buf, 1, sizeof(buf) - 1, f);
187                fclose(f);
188                if (i > 0) {
189                        /* i - 1 to strip the '\n' at the end */
190                        buf[i - 1] = 0;
191                        label = strdup(buf);
192                        goto sensors_get_label_exit;
193                }
194        }
195
196        /* No label, return the feature name instead */
197        label = strdup(feature->name);
198       
199sensors_get_label_exit:
200        if (!label)
201                sensors_fatal_error("sensors_get_label",
202                                    "Allocating label text");
203        return label;
204}
205
206/* Looks up whether a feature should be ignored. Returns
207   1 if it should be ignored, 0 if not. */
208static int sensors_get_ignored(const sensors_chip_name *name,
209                               const sensors_feature *feature)
210{
211        const sensors_chip *chip;
212        int i;
213
214        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
215                for (i = 0; i < chip->ignores_count; i++)
216                        if (!strcmp(feature->name, chip->ignores[i].name))
217                                return 1;
218        return 0;
219}
220
221/* Read the value of a subfeature of a certain chip. Note that chip should not
222   contain wildcard values! This function will return 0 on success, and <0
223   on failure. */
224int sensors_get_value(const sensors_chip_name *name, int subfeat_nr,
225                      double *result)
226{
227        const sensors_chip_features *chip_features;
228        const sensors_subfeature *subfeature;
229        const sensors_expr *expr = NULL;
230        double val;
231        int res, i;
232
233        if (sensors_chip_name_has_wildcards(name))
234                return -SENSORS_ERR_WILDCARDS;
235        if (!(chip_features = sensors_lookup_chip(name)))
236                return -SENSORS_ERR_NO_ENTRY;
237        if (!(subfeature = sensors_lookup_subfeature_nr(chip_features,
238                                                        subfeat_nr)))
239                return -SENSORS_ERR_NO_ENTRY;
240        if (!(subfeature->flags & SENSORS_MODE_R))
241                return -SENSORS_ERR_ACCESS_R;
242
243        /* Apply compute statement if it exists */
244        if (subfeature->flags & SENSORS_COMPUTE_MAPPING) {
245                const sensors_feature *feature;
246                const sensors_chip *chip;
247
248                feature = sensors_lookup_feature_nr(chip_features,
249                                        subfeature->mapping);
250
251                chip = NULL;
252                while ((chip = sensors_for_all_config_chips(name, chip)))
253                        for (i = 0; i < chip->computes_count; i++) {
254                                if (!strcmp(feature->name,
255                                            chip->computes[i].name)) {
256                                        expr = chip->computes[i].from_proc;
257                                        break;
258                                }
259                        }
260        }
261
262        res = sensors_read_sysfs_attr(name, subfeature, &val);
263        if (res)
264                return res;
265        if (!expr)
266                *result = val;
267        else if ((res = sensors_eval_expr(chip_features, expr, val, result)))
268                return res;
269        return 0;
270}
271
272/* Set the value of a subfeature of a certain chip. Note that chip should not
273   contain wildcard values! This function will return 0 on success, and <0
274   on failure. */
275int sensors_set_value(const sensors_chip_name *name, int subfeat_nr,
276                      double value)
277{
278        const sensors_chip_features *chip_features;
279        const sensors_subfeature *subfeature;
280        const sensors_expr *expr = NULL;
281        int i, res;
282        double to_write;
283
284        if (sensors_chip_name_has_wildcards(name))
285                return -SENSORS_ERR_WILDCARDS;
286        if (!(chip_features = sensors_lookup_chip(name)))
287                return -SENSORS_ERR_NO_ENTRY;
288        if (!(subfeature = sensors_lookup_subfeature_nr(chip_features,
289                                                        subfeat_nr)))
290                return -SENSORS_ERR_NO_ENTRY;
291        if (!(subfeature->flags & SENSORS_MODE_W))
292                return -SENSORS_ERR_ACCESS_W;
293
294        /* Apply compute statement if it exists */
295        if (subfeature->flags & SENSORS_COMPUTE_MAPPING) {
296                const sensors_feature *feature;
297                const sensors_chip *chip;
298
299                feature = sensors_lookup_feature_nr(chip_features,
300                                        subfeature->mapping);
301
302                chip = NULL;
303                while ((chip = sensors_for_all_config_chips(name, chip)))
304                        for (i = 0; i < chip->computes_count; i++) {
305                                if (!strcmp(feature->name,
306                                            chip->computes[i].name)) {
307                                        expr = chip->computes[i].to_proc;
308                                        break;
309                                }
310                        }
311        }
312
313        to_write = value;
314        if (expr)
315                if ((res = sensors_eval_expr(chip_features, expr,
316                                             value, &to_write)))
317                        return res;
318        return sensors_write_sysfs_attr(name, subfeature, to_write);
319}
320
321const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name
322                                                    *match, int *nr)
323{
324        const sensors_chip_name *res;
325
326        while (*nr < sensors_proc_chips_count) {
327                res = &sensors_proc_chips[(*nr)++].chip;
328                if (!match || sensors_match_chip(res, match))
329                        return res;
330        }
331        return NULL;
332}
333
334const char *sensors_get_adapter_name(const sensors_bus_id *bus)
335{
336        int i;
337
338        /* bus types with a single instance */
339        switch (bus->type) {
340        case SENSORS_BUS_TYPE_ISA:
341                return "ISA adapter";
342        case SENSORS_BUS_TYPE_PCI:
343                return "PCI adapter";
344        /* SPI should not be here, but for now SPI adapters have no name
345           so we don't have any custom string to return. */
346        case SENSORS_BUS_TYPE_SPI:
347                return "SPI adapter";
348        }
349
350        /* bus types with several instances */
351        for (i = 0; i < sensors_proc_bus_count; i++)
352                if (sensors_proc_bus[i].bus.type == bus->type &&
353                    sensors_proc_bus[i].bus.nr == bus->nr)
354                        return sensors_proc_bus[i].adapter;
355        return NULL;
356}
357
358const sensors_feature *
359sensors_get_features(const sensors_chip_name *name, int *nr)
360{
361        const sensors_chip_features *chip;
362
363        if (!(chip = sensors_lookup_chip(name)))
364                return NULL;    /* No such chip */
365
366        while (*nr < chip->feature_count
367            && sensors_get_ignored(name, &chip->feature[*nr]))
368                (*nr)++;
369        if (*nr >= chip->feature_count)
370                return NULL;
371        return &chip->feature[(*nr)++];
372}
373
374const sensors_subfeature *
375sensors_get_all_subfeatures(const sensors_chip_name *name,
376                        const sensors_feature *feature, int *nr)
377{
378        const sensors_chip_features *chip;
379        const sensors_subfeature *subfeature;
380
381        if (!(chip = sensors_lookup_chip(name)))
382                return NULL;    /* No such chip */
383
384        /* Seek directly to the first subfeature */
385        if (*nr < feature->first_subfeature)
386                *nr = feature->first_subfeature;
387
388        if (*nr >= chip->subfeature_count)
389                return NULL;    /* end of list */
390        subfeature = &chip->subfeature[(*nr)++];
391        if (subfeature->mapping == feature->number)
392                return subfeature;
393        return NULL;    /* end of subfeature list */
394}
395
396const sensors_subfeature *
397sensors_get_subfeature(const sensors_chip_name *name,
398                       const sensors_feature *feature,
399                       sensors_subfeature_type type)
400{
401        const sensors_chip_features *chip;
402        int i;
403
404        if (!(chip = sensors_lookup_chip(name)))
405                return NULL;    /* No such chip */
406
407        for (i = feature->first_subfeature; i < chip->subfeature_count &&
408             chip->subfeature[i].mapping == feature->number; i++) {
409                if (chip->subfeature[i].type == type)
410                        return &chip->subfeature[i];
411        }
412        return NULL;    /* No such subfeature */
413}
414
415/* Evaluate an expression */
416int sensors_eval_expr(const sensors_chip_features *chip_features,
417                      const sensors_expr *expr,
418                      double val, double *result)
419{
420        double res1, res2;
421        int res;
422        const sensors_subfeature *subfeature;
423
424        if (expr->kind == sensors_kind_val) {
425                *result = expr->data.val;
426                return 0;
427        }
428        if (expr->kind == sensors_kind_source) {
429                *result = val;
430                return 0;
431        }
432        if (expr->kind == sensors_kind_var) {
433                if (!(subfeature = sensors_lookup_subfeature_name(chip_features,
434                                                            expr->data.var)))
435                        return -SENSORS_ERR_NO_ENTRY;
436                if (!(res = sensors_get_value(&chip_features->chip,
437                                              subfeature->number, result)))
438                        return res;
439                return 0;
440        }
441        if ((res = sensors_eval_expr(chip_features, expr->data.subexpr.sub1,
442                                     val, &res1)))
443                return res;
444        if (expr->data.subexpr.sub2 &&
445            (res = sensors_eval_expr(chip_features, expr->data.subexpr.sub2,
446                                     val, &res2)))
447                return res;
448        switch (expr->data.subexpr.op) {
449        case sensors_add:
450                *result = res1 + res2;
451                return 0;
452        case sensors_sub:
453                *result = res1 - res2;
454                return 0;
455        case sensors_multiply:
456                *result = res1 * res2;
457                return 0;
458        case sensors_divide:
459                if (res2 == 0.0)
460                        return -SENSORS_ERR_DIV_ZERO;
461                *result = res1 / res2;
462                return 0;
463        case sensors_negate:
464                *result = -res1;
465                return 0;
466        case sensors_exp:
467                *result = exp(res1);
468                return 0;
469        case sensors_log:
470                if (res1 < 0.0)
471                        return -SENSORS_ERR_DIV_ZERO;
472                *result = log(res1);
473                return 0;
474        }
475        return 0;
476}
477
478/* Execute all set statements for this particular chip. The chip may not
479   contain wildcards!  This function will return 0 on success, and <0 on
480   failure. */
481static int sensors_do_this_chip_sets(const sensors_chip_name *name)
482{
483        const sensors_chip_features *chip_features;
484        sensors_chip *chip;
485        double value;
486        int i;
487        int err = 0, res;
488        const sensors_subfeature *subfeature;
489
490        chip_features = sensors_lookup_chip(name);      /* Can't fail */
491
492        for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
493                for (i = 0; i < chip->sets_count; i++) {
494                        subfeature = sensors_lookup_subfeature_name(chip_features,
495                                                        chip->sets[i].name);
496                        if (!subfeature) {
497                                sensors_parse_error("Unknown feature name",
498                                                    chip->sets[i].lineno);
499                                err = -SENSORS_ERR_NO_ENTRY;
500                                continue;
501                        }
502
503                        res = sensors_eval_expr(chip_features,
504                                                chip->sets[i].value, 0,
505                                                &value);
506                        if (res) {
507                                sensors_parse_error("Error parsing expression",
508                                                    chip->sets[i].lineno);
509                                err = res;
510                                continue;
511                        }
512                        if ((res = sensors_set_value(name, subfeature->number,
513                                                     value))) {
514                                sensors_parse_error("Failed to set value",
515                                                chip->sets[i].lineno);
516                                err = res;
517                                continue;
518                        }
519                }
520        return err;
521}
522
523/* Execute all set statements for this particular chip. The chip may contain
524   wildcards!  This function will return 0 on success, and <0 on failure. */
525int sensors_do_chip_sets(const sensors_chip_name *name)
526{
527        int nr, this_res;
528        const sensors_chip_name *found_name;
529        int res = 0;
530
531        for (nr = 0; (found_name = sensors_get_detected_chips(name, &nr));) {
532                this_res = sensors_do_this_chip_sets(found_name);
533                if (this_res)
534                        res = this_res;
535        }
536        return res;
537}
Note: See TracBrowser for help on using the browser.