root/lm-sensors/trunk/prog/sensors/chips.c @ 5836

Revision 5836, 17.4 KB (checked in by khali, 3 years ago)

Properly handle read errors from sensor inputs. Report them as "N/A".
This happens with a couple drivers for devices with inputs which
can come and go.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    chips.c - Part of sensors, a user-space program for hardware monitoring
3    Copyright (C) 1998-2003  Frodo Looijaard <frodol@dds.nl> and
4                             Mark D. Studebaker <mdsxyz123@yahoo.com>
5    Copyright (C) 2007       Jean Delvare <khali@linux-fr.org>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20    MA 02110-1301 USA.
21*/
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <math.h>
27
28#include "main.h"
29#include "chips.h"
30#include "lib/sensors.h"
31#include "lib/error.h"
32
33void print_chip_raw(const sensors_chip_name *name)
34{
35        int a, b, err;
36        const sensors_feature *feature;
37        const sensors_subfeature *sub;
38        char *label;
39        double val;
40
41        a = 0;
42        while ((feature = sensors_get_features(name, &a))) {
43                if (!(label = sensors_get_label(name, feature))) {
44                        fprintf(stderr, "ERROR: Can't get label of feature "
45                                "%s!\n", feature->name);
46                        continue;
47                }
48                printf("%s:\n", label);
49                free(label);
50
51                b = 0;
52                while ((sub = sensors_get_all_subfeatures(name, feature, &b))) {
53                        if (sub->flags & SENSORS_MODE_R) {
54                                if ((err = sensors_get_value(name, sub->number,
55                                                             &val)))
56                                        fprintf(stderr, "ERROR: Can't get "
57                                                "value of subfeature %s: %s\n",
58                                                sub->name,
59                                                sensors_strerror(err));
60                                else
61                                        printf("  %s: %.2f\n", sub->name, val);
62                        } else
63                                printf("(%s)\n", label);
64                }
65        }
66}
67
68static inline double deg_ctof(double cel)
69{
70        return cel * (9.0F / 5.0F) + 32.0F;
71}
72
73static void print_label(const char *label, int space)
74{
75        int len = strlen(label)+1;
76        printf("%s:%*s", label, space - len, "");
77}
78
79static double get_value(const sensors_chip_name *name,
80                        const sensors_subfeature *sub)
81{
82        double val;
83        int err;
84
85        err = sensors_get_value(name, sub->number, &val);
86        if (err) {
87                fprintf(stderr, "ERROR: Can't get value of subfeature %s: %s\n",
88                        sub->name, sensors_strerror(err));
89                val = 0;
90        }
91        return val;
92}
93
94/* A variant for input values, where we want to handle errors gracefully */
95static int get_input_value(const sensors_chip_name *name,
96                           const sensors_subfeature *sub,
97                           double *val)
98{
99        int err;
100
101        err = sensors_get_value(name, sub->number, val);
102        if (err && err != -SENSORS_ERR_ACCESS_R) {
103                fprintf(stderr, "ERROR: Can't get value of subfeature %s: %s\n",
104                        sub->name, sensors_strerror(err));
105        }
106        return err;
107}
108
109static int get_label_size(const sensors_chip_name *name)
110{
111        int i;
112        const sensors_feature *iter;
113        char *label;
114        unsigned int max_size = 11;     /* 11 as minumum label width */
115
116        i = 0;
117        while ((iter = sensors_get_features(name, &i))) {
118                if ((label = sensors_get_label(name, iter)) &&
119                    strlen(label) > max_size)
120                        max_size = strlen(label);
121                free(label);
122        }
123        return max_size + 1;
124}
125
126static void print_temp_limits(double limit1, double limit2,
127                              const char *name1, const char *name2, int alarm)
128{
129        if (fahrenheit) {
130                limit1 = deg_ctof(limit1);
131                limit2 = deg_ctof(limit2);
132        }
133
134        if (name2) {
135                printf("(%-4s = %+5.1f%s, %-4s = %+5.1f%s)  ",
136                       name1, limit1, degstr,
137                       name2, limit2, degstr);
138        } else if (name1) {
139                printf("(%-4s = %+5.1f%s)                  ",
140                       name1, limit1, degstr);
141        } else {
142                printf("                                  ");
143        }
144
145        if (alarm)
146                printf("ALARM  ");
147}
148
149static void print_chip_temp(const sensors_chip_name *name,
150                            const sensors_feature *feature,
151                            int label_size)
152{
153        const sensors_subfeature *sf, *sfmin, *sfmax, *sfcrit, *sfhyst;
154        double val, limit1, limit2;
155        const char *s1, *s2;
156        int alarm, crit_displayed = 0;
157        char *label;
158
159        if (!(label = sensors_get_label(name, feature))) {
160                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
161                        feature->name);
162                return;
163        }
164        print_label(label, label_size);
165        free(label);
166
167        sf = sensors_get_subfeature(name, feature,
168                                    SENSORS_SUBFEATURE_TEMP_ALARM);
169        alarm = sf && get_value(name, sf);
170
171        sfmin = sensors_get_subfeature(name, feature,
172                                       SENSORS_SUBFEATURE_TEMP_MIN);
173        sfmax = sensors_get_subfeature(name, feature,
174                                       SENSORS_SUBFEATURE_TEMP_MAX);
175        sfcrit = sensors_get_subfeature(name, feature,
176                                        SENSORS_SUBFEATURE_TEMP_CRIT);
177        if (sfmax) {
178                sf = sensors_get_subfeature(name, feature,
179                                        SENSORS_SUBFEATURE_TEMP_MAX_ALARM);
180                if (sf && get_value(name, sf))
181                        alarm |= 1;
182
183                if (sfmin) {
184                        limit1 = get_value(name, sfmin);
185                        s1 = "low";
186                        limit2 = get_value(name, sfmax);
187                        s2 = "high";
188
189                        sf = sensors_get_subfeature(name, feature,
190                                        SENSORS_SUBFEATURE_TEMP_MIN_ALARM);
191                        if (sf && get_value(name, sf))
192                                alarm |= 1;
193                } else {
194                        limit1 = get_value(name, sfmax);
195                        s1 = "high";
196
197                        sfhyst = sensors_get_subfeature(name, feature,
198                                        SENSORS_SUBFEATURE_TEMP_MAX_HYST);
199                        if (sfhyst) {
200                                limit2 = get_value(name, sfhyst);
201                                s2 = "hyst";
202                        } else if (sfcrit) {
203                                limit2 = get_value(name, sfcrit);
204                                s2 = "crit";
205
206                                sf = sensors_get_subfeature(name, feature,
207                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
208                                if (sf && get_value(name, sf))
209                                        alarm |= 1;
210                                crit_displayed = 1;
211                        } else {
212                                limit2 = 0;
213                                s2 = NULL;
214                        }
215                }
216        } else if (sfcrit) {
217                limit1 = get_value(name, sfcrit);
218                s1 = "crit";
219
220                sfhyst = sensors_get_subfeature(name, feature,
221                                        SENSORS_SUBFEATURE_TEMP_CRIT_HYST);
222                if (sfhyst) {
223                        limit2 = get_value(name, sfhyst);
224                        s2 = "hyst";
225                } else {
226                        limit2 = 0;
227                        s2 = NULL;
228                }
229
230                sf = sensors_get_subfeature(name, feature,
231                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
232                if (sf && get_value(name, sf))
233                        alarm |= 1;
234                crit_displayed = 1;
235        } else {
236                limit1 = limit2 = 0;
237                s1 = s2 = NULL;
238        }
239
240
241        sf = sensors_get_subfeature(name, feature,
242                                    SENSORS_SUBFEATURE_TEMP_FAULT);
243        if (sf && get_value(name, sf)) {
244                printf("   FAULT  ");
245        } else {
246                sf = sensors_get_subfeature(name, feature,
247                                            SENSORS_SUBFEATURE_TEMP_INPUT);
248                if (sf && get_input_value(name, sf, &val) == 0) {
249                        get_input_value(name, sf, &val);
250                        if (fahrenheit)
251                                val = deg_ctof(val);
252                        printf("%+6.1f%s  ", val, degstr);
253                } else
254                        printf("     N/A  ");
255        }
256        print_temp_limits(limit1, limit2, s1, s2, alarm);
257
258        if (!crit_displayed && sfcrit) {
259                limit1 = get_value(name, sfcrit);
260                s1 = "crit";
261
262                sfhyst = sensors_get_subfeature(name, feature,
263                                        SENSORS_SUBFEATURE_TEMP_CRIT_HYST);
264                if (sfhyst) {
265                        limit2 = get_value(name, sfhyst);
266                        s2 = "hyst";
267                } else {
268                        limit2 = 0;
269                        s2 = NULL;
270                }
271
272                sf = sensors_get_subfeature(name, feature,
273                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
274                alarm = sf && get_value(name, sf);
275
276                printf("\n%*s", label_size + 10, "");
277                print_temp_limits(limit1, limit2, s1, s2, alarm);
278        }
279
280        /* print out temperature sensor info */
281        sf = sensors_get_subfeature(name, feature,
282                                    SENSORS_SUBFEATURE_TEMP_TYPE);
283        if (sf) {
284                int sens = (int)get_value(name, sf);
285
286                /* older kernels / drivers sometimes report a beta value for
287                   thermistors */
288                if (sens > 1000)
289                        sens = 4;
290
291                printf("sensor = %s", sens == 0 ? "disabled" :
292                       sens == 1 ? "diode" :
293                       sens == 2 ? "transistor" :
294                       sens == 3 ? "thermal diode" :
295                       sens == 4 ? "thermistor" :
296                       sens == 5 ? "AMD AMDSI" :
297                       sens == 6 ? "Intel PECI" : "unknown");
298        }
299        printf("\n");
300}
301
302static void print_chip_in(const sensors_chip_name *name,
303                          const sensors_feature *feature,
304                          int label_size)
305{
306        const sensors_subfeature *sf, *sfmin, *sfmax;
307        double val, alarm_max, alarm_min;
308        char *label;
309
310        if (!(label = sensors_get_label(name, feature))) {
311                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
312                        feature->name);
313                return;
314        }
315        print_label(label, label_size);
316        free(label);
317
318        sf = sensors_get_subfeature(name, feature,
319                                    SENSORS_SUBFEATURE_IN_INPUT);
320        if (sf && get_input_value(name, sf, &val) == 0)
321                printf("%+6.2f V", val);
322        else
323                printf("     N/A");
324
325        sfmin = sensors_get_subfeature(name, feature,
326                                       SENSORS_SUBFEATURE_IN_MIN);
327        sfmax = sensors_get_subfeature(name, feature,
328                                       SENSORS_SUBFEATURE_IN_MAX);
329        if (sfmin && sfmax)
330                printf("  (min = %+6.2f V, max = %+6.2f V)",
331                       get_value(name, sfmin),
332                       get_value(name, sfmax));
333        else if (sfmin)
334                printf("  (min = %+6.2f V)",
335                       get_value(name, sfmin));
336        else if (sfmax)
337                printf("  (max = %+6.2f V)",
338                       get_value(name, sfmax));
339
340        sf = sensors_get_subfeature(name, feature,
341                                    SENSORS_SUBFEATURE_IN_ALARM);
342        sfmin = sensors_get_subfeature(name, feature,
343                                       SENSORS_SUBFEATURE_IN_MIN_ALARM);
344        sfmax = sensors_get_subfeature(name, feature,
345                                       SENSORS_SUBFEATURE_IN_MAX_ALARM);
346        if (sfmin || sfmax) {
347                alarm_max = sfmax ? get_value(name, sfmax) : 0;
348                alarm_min = sfmin ? get_value(name, sfmin) : 0;
349
350                if (alarm_min || alarm_max) {
351                        printf(" ALARM (");
352
353                        if (alarm_min)
354                                printf("MIN");
355                        if (alarm_max)
356                                printf("%sMAX", (alarm_min) ? ", " : "");
357
358                        printf(")");
359                }
360        } else if (sf) {
361                printf("   %s",
362                       get_value(name, sf) ? "ALARM" : "");
363        }
364
365        printf("\n");
366}
367
368static void print_chip_fan(const sensors_chip_name *name,
369                           const sensors_feature *feature,
370                           int label_size)
371{
372        const sensors_subfeature *sf, *sfmin, *sfdiv;
373        double val;
374        char *label;
375
376        if (!(label = sensors_get_label(name, feature))) {
377                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
378                        feature->name);
379                return;
380        }
381        print_label(label, label_size);
382        free(label);
383
384        sf = sensors_get_subfeature(name, feature,
385                                    SENSORS_SUBFEATURE_FAN_FAULT);
386        if (sf && get_value(name, sf))
387                printf("   FAULT");
388        else {
389                sf = sensors_get_subfeature(name, feature,
390                                            SENSORS_SUBFEATURE_FAN_INPUT);
391                if (sf && get_input_value(name, sf, &val) == 0)
392                        printf("%4.0f RPM", val);
393                else
394                        printf("     N/A");
395        }
396
397        sfmin = sensors_get_subfeature(name, feature,
398                                       SENSORS_SUBFEATURE_FAN_MIN);
399        sfdiv = sensors_get_subfeature(name, feature,
400                                       SENSORS_SUBFEATURE_FAN_DIV);
401        if (sfmin && sfdiv)
402                printf("  (min = %4.0f RPM, div = %1.0f)",
403                       get_value(name, sfmin),
404                       get_value(name, sfdiv));
405        else if (sfmin)
406                printf("  (min = %4.0f RPM)",
407                       get_value(name, sfmin));
408        else if (sfdiv)
409                printf("  (div = %1.0f)",
410                       get_value(name, sfdiv));
411
412        sf = sensors_get_subfeature(name, feature,
413                                    SENSORS_SUBFEATURE_FAN_ALARM);
414        if (sf && get_value(name, sf)) {
415                printf("  ALARM");
416        }
417
418        printf("\n");
419}
420
421struct scale_table {
422        double upper_bound;
423        const char *unit;
424};
425
426static void scale_value(double *value, const char **prefixstr)
427{
428        double abs_value = fabs(*value);
429        double divisor = 1e-9;
430        static struct scale_table prefix_scales[] = {
431                {1e-6, "n"},
432                {1e-3, "u"},
433                {1,    "m"},
434                {1e3,   ""},
435                {1e6,  "k"},
436                {1e9,  "M"},
437                {0,    "G"}, /* no upper bound */
438        };
439        struct scale_table *scale = prefix_scales;
440
441        while (scale->upper_bound && abs_value > scale->upper_bound) {
442                divisor = scale->upper_bound;
443                scale++;
444        }
445
446        *value /= divisor;
447        *prefixstr = scale->unit;
448}
449
450static void print_chip_power(const sensors_chip_name *name,
451                             const sensors_feature *feature,
452                             int label_size)
453{
454        double val;
455        int need_space = 0;
456        const sensors_subfeature *sf, *sfmin, *sfmax, *sfint;
457        char *label;
458        const char *unit;
459
460        if (!(label = sensors_get_label(name, feature))) {
461                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
462                        feature->name);
463                return;
464        }
465        print_label(label, label_size);
466        free(label);
467
468        /* Power sensors come in 2 flavors: instantaneous and averaged.
469           To keep things simple, we assume that each sensor only implements
470           one flavor. */
471        sf = sensors_get_subfeature(name, feature,
472                                    SENSORS_SUBFEATURE_POWER_INPUT);
473        if (sf) {
474                sfmin = sensors_get_subfeature(name, feature,
475                                               SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST);
476                sfmax = sensors_get_subfeature(name, feature,
477                                               SENSORS_SUBFEATURE_POWER_INPUT_LOWEST);
478                sfint = NULL;
479        } else {
480                sf = sensors_get_subfeature(name, feature,
481                                            SENSORS_SUBFEATURE_POWER_AVERAGE);
482                sfmin = sensors_get_subfeature(name, feature,
483                                               SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST);
484                sfmax = sensors_get_subfeature(name, feature,
485                                               SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST);
486                sfint = sensors_get_subfeature(name, feature,
487                                               SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL);
488        }
489
490        if (sf && get_input_value(name, sf, &val) == 0) {
491                scale_value(&val, &unit);
492                printf("%6.2f %sW", val, unit);
493        } else
494                printf("     N/A");
495
496        if (sfmin || sfmax || sfint) {
497                printf("  (");
498
499                if (sfmin) {
500                        val = get_value(name, sfmin);
501                        scale_value(&val, &unit);
502                        printf("min = %6.2f %sW", val, unit);
503                        need_space = 1;
504                }
505
506                if (sfmax) {
507                        val = get_value(name, sfmax);
508                        scale_value(&val, &unit);
509                        printf("%smax = %6.2f %sW", (need_space ? ", " : ""),
510                               val, unit);
511                        need_space = 1;
512                }
513
514                if (sfint) {
515                        printf("%sinterval = %6.2f s", (need_space ? ", " : ""),
516                               get_value(name, sfint));
517                        need_space = 1;
518                }
519                printf(")");
520        }
521
522        printf("\n");
523}
524
525static void print_chip_energy(const sensors_chip_name *name,
526                              const sensors_feature *feature,
527                              int label_size)
528{
529        double val;
530        const sensors_subfeature *sf;
531        char *label;
532        const char *unit;
533
534        if (!(label = sensors_get_label(name, feature))) {
535                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
536                        feature->name);
537                return;
538        }
539        print_label(label, label_size);
540        free(label);
541
542        sf = sensors_get_subfeature(name, feature,
543                                    SENSORS_SUBFEATURE_ENERGY_INPUT);
544        if (sf && get_input_value(name, sf, &val) == 0) {
545                scale_value(&val, &unit);
546                printf("%6.2f %sJ", val, unit);
547        } else
548                printf("     N/A");
549
550        printf("\n");
551}
552
553static void print_chip_vid(const sensors_chip_name *name,
554                           const sensors_feature *feature,
555                           int label_size)
556{
557        char *label;
558        const sensors_subfeature *subfeature;
559        double vid;
560
561        subfeature = sensors_get_subfeature(name, feature,
562                                            SENSORS_SUBFEATURE_VID);
563        if (!subfeature)
564                return;
565
566        if ((label = sensors_get_label(name, feature))
567         && !sensors_get_value(name, subfeature->number, &vid)) {
568                print_label(label, label_size);
569                printf("%+6.3f V\n", vid);
570        }
571        free(label);
572}
573
574static void print_chip_beep_enable(const sensors_chip_name *name,
575                                   const sensors_feature *feature,
576                                   int label_size)
577{
578        char *label;
579        const sensors_subfeature *subfeature;
580        double beep_enable;
581
582        subfeature = sensors_get_subfeature(name, feature,
583                                            SENSORS_SUBFEATURE_BEEP_ENABLE);
584        if (!subfeature)
585                return;
586
587        if ((label = sensors_get_label(name, feature))
588         && !sensors_get_value(name, subfeature->number, &beep_enable)) {
589                print_label(label, label_size);
590                printf("%s\n", beep_enable ? "enabled" : "disabled");
591        }
592        free(label);
593}
594
595static void print_chip_curr(const sensors_chip_name *name,
596                            const sensors_feature *feature,
597                            int label_size)
598{
599        const sensors_subfeature *sf, *sfmin, *sfmax;
600        double alarm_max, alarm_min, val;
601        char *label;
602
603        if (!(label = sensors_get_label(name, feature))) {
604                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
605                        feature->name);
606                return;
607        }
608        print_label(label, label_size);
609        free(label);
610
611        sf = sensors_get_subfeature(name, feature,
612                                    SENSORS_SUBFEATURE_CURR_INPUT);
613        if (sf && get_input_value(name, sf, &val) == 0)
614                printf("%+6.2f A", val);
615        else
616                printf("     N/A");
617
618        sfmin = sensors_get_subfeature(name, feature,
619                                       SENSORS_SUBFEATURE_CURR_MIN);
620        sfmax = sensors_get_subfeature(name, feature,
621                                       SENSORS_SUBFEATURE_CURR_MAX);
622        if (sfmin && sfmax)
623                printf("  (min = %+6.2f A, max = %+6.2f A)",
624                       get_value(name, sfmin),
625                       get_value(name, sfmax));
626        else if (sfmin)
627                printf("  (min = %+6.2f A)",
628                       get_value(name, sfmin));
629        else if (sfmax)
630                printf("  (max = %+6.2f A)",
631                       get_value(name, sfmax));
632
633        sf = sensors_get_subfeature(name, feature,
634                                    SENSORS_SUBFEATURE_CURR_ALARM);
635        sfmin = sensors_get_subfeature(name, feature,
636                                       SENSORS_SUBFEATURE_CURR_MIN_ALARM);
637        sfmax = sensors_get_subfeature(name, feature,
638                                       SENSORS_SUBFEATURE_CURR_MAX_ALARM);
639        if (sfmin || sfmax) {
640                alarm_max = sfmax ? get_value(name, sfmax) : 0;
641                alarm_min = sfmin ? get_value(name, sfmin) : 0;
642
643                if (alarm_min || alarm_max) {
644                        printf(" ALARM (");
645
646                        if (alarm_min)
647                                printf("MIN");
648                        if (alarm_max)
649                                printf("%sMAX", (alarm_min) ? ", " : "");
650
651                        printf(")");
652                }
653        } else if (sf) {
654                printf("   %s",
655                       get_value(name, sf) ? "ALARM" : "");
656        }
657
658        printf("\n");
659}
660
661void print_chip(const sensors_chip_name *name)
662{
663        const sensors_feature *feature;
664        int i, label_size;
665
666        label_size = get_label_size(name);
667
668        i = 0;
669        while ((feature = sensors_get_features(name, &i))) {
670                switch (feature->type) {
671                case SENSORS_FEATURE_TEMP:
672                        print_chip_temp(name, feature, label_size);
673                        break;
674                case SENSORS_FEATURE_IN:
675                        print_chip_in(name, feature, label_size);
676                        break;
677                case SENSORS_FEATURE_FAN:
678                        print_chip_fan(name, feature, label_size);
679                        break;
680                case SENSORS_FEATURE_VID:
681                        print_chip_vid(name, feature, label_size);
682                        break;
683                case SENSORS_FEATURE_BEEP_ENABLE:
684                        print_chip_beep_enable(name, feature, label_size);
685                        break;
686                case SENSORS_FEATURE_POWER:
687                        print_chip_power(name, feature, label_size);
688                        break;
689                case SENSORS_FEATURE_ENERGY:
690                        print_chip_energy(name, feature, label_size);
691                        break;
692                case SENSORS_FEATURE_CURR:
693                        print_chip_curr(name, feature, label_size);
694                        break;
695                default:
696                        continue;
697                }
698        }
699}
Note: See TracBrowser for help on using the browser.