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

Revision 3113, 16.0 KB (checked in by mmh, 9 years ago)

Remove a workaround for sysfs support that is no longer needed.

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