blob: 8e227e2550dbb5f1a0fe3aea179855e80fe15050 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/*
2 access.c - Part of libsensors, a Linux library for reading sensor data.
3 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
4 Copyright (C) 2007-2009 Jean Delvare <khali@linux-fr.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301 USA.
20*/
21
22#include <stdlib.h>
23#include <string.h>
24#include <math.h>
25#include "access.h"
26#include "sensors.h"
27#include "data.h"
28#include "error.h"
29#include "sysfs.h"
30
31/* We watch the recursion depth for variables only, as an easy way to
32 detect cycles. */
33#define DEPTH_MAX 8
34
35static int sensors_eval_expr(const sensors_chip_features *chip_features,
36 const sensors_expr *expr,
37 double val, int depth, double *result);
38
39/* Compare two chips name descriptions, to see whether they could match.
40 Return 0 if it does not match, return 1 if it does match. */
41static int sensors_match_chip(const sensors_chip_name *chip1,
42 const sensors_chip_name *chip2)
43{
44 if ((chip1->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
45 (chip2->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
46 strcmp(chip1->prefix, chip2->prefix))
47 return 0;
48
49 if ((chip1->bus.type != SENSORS_BUS_TYPE_ANY) &&
50 (chip2->bus.type != SENSORS_BUS_TYPE_ANY) &&
51 (chip1->bus.type != chip2->bus.type))
52 return 0;
53
54 if ((chip1->bus.nr != SENSORS_BUS_NR_ANY) &&
55 (chip2->bus.nr != SENSORS_BUS_NR_ANY) &&
56 (chip1->bus.nr != chip2->bus.nr))
57 return 0;
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. */
74static sensors_chip *
75sensors_for_all_config_chips(const sensors_chip_name *name,
76 const sensors_chip *last)
77{
78 int nr, i;
79 sensors_chip_name_list chips;
80
81 for (nr = last ? last - sensors_config_chips - 1 :
82 sensors_config_chips_count - 1; nr >= 0; nr--) {
83
84 chips = sensors_config_chips[nr].chips;
85 for (i = 0; i < chips.fits_count; i++) {
86 if (sensors_match_chip(&chips.fits[i], name))
87 return sensors_config_chips + nr;
88 }
89 }
90 return NULL;
91}
92
93/* Look up a chip in the intern chip list, and return a pointer to it.
94 Do not modify the struct the return value points to! Returns NULL if
95 not found.*/
96static const sensors_chip_features *
97sensors_lookup_chip(const sensors_chip_name *name)
98{
99 int i;
100
101 for (i = 0; i < sensors_proc_chips_count; i++)
102 if (sensors_match_chip(&sensors_proc_chips[i].chip, name))
103 return &sensors_proc_chips[i];
104
105 return NULL;
106}
107
108/* Look up a subfeature of the given chip, and return a pointer to it.
109 Do not modify the struct the return value points to! Returns NULL if
110 not found.*/
111static const sensors_subfeature *
112sensors_lookup_subfeature_nr(const sensors_chip_features *chip,
113 int subfeat_nr)
114{
115 if (subfeat_nr < 0 ||
116 subfeat_nr >= chip->subfeature_count)
117 return NULL;
118 return chip->subfeature + subfeat_nr;
119}
120
121/* Look up a feature of the given chip, and return a pointer to it.
122 Do not modify the struct the return value points to! Returns NULL if
123 not found.*/
124static const sensors_feature *
125sensors_lookup_feature_nr(const sensors_chip_features *chip, int feat_nr)
126{
127 if (feat_nr < 0 ||
128 feat_nr >= chip->feature_count)
129 return NULL;
130 return chip->feature + feat_nr;
131}
132
133/* Look up a subfeature by name, and return a pointer to it.
134 Do not modify the struct the return value points to! Returns NULL if
135 not found.*/
136static const sensors_subfeature *
137sensors_lookup_subfeature_name(const sensors_chip_features *chip,
138 const char *name)
139{
140 int j;
141
142 for (j = 0; j < chip->subfeature_count; j++)
143 if (!strcmp(chip->subfeature[j].name, name))
144 return chip->subfeature + j;
145 return NULL;
146}
147
148/* Check whether the chip name is an 'absolute' name, which can only match
149 one chip, or whether it has wildcards. Returns 0 if it is absolute, 1
150 if there are wildcards. */
151int sensors_chip_name_has_wildcards(const sensors_chip_name *chip)
152{
153 if ((chip->prefix == SENSORS_CHIP_NAME_PREFIX_ANY) ||
154 (chip->bus.type == SENSORS_BUS_TYPE_ANY) ||
155 (chip->bus.nr == SENSORS_BUS_NR_ANY) ||
156 (chip->addr == SENSORS_CHIP_NAME_ADDR_ANY))
157 return 1;
158 else
159 return 0;
160}
161
162/* Look up the label for a given feature. Note that chip should not
163 contain wildcard values! The returned string is newly allocated (free it
164 yourself). On failure, NULL is returned.
165 If no label exists for this feature, its name is returned itself. */
166char *sensors_get_label(const sensors_chip_name *name,
167 const sensors_feature *feature)
168{
169 char *label;
170 const sensors_chip *chip;
171 char buf[PATH_MAX];
172 FILE *f;
173 int i;
174
175 if (sensors_chip_name_has_wildcards(name))
176 return NULL;
177
178 for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
179 for (i = 0; i < chip->labels_count; i++)
180 if (!strcmp(feature->name, chip->labels[i].name)) {
181 label = chip->labels[i].value;
182 goto sensors_get_label_exit;
183 }
184
185 /* No user specified label, check for a _label sysfs file */
186 snprintf(buf, PATH_MAX, "%s/%s_label", name->path, feature->name);
187
188 if ((f = fopen(buf, "r"))) {
189 i = fread(buf, 1, sizeof(buf), f);
190 fclose(f);
191 if (i > 0) {
192 /* i - 1 to strip the '\n' at the end */
193 buf[i - 1] = 0;
194 label = buf;
195 goto sensors_get_label_exit;
196 }
197 }
198
199 /* No label, return the feature name instead */
200 label = feature->name;
201
202sensors_get_label_exit:
203 label = strdup(label);
204 if (!label)
205 sensors_fatal_error(__func__, "Allocating label text");
206 return label;
207}
208
209/* Looks up whether a feature should be ignored. Returns
210 1 if it should be ignored, 0 if not. */
211static int sensors_get_ignored(const sensors_chip_name *name,
212 const sensors_feature *feature)
213{
214 const sensors_chip *chip;
215 int i;
216
217 for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
218 for (i = 0; i < chip->ignores_count; i++)
219 if (!strcmp(feature->name, chip->ignores[i].name))
220 return 1;
221 return 0;
222}
223
224/* Read the value of a subfeature 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. */
227static int __sensors_get_value(const sensors_chip_name *name, int subfeat_nr,
228 int depth, double *result)
229{
230 const sensors_chip_features *chip_features;
231 const sensors_subfeature *subfeature;
232 const sensors_expr *expr = NULL;
233 double val;
234 int res, i;
235
236 if (depth >= DEPTH_MAX)
237 return -SENSORS_ERR_RECURSION;
238 if (sensors_chip_name_has_wildcards(name))
239 return -SENSORS_ERR_WILDCARDS;
240 if (!(chip_features = sensors_lookup_chip(name)))
241 return -SENSORS_ERR_NO_ENTRY;
242 if (!(subfeature = sensors_lookup_subfeature_nr(chip_features,
243 subfeat_nr)))
244 return -SENSORS_ERR_NO_ENTRY;
245 if (!(subfeature->flags & SENSORS_MODE_R))
246 return -SENSORS_ERR_ACCESS_R;
247
248 /* Apply compute statement if it exists */
249 if (subfeature->flags & SENSORS_COMPUTE_MAPPING) {
250 const sensors_feature *feature;
251 const sensors_chip *chip;
252
253 feature = sensors_lookup_feature_nr(chip_features,
254 subfeature->mapping);
255
256 chip = NULL;
257 while (!expr &&
258 (chip = sensors_for_all_config_chips(name, chip)))
259 for (i = 0; i < chip->computes_count; i++) {
260 if (!strcmp(feature->name,
261 chip->computes[i].name)) {
262 expr = chip->computes[i].from_proc;
263 break;
264 }
265 }
266 }
267
268 res = sensors_read_sysfs_attr(name, subfeature, &val);
269 if (res)
270 return res;
271 if (!expr)
272 *result = val;
273 else if ((res = sensors_eval_expr(chip_features, expr, val, depth,
274 result)))
275 return res;
276 return 0;
277}
278
279int sensors_get_value(const sensors_chip_name *name, int subfeat_nr,
280 double *result)
281{
282 return __sensors_get_value(name, subfeat_nr, 0, result);
283}
284
285/* Set the value of a subfeature of a certain chip. Note that chip should not
286 contain wildcard values! This function will return 0 on success, and <0
287 on failure. */
288int sensors_set_value(const sensors_chip_name *name, int subfeat_nr,
289 double value)
290{
291 const sensors_chip_features *chip_features;
292 const sensors_subfeature *subfeature;
293 const sensors_expr *expr = NULL;
294 int i, res;
295 double to_write;
296
297 if (sensors_chip_name_has_wildcards(name))
298 return -SENSORS_ERR_WILDCARDS;
299 if (!(chip_features = sensors_lookup_chip(name)))
300 return -SENSORS_ERR_NO_ENTRY;
301 if (!(subfeature = sensors_lookup_subfeature_nr(chip_features,
302 subfeat_nr)))
303 return -SENSORS_ERR_NO_ENTRY;
304 if (!(subfeature->flags & SENSORS_MODE_W))
305 return -SENSORS_ERR_ACCESS_W;
306
307 /* Apply compute statement if it exists */
308 if (subfeature->flags & SENSORS_COMPUTE_MAPPING) {
309 const sensors_feature *feature;
310 const sensors_chip *chip;
311
312 feature = sensors_lookup_feature_nr(chip_features,
313 subfeature->mapping);
314
315 chip = NULL;
316 while (!expr &&
317 (chip = sensors_for_all_config_chips(name, chip)))
318 for (i = 0; i < chip->computes_count; i++) {
319 if (!strcmp(feature->name,
320 chip->computes[i].name)) {
321 expr = chip->computes[i].to_proc;
322 break;
323 }
324 }
325 }
326
327 to_write = value;
328 if (expr)
329 if ((res = sensors_eval_expr(chip_features, expr,
330 value, 0, &to_write)))
331 return res;
332 return sensors_write_sysfs_attr(name, subfeature, to_write);
333}
334
335const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name
336 *match, int *nr)
337{
338 const sensors_chip_name *res;
339
340 while (*nr < sensors_proc_chips_count) {
341 res = &sensors_proc_chips[(*nr)++].chip;
342 if (!match || sensors_match_chip(res, match))
343 return res;
344 }
345 return NULL;
346}
347
348const char *sensors_get_adapter_name(const sensors_bus_id *bus)
349{
350 int i;
351
352 /* bus types with a single instance */
353 switch (bus->type) {
354 case SENSORS_BUS_TYPE_ISA:
355 return "ISA adapter";
356 case SENSORS_BUS_TYPE_PCI:
357 return "PCI adapter";
358 /* SPI should not be here, but for now SPI adapters have no name
359 so we don't have any custom string to return. */
360 case SENSORS_BUS_TYPE_SPI:
361 return "SPI adapter";
362 case SENSORS_BUS_TYPE_VIRTUAL:
363 return "Virtual device";
364 case SENSORS_BUS_TYPE_ACPI:
365 return "ACPI interface";
366 /* HID should probably not be there either, but I don't know if
367 HID buses have a name nor where to find it. */
368 case SENSORS_BUS_TYPE_HID:
369 return "HID adapter";
370 }
371
372 /* bus types with several instances */
373 for (i = 0; i < sensors_proc_bus_count; i++)
374 if (sensors_proc_bus[i].bus.type == bus->type &&
375 sensors_proc_bus[i].bus.nr == bus->nr)
376 return sensors_proc_bus[i].adapter;
377 return NULL;
378}
379
380const sensors_feature *
381sensors_get_features(const sensors_chip_name *name, int *nr)
382{
383 const sensors_chip_features *chip;
384
385 if (!(chip = sensors_lookup_chip(name)))
386 return NULL; /* No such chip */
387
388 while (*nr < chip->feature_count
389 && sensors_get_ignored(name, &chip->feature[*nr]))
390 (*nr)++;
391 if (*nr >= chip->feature_count)
392 return NULL;
393 return &chip->feature[(*nr)++];
394}
395
396const sensors_subfeature *
397sensors_get_all_subfeatures(const sensors_chip_name *name,
398 const sensors_feature *feature, int *nr)
399{
400 const sensors_chip_features *chip;
401 const sensors_subfeature *subfeature;
402
403 if (!(chip = sensors_lookup_chip(name)))
404 return NULL; /* No such chip */
405
406 /* Seek directly to the first subfeature */
407 if (*nr < feature->first_subfeature)
408 *nr = feature->first_subfeature;
409
410 if (*nr >= chip->subfeature_count)
411 return NULL; /* end of list */
412 subfeature = &chip->subfeature[(*nr)++];
413 if (subfeature->mapping == feature->number)
414 return subfeature;
415 return NULL; /* end of subfeature list */
416}
417
418const sensors_subfeature *
419sensors_get_subfeature(const sensors_chip_name *name,
420 const sensors_feature *feature,
421 sensors_subfeature_type type)
422{
423 const sensors_chip_features *chip;
424 int i;
425
426 if (!(chip = sensors_lookup_chip(name)))
427 return NULL; /* No such chip */
428
429 for (i = feature->first_subfeature; i < chip->subfeature_count &&
430 chip->subfeature[i].mapping == feature->number; i++) {
431 if (chip->subfeature[i].type == type)
432 return &chip->subfeature[i];
433 }
434 return NULL; /* No such subfeature */
435}
436
437/* Evaluate an expression */
438int sensors_eval_expr(const sensors_chip_features *chip_features,
439 const sensors_expr *expr,
440 double val, int depth, double *result)
441{
442 double res1, res2;
443 int res;
444 const sensors_subfeature *subfeature;
445
446 if (expr->kind == sensors_kind_val) {
447 *result = expr->data.val;
448 return 0;
449 }
450 if (expr->kind == sensors_kind_source) {
451 *result = val;
452 return 0;
453 }
454 if (expr->kind == sensors_kind_var) {
455 if (!(subfeature = sensors_lookup_subfeature_name(chip_features,
456 expr->data.var)))
457 return -SENSORS_ERR_NO_ENTRY;
458 return __sensors_get_value(&chip_features->chip,
459 subfeature->number, depth + 1,
460 result);
461 }
462 if ((res = sensors_eval_expr(chip_features, expr->data.subexpr.sub1,
463 val, depth, &res1)))
464 return res;
465 if (expr->data.subexpr.sub2 &&
466 (res = sensors_eval_expr(chip_features, expr->data.subexpr.sub2,
467 val, depth, &res2)))
468 return res;
469 switch (expr->data.subexpr.op) {
470 case sensors_add:
471 *result = res1 + res2;
472 return 0;
473 case sensors_sub:
474 *result = res1 - res2;
475 return 0;
476 case sensors_multiply:
477 *result = res1 * res2;
478 return 0;
479 case sensors_divide:
480 if (res2 == 0.0)
481 return -SENSORS_ERR_DIV_ZERO;
482 *result = res1 / res2;
483 return 0;
484 case sensors_negate:
485 *result = -res1;
486 return 0;
487 case sensors_exp:
488 *result = exp(res1);
489 return 0;
490 case sensors_log:
491 if (res1 < 0.0)
492 return -SENSORS_ERR_DIV_ZERO;
493 *result = log(res1);
494 return 0;
495 }
496 return 0;
497}
498
499/* Execute all set statements for this particular chip. The chip may not
500 contain wildcards! This function will return 0 on success, and <0 on
501 failure. */
502static int sensors_do_this_chip_sets(const sensors_chip_name *name)
503{
504 const sensors_chip_features *chip_features;
505 sensors_chip *chip;
506 double value;
507 int i;
508 int err = 0, res;
509 const sensors_subfeature *subfeature;
510
511 chip_features = sensors_lookup_chip(name); /* Can't fail */
512
513 for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));)
514 for (i = 0; i < chip->sets_count; i++) {
515 subfeature = sensors_lookup_subfeature_name(chip_features,
516 chip->sets[i].name);
517 if (!subfeature) {
518 sensors_parse_error_wfn("Unknown feature name",
519 chip->sets[i].line.filename,
520 chip->sets[i].line.lineno);
521 err = -SENSORS_ERR_NO_ENTRY;
522 continue;
523 }
524
525 res = sensors_eval_expr(chip_features,
526 chip->sets[i].value, 0,
527 0, &value);
528 if (res) {
529 sensors_parse_error_wfn("Error parsing expression",
530 chip->sets[i].line.filename,
531 chip->sets[i].line.lineno);
532 err = res;
533 continue;
534 }
535 if ((res = sensors_set_value(name, subfeature->number,
536 value))) {
537 sensors_parse_error_wfn("Failed to set value",
538 chip->sets[i].line.filename,
539 chip->sets[i].line.lineno);
540 err = res;
541 continue;
542 }
543 }
544 return err;
545}
546
547/* Execute all set statements for this particular chip. The chip may contain
548 wildcards! This function will return 0 on success, and <0 on failure. */
549int sensors_do_chip_sets(const sensors_chip_name *name)
550{
551 int nr, this_res;
552 const sensors_chip_name *found_name;
553 int res = 0;
554
555 for (nr = 0; (found_name = sensors_get_detected_chips(name, &nr));) {
556 this_res = sensors_do_this_chip_sets(found_name);
557 if (this_res)
558 res = this_res;
559 }
560 return res;
561}