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

Revision 4287, 15.3 kB (checked in by mmh, 2 years ago)

The sensors library relied on one structure having an identical layout in
memory as part of another structure. This rather large patch fixes that by
making the smaller piece an explicit member of the larger.

I brought this patch into sync with the latest SVN, and tested it by comparing
objects files from the tree pre- and post- patch.

The remaining 99% of the credit goes to Bob Schlärmann <bob2@dsv.nl> for
creating the original patch... thanks Bob!

* Bob Schlärmann <bob2@dsv.nl> [2006-12-24 18:29:39 +0100]:

The following patch changes all of the lib/chips.c entries and any function
that uses sensors_chip_feature. Most of the conversion was done through a
perl script, so if you don't agree with the syntax it'll be easy to change.

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