root/lm-sensors/tags/V2-10-4/lib/access.c

Revision 4551, 15.6 kB (checked in by jwrdegoede, 1 year ago)

Add abituguru3 support

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