root/lm-sensors/trunk/lib/access.c

Revision 5079, 15.8 kB (checked in by khali, 1 year ago)

sensors_eval_expr can be made static.

  • 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 <limits.h>
24 #include "access.h"
25 #include "sensors.h"
26 #include "data.h"
27 #include "error.h"
28 #include "proc.h"
29 #include "general.h"
30 #include "sysfs.h"
31
32 static int sensors_eval_expr(sensors_chip_name chipname,
33                              const sensors_expr *expr,
34                              double val, double *result);
35
36 static int sensors_do_this_chip_sets(sensors_chip_name name);
37
38 /* Compare two chips name descriptions, to see whether they could match.
39    Return 0 if it does not match, return 1 if it does match. */
40 int sensors_match_chip(sensors_chip_name chip1, sensors_chip_name chip2)
41 {
42         if ((chip1.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
43             (chip2.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
44             strcasecmp(chip1.prefix, chip2.prefix))
45                 return 0;
46
47         if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY) &&
48             (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY) &&
49             (chip1.bus != chip2.bus)) {
50
51                 if ((chip1.bus == SENSORS_CHIP_NAME_BUS_ISA) ||
52                     (chip2.bus == SENSORS_CHIP_NAME_BUS_ISA))
53                         return 0;
54
55                 if ((chip1.bus == SENSORS_CHIP_NAME_BUS_PCI) ||
56                     (chip2.bus == SENSORS_CHIP_NAME_BUS_PCI))
57                         return 0;
58
59                 if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C) &&
60                     (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
61                         return 0;
62         }
63
64         if ((chip1.addr != chip2.addr) &&
65             (chip1.addr != SENSORS_CHIP_NAME_ADDR_ANY) &&
66             (chip2.addr != SENSORS_CHIP_NAME_ADDR_ANY))
67                 return 0;
68
69         return 1;
70 }
71
72 /* Returns, one by one, a pointer to all sensor_chip structs of the
73    config file which match with the given chip name. Last should be
74    the value returned by the last call, or NULL if this is the first
75    call. Returns NULL if no more matches are found. Do not modify
76    the struct the return value points to!
77    Note that this visits the list of chips from last to first. Usually,
78    you want the match that was latest in the config file. */
79 sensors_chip *sensors_for_all_config_chips(sensors_chip_name chip_name,
80                                            const sensors_chip * last)
81 {
82         int nr, i;
83         sensors_chip_name_list chips;
84
85         for (nr = last ? last - sensors_config_chips - 1 :
86                          sensors_config_chips_count - 1; nr >= 0; nr--) {
87
88                 chips = sensors_config_chips[nr].chips;
89                 for (i = 0; i < chips.fits_count; i++) {
90                         if (sensors_match_chip(chips.fits[i], chip_name))
91                                 return sensors_config_chips + nr;
92                 }
93         }
94         return NULL;
95 }
96
97 /* Look up a resource in the intern chip list, and return a pointer to it.
98    Do not modify the struct the return value points to! Returns NULL if
99    not found.*/
100 const sensors_chip_feature *sensors_lookup_feature_nr(const char *prefix,
101                                                       int feature)
102 {
103         int i, j;
104         const sensors_chip_feature *features;
105
106         for (i = 0; sensors_chip_features_list[i].prefix; i++)
107                 if (!strcasecmp(sensors_chip_features_list[i].prefix, prefix)) {
108                         features = sensors_chip_features_list[i].feature;
109                         for (j = 0; features[j].data.name; j++)
110                                 if (features[j].data.number == feature)
111                                         return features + j;
112                 }
113         return NULL;
114 }
115
116 /* Look up a resource in the intern chip list, and return a pointer to it.
117    Do not modify the struct the return value points to! Returns NULL if
118    not found.*/
119 const sensors_chip_feature *sensors_lookup_feature_name(const char *prefix,
120                                                         const char *feature)
121 {
122         int i, j;
123         const sensors_chip_feature *features;
124
125         for (i = 0; sensors_chip_features_list[i].prefix; i++)
126                 if (!strcasecmp(sensors_chip_features_list[i].prefix, prefix)) {
127                         features = sensors_chip_features_list[i].feature;
128                         for (j = 0; features[j].data.name; j++)
129                                 if (!strcasecmp(features[j].data.name, feature))
130                                         return features + j;
131                 }
132         return NULL;
133 }
134
135 /* Check whether the chip name is an 'absolute' name, which can only match
136    one chip, or whether it has wildcards. Returns 0 if it is absolute, 1
137    if there are wildcards. */
138 int sensors_chip_name_has_wildcards(sensors_chip_name chip)
139 {
140         if ((chip.prefix == SENSORS_CHIP_NAME_PREFIX_ANY) ||
141             (chip.bus == SENSORS_CHIP_NAME_BUS_ANY) ||
142             (chip.bus == SENSORS_CHIP_NAME_BUS_ANY_I2C) ||
143             (chip.addr == SENSORS_CHIP_NAME_ADDR_ANY))
144                 return 1;
145         else
146                 return 0;
147 }
148
149 /* Look up the label which belongs to this chip. Note that chip should not
150    contain wildcard values! *result is newly allocated (free it yourself).
151    This function will return 0 on success, and <0 on failure.
152    If no label exists for this feature, its name is returned itself. */
153 int sensors_get_label(sensors_chip_name name, int feature, char **result)
154 {
155         const sensors_chip *chip;
156         const sensors_chip_feature *featureptr;
157         int i;
158
159         *result = NULL;
160         if (sensors_chip_name_has_wildcards(name))
161                 return -SENSORS_ERR_WILDCARDS;
162         if (!(featureptr = sensors_lookup_feature_nr(name.prefix, feature)))
163                 return -SENSORS_ERR_NO_ENTRY;
164
165         for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
166                 for (i = 0; i < chip->labels_count; i++)
167                         if (!strcasecmp(featureptr->data.name,chip->labels[i].name)){
168                                 *result = strdup(chip->labels[i].value);
169                                 goto sensors_get_label_exit;
170                         }
171
172         if (sensors_found_sysfs) {
173                 char buf[128], path[PATH_MAX];
174                 FILE *f;
175
176                 /* No user specified label, check for a _label sysfs file */
177                 snprintf(path, PATH_MAX, "%s/%s_label", name.busname,
178                         featureptr->data.name);
179
180                 if ((f = fopen(path, "r"))) {
181                         i = fread(buf, 1, sizeof(buf) - 1, f);
182                         fclose(f);
183                         if (i > 0) {
184                                 /* i - 1 to strip the '\n' at the end */
185                                 buf[i - 1] = 0;
186                                 *result = strdup(buf);
187                                 goto sensors_get_label_exit;
188                         }
189                 }
190         }
191
192         /* No label, return the feature name instead */
193         *result = strdup(featureptr->data.name);
194        
195 sensors_get_label_exit:
196         if (*result == NULL)
197                 sensors_fatal_error("sensors_get_label",
198                                     "Allocating label text");
199         return 0;
200 }
201
202 int sensors_get_ignored(sensors_chip_name name, int feature)
203 {
204         const sensors_chip *chip;
205         const sensors_chip_feature *featureptr;
206         const sensors_chip_feature *alt_featureptr;
207         int i;
208
209         if (sensors_chip_name_has_wildcards(name))
210                 return -SENSORS_ERR_WILDCARDS;
211         if (!(featureptr = sensors_lookup_feature_nr(name.prefix, feature)))
212                 return -SENSORS_ERR_NO_ENTRY;
213         if (featureptr->data.mapping == SENSORS_NO_MAPPING)
214                 alt_featureptr = NULL;
215         else if (!(alt_featureptr =
216                    sensors_lookup_feature_nr(name.prefix,
217                                              featureptr->data.mapping)))
218                 return -SENSORS_ERR_NO_ENTRY;
219         for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
220                 for (i = 0; i < chip->ignores_count; i++)
221                         if (!strcasecmp(featureptr->data.name, chip->ignores[i].name) ||
222                             (alt_featureptr &&
223                              !strcasecmp(alt_featureptr->data.name, chip->ignores[i].name)))
224                                 return 0;
225         /* valid */
226         return 1;
227 }
228
229 /* Read the value of a feature of a certain chip. Note that chip should not
230    contain wildcard values! This function will return 0 on success, and <0
231    on failure. */
232 int sensors_get_feature(sensors_chip_name name, int feature, double *result)
233 {
234         const sensors_chip_feature *main_feature;
235         const sensors_chip_feature *alt_feature;
236         const sensors_chip *chip;
237         const sensors_expr *expr = NULL;
238         double val;
239         int res, i;
240         int final_expr = 0;
241
242         if (sensors_chip_name_has_wildcards(name))
243                 return -SENSORS_ERR_WILDCARDS;
244         if (!(main_feature = sensors_lookup_feature_nr(name.prefix, feature)))
245                 return -SENSORS_ERR_NO_ENTRY;
246         if (main_feature->data.compute_mapping == SENSORS_NO_MAPPING)
247                 alt_feature = NULL;
248         else if (!(alt_feature = sensors_lookup_feature_nr(name.prefix,
249                                         main_feature->data.compute_mapping)))
250                 return -SENSORS_ERR_NO_ENTRY;
251         if (!(main_feature->data.mode & SENSORS_MODE_R))
252                 return -SENSORS_ERR_ACCESS_R;
253         for (chip = NULL;
254              !expr && (chip = sensors_for_all_config_chips(name, chip));)
255                 for (i = 0; !final_expr && (i < chip->computes_count); i++) {
256                         if (!strcasecmp(main_feature->data.name, chip->computes[i].name)) {
257                                 expr = chip->computes[i].from_proc;
258                                 final_expr = 1;
259                         } else if (alt_feature && !strcasecmp(alt_feature->data.name,
260                                                chip->computes[i].name)) {
261                                 expr = chip->computes[i].from_proc;
262                         }
263                 }
264         if (sensors_read_proc(name, feature, &val))
265                 return -SENSORS_ERR_PROC;
266         if (!expr)
267                 *result = val;
268         else if ((res = sensors_eval_expr(name, expr, val, result)))
269                 return res;
270         return 0;
271 }
272
273 /* Set the value of a feature of a certain chip. Note that chip should not
274    contain wildcard values! This function will return 0 on success, and <0
275    on failure. */
276 int sensors_set_feature(sensors_chip_name name, int feature, double value)
277 {
278         const sensors_chip_feature *main_feature;
279         const sensors_chip_feature *alt_feature;
280         const sensors_chip *chip;
281         const sensors_expr *expr = NULL;
282         int i, res;
283         int final_expr = 0;
284         double to_write;
285
286         if (sensors_chip_name_has_wildcards(name))
287                 return -SENSORS_ERR_WILDCARDS;
288         if (!(main_feature = sensors_lookup_feature_nr(name.prefix, feature)))
289                 return -SENSORS_ERR_NO_ENTRY;
290         if (main_feature->data.compute_mapping == SENSORS_NO_MAPPING)
291                 alt_feature = NULL;
292         else if (!(alt_feature = sensors_lookup_feature_nr(name.prefix,
293                                              main_feature->data.compute_mapping)))
294                 return -SENSORS_ERR_NO_ENTRY;
295         if (!(main_feature->data.mode & SENSORS_MODE_W))
296                 return -SENSORS_ERR_ACCESS_W;
297         for (chip = NULL;
298              !expr && (chip = sensors_for_all_config_chips(name, chip));)
299                 for (i = 0; !final_expr && (i < chip->computes_count); i++)
300                         if (!strcasecmp(main_feature->data.name, chip->computes[i].name)) {
301                                 expr = chip->computes->to_proc;
302                                 final_expr = 1;
303                         } else if (alt_feature && !strcasecmp(alt_feature->data.name,
304                                                chip->computes[i].name)) {
305                                 expr = chip->computes[i].to_proc;
306                         }
307
308         to_write = value;
309         if (expr)
310                 if ((res = sensors_eval_expr(name, expr, value, &to_write)))
311                         return res;
312         if (sensors_write_proc(name, feature, to_write))
313                 return -SENSORS_ERR_PROC;
314         return 0;
315 }
316
317 const sensors_chip_name *sensors_get_detected_chips(int *nr)
318 {
319         const sensors_chip_name *res;
320         res = (*nr >= sensors_proc_chips_count ?
321                         NULL : &sensors_proc_chips[*nr].name);
322         (*nr)++;
323         return res;
324 }
325
326 const char *sensors_get_adapter_name(int bus_nr)
327 {
328         int i;
329
330         if (bus_nr == SENSORS_CHIP_NAME_BUS_ISA)
331                 return "ISA adapter";
332         if (bus_nr == SENSORS_CHIP_NAME_BUS_PCI)
333                 return "PCI adapter";
334         if (bus_nr == SENSORS_CHIP_NAME_BUS_DUMMY)
335                 return "Dummy adapter";
336         for (i = 0; i < sensors_proc_bus_count; i++)
337                 if (sensors_proc_bus[i].number == bus_nr)
338                         return sensors_proc_bus[i].adapter;
339         return NULL;
340 }
341
342 /* This function is deprecated and will be dropped soon. */
343 const char *sensors_get_algorithm_name(int bus_nr)
344 {
345         return "No longer available";
346 }
347
348 /* nr1-1 is the last main feature found; nr2-1 is the last subfeature found */
349 const sensors_feature_data *sensors_get_all_features(sensors_chip_name name,
350                                                      int *nr1, int *nr2)
351 {
352         sensors_chip_feature *feature_list;
353         int i;
354
355         for (i = 0; sensors_chip_features_list[i].prefix; i++)
356                 if (!strcasecmp(sensors_chip_features_list[i].prefix, name.prefix)) {
357                         feature_list = sensors_chip_features_list[i].feature;
358                         if (!*nr1 && !*nr2) {   /* Return the first entry */
359                                 if (!feature_list[0].data.name) /* The list may be empty */
360                                         return NULL;
361                                 *nr1 = *nr2 = 1;
362                                 return &feature_list->data;
363                         }
364                         for ((*nr2)++; feature_list[*nr2 - 1].data.name; (*nr2)++)
365                                 if (feature_list[*nr2 - 1].data.mapping ==
366                                     feature_list[*nr1 - 1].data.number)
367                                         return &((feature_list + *nr2 - 1)->data);
368                         for ((*nr1)++;
369                              feature_list[*nr1 - 1].data.name
370                              && (feature_list[*nr1 - 1].data.mapping !=
371                                  SENSORS_NO_MAPPING); (*nr1)++) ;
372                         *nr2 = *nr1;
373                         if (!feature_list[*nr1 - 1].data.name)
374                                 return NULL;
375                         return &((feature_list + *nr1 - 1)->data);
376                 }
377         return NULL;
378 }
379
380 /* Evaluate an expression */
381 int sensors_eval_expr(sensors_chip_name chipname, const sensors_expr * expr,
382                       double val, double *result)
383 {
384         double res1, res2;
385         int res;
386         const sensors_chip_feature *feature;
387
388         if (expr->kind == sensors_kind_val) {
389                 *result = expr->data.val;
390                 return 0;
391         }
392         if (expr->kind == sensors_kind_source) {
393                 *result = val;
394                 return 0;
395         }
396         if (expr->kind == sensors_kind_var) {
397                 if (!(feature = sensors_lookup_feature_name(chipname.prefix,
398                                                             expr->data.var)))
399                         return -SENSORS_ERR_NO_ENTRY;
400                 if (!(res = sensors_get_feature(chipname, feature->data.number, result)))
401                         return res;
402                 return 0;
403         }
404         if ((res = sensors_eval_expr(chipname, expr->data.subexpr.sub1, val, &res1)))
405                 return res;
406         if (expr->data.subexpr.sub2 &&
407             (res = sensors_eval_expr(chipname, expr->data.subexpr.sub2, val, &res2)))
408                 return res;
409         switch (expr->data.subexpr.op) {
410         case sensors_add:
411                 *result = res1 + res2;
412                 return 0;
413         case sensors_sub:
414                 *result = res1 - res2;
415                 return 0;
416         case sensors_multiply:
417                 *result = res1 * res2;
418                 return 0;
419         case sensors_divide:
420                 if (res2 == 0.0)
421                         return -SENSORS_ERR_DIV_ZERO;
422                 *result = res1 / res2;
423                 return 0;
424         case sensors_negate:
425                 *result = -res1;
426                 return 0;
427         case sensors_exp:
428                 *result = exp(res1);
429                 return 0;
430         case sensors_log:
431                 if (res1 < 0.0)
432                         return -SENSORS_ERR_DIV_ZERO;
433                 *result = log(res1);
434                 return 0;
435         }
436         return 0;
437 }
438
439 /* Execute all set statements for this particular chip. The chip may not
440    contain wildcards!  This function will return 0 on success, and <0 on
441    failure. */
442 int sensors_do_this_chip_sets(sensors_chip_name name)
443 {
444         sensors_chip *chip;
445         double value;
446         int i, j;
447         int err = 0, res;
448         const sensors_chip_feature *feature;
449         int *feature_list = NULL;
450         int feature_count = 0;
451         int feature_max = 0;
452         int feature_nr;
453
454         for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
455                 for (i = 0; i < chip->sets_count; i++) {
456                         feature = sensors_lookup_feature_name(name.prefix,
457                                                         chip->sets[i].name);
458                         if (!feature) {
459                                 sensors_parse_error("Unknown feature name",
460                                                     chip->sets[i].lineno);
461                                 err = -SENSORS_ERR_NO_ENTRY;
462                                 continue;
463                         }
464                         feature_nr = feature->data.number;
465
466                         /* Check whether we already set this feature */
467                         for (j = 0; j < feature_count; j++)
468                                 if (feature_list[j] == feature_nr)
469                                         break;
470                         if (j != feature_count)
471                                 continue;
472                         sensors_add_array_el(&feature_nr, &feature_list,
473                                              &feature_count, &feature_max,
474                                              sizeof(int));
475
476                         res = sensors_eval_expr(name, chip->sets[i].value, 0,
477                                               &value);
478                         if (res) {
479                                 sensors_parse_error("Error parsing expression",
480                                                     chip->sets[i].lineno);
481                                 err = res;
482                                 continue;
483                         }
484                         if ((res = sensors_set_feature(name, feature_nr, value))) {
485                                 sensors_parse_error("Failed to set feature",
486                                                 chip->sets[i].lineno);
487                                 err = res;
488                                 continue;
489                         }
490                 }
491         free(feature_list);
492         return err;
493 }
494
495 /* Execute all set statements for this particular chip. The chip may contain
496    wildcards!  This function will return 0 on success, and <0 on failure. */
497 int sensors_do_chip_sets(sensors_chip_name name)
498 {
499         int nr, this_res;
500         const sensors_chip_name *found_name;
501         int res = 0;
502
503         for (nr = 0; (found_name = sensors_get_detected_chips(&nr));)
504                 if (sensors_match_chip(name, *found_name)) {
505                         this_res = sensors_do_this_chip_sets(*found_name);
506                         if (!res)
507                                 res = this_res;
508                 }
509         return res;
510 }
511
512 /* Execute all set statements for all detected chips. This is the same as
513    calling sensors_do_chip_sets with an all wildcards chip name */
514 int sensors_do_all_sets(void)
515 {
516         sensors_chip_name name = { SENSORS_CHIP_NAME_PREFIX_ANY,
517                 SENSORS_CHIP_NAME_BUS_ANY,
518                 SENSORS_CHIP_NAME_ADDR_ANY
519         };
520         return sensors_do_chip_sets(name);
521 }
Note: See TracBrowser for help on using the browser.