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

Revision 649, 14.9 KB (checked in by frodo, 13 years ago)

Something in the README about ways to determine your chips

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