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

Revision 5872, 17.5 KB (checked in by khali, 3 years ago)

Ensure there's at least one space between the label and the value.

  • 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
124        /* One more for the colon, and one more to guarantee at least one
125           space between that colon and the value */
126        return max_size + 2;
127}
128
129static void print_temp_limits(double limit1, double limit2,
130                              const char *name1, const char *name2, int alarm)
131{
132        if (fahrenheit) {
133                limit1 = deg_ctof(limit1);
134                limit2 = deg_ctof(limit2);
135        }
136
137        if (name2) {
138                printf("(%-4s = %+5.1f%s, %-4s = %+5.1f%s)  ",
139                       name1, limit1, degstr,
140                       name2, limit2, degstr);
141        } else if (name1) {
142                printf("(%-4s = %+5.1f%s)                  ",
143                       name1, limit1, degstr);
144        } else {
145                printf("                                  ");
146        }
147
148        if (alarm)
149                printf("ALARM  ");
150}
151
152static void print_chip_temp(const sensors_chip_name *name,
153                            const sensors_feature *feature,
154                            int label_size)
155{
156        const sensors_subfeature *sf, *sfmin, *sfmax, *sfcrit, *sfhyst;
157        double val, limit1, limit2;
158        const char *s1, *s2;
159        int alarm, crit_displayed = 0;
160        char *label;
161
162        if (!(label = sensors_get_label(name, feature))) {
163                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
164                        feature->name);
165                return;
166        }
167        print_label(label, label_size);
168        free(label);
169
170        sf = sensors_get_subfeature(name, feature,
171                                    SENSORS_SUBFEATURE_TEMP_ALARM);
172        alarm = sf && get_value(name, sf);
173
174        sfmin = sensors_get_subfeature(name, feature,
175                                       SENSORS_SUBFEATURE_TEMP_MIN);
176        sfmax = sensors_get_subfeature(name, feature,
177                                       SENSORS_SUBFEATURE_TEMP_MAX);
178        sfcrit = sensors_get_subfeature(name, feature,
179                                        SENSORS_SUBFEATURE_TEMP_CRIT);
180        if (sfmax) {
181                sf = sensors_get_subfeature(name, feature,
182                                        SENSORS_SUBFEATURE_TEMP_MAX_ALARM);
183                if (sf && get_value(name, sf))
184                        alarm |= 1;
185
186                if (sfmin) {
187                        limit1 = get_value(name, sfmin);
188                        s1 = "low";
189                        limit2 = get_value(name, sfmax);
190                        s2 = "high";
191
192                        sf = sensors_get_subfeature(name, feature,
193                                        SENSORS_SUBFEATURE_TEMP_MIN_ALARM);
194                        if (sf && get_value(name, sf))
195                                alarm |= 1;
196                } else {
197                        limit1 = get_value(name, sfmax);
198                        s1 = "high";
199
200                        sfhyst = sensors_get_subfeature(name, feature,
201                                        SENSORS_SUBFEATURE_TEMP_MAX_HYST);
202                        if (sfhyst) {
203                                limit2 = get_value(name, sfhyst);
204                                s2 = "hyst";
205                        } else if (sfcrit) {
206                                limit2 = get_value(name, sfcrit);
207                                s2 = "crit";
208
209                                sf = sensors_get_subfeature(name, feature,
210                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
211                                if (sf && get_value(name, sf))
212                                        alarm |= 1;
213                                crit_displayed = 1;
214                        } else {
215                                limit2 = 0;
216                                s2 = NULL;
217                        }
218                }
219        } else if (sfcrit) {
220                limit1 = get_value(name, sfcrit);
221                s1 = "crit";
222
223                sfhyst = sensors_get_subfeature(name, feature,
224                                        SENSORS_SUBFEATURE_TEMP_CRIT_HYST);
225                if (sfhyst) {
226                        limit2 = get_value(name, sfhyst);
227                        s2 = "hyst";
228                } else {
229                        limit2 = 0;
230                        s2 = NULL;
231                }
232
233                sf = sensors_get_subfeature(name, feature,
234                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
235                if (sf && get_value(name, sf))
236                        alarm |= 1;
237                crit_displayed = 1;
238        } else {
239                limit1 = limit2 = 0;
240                s1 = s2 = NULL;
241        }
242
243
244        sf = sensors_get_subfeature(name, feature,
245                                    SENSORS_SUBFEATURE_TEMP_FAULT);
246        if (sf && get_value(name, sf)) {
247                printf("   FAULT  ");
248        } else {
249                sf = sensors_get_subfeature(name, feature,
250                                            SENSORS_SUBFEATURE_TEMP_INPUT);
251                if (sf && get_input_value(name, sf, &val) == 0) {
252                        get_input_value(name, sf, &val);
253                        if (fahrenheit)
254                                val = deg_ctof(val);
255                        printf("%+6.1f%s  ", val, degstr);
256                } else
257                        printf("     N/A  ");
258        }
259        print_temp_limits(limit1, limit2, s1, s2, alarm);
260
261        if (!crit_displayed && sfcrit) {
262                limit1 = get_value(name, sfcrit);
263                s1 = "crit";
264
265                sfhyst = sensors_get_subfeature(name, feature,
266                                        SENSORS_SUBFEATURE_TEMP_CRIT_HYST);
267                if (sfhyst) {
268                        limit2 = get_value(name, sfhyst);
269                        s2 = "hyst";
270                } else {
271                        limit2 = 0;
272                        s2 = NULL;
273                }
274
275                sf = sensors_get_subfeature(name, feature,
276                                        SENSORS_SUBFEATURE_TEMP_CRIT_ALARM);
277                alarm = sf && get_value(name, sf);
278
279                printf("\n%*s", label_size + 10, "");
280                print_temp_limits(limit1, limit2, s1, s2, alarm);
281        }
282
283        /* print out temperature sensor info */
284        sf = sensors_get_subfeature(name, feature,
285                                    SENSORS_SUBFEATURE_TEMP_TYPE);
286        if (sf) {
287                int sens = (int)get_value(name, sf);
288
289                /* older kernels / drivers sometimes report a beta value for
290                   thermistors */
291                if (sens > 1000)
292                        sens = 4;
293
294                printf("sensor = %s", sens == 0 ? "disabled" :
295                       sens == 1 ? "diode" :
296                       sens == 2 ? "transistor" :
297                       sens == 3 ? "thermal diode" :
298                       sens == 4 ? "thermistor" :
299                       sens == 5 ? "AMD AMDSI" :
300                       sens == 6 ? "Intel PECI" : "unknown");
301        }
302        printf("\n");
303}
304
305static void print_chip_in(const sensors_chip_name *name,
306                          const sensors_feature *feature,
307                          int label_size)
308{
309        const sensors_subfeature *sf, *sfmin, *sfmax;
310        double val, alarm_max, alarm_min;
311        char *label;
312
313        if (!(label = sensors_get_label(name, feature))) {
314                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
315                        feature->name);
316                return;
317        }
318        print_label(label, label_size);
319        free(label);
320
321        sf = sensors_get_subfeature(name, feature,
322                                    SENSORS_SUBFEATURE_IN_INPUT);
323        if (sf && get_input_value(name, sf, &val) == 0)
324                printf("%+6.2f V", val);
325        else
326                printf("     N/A");
327
328        sfmin = sensors_get_subfeature(name, feature,
329                                       SENSORS_SUBFEATURE_IN_MIN);
330        sfmax = sensors_get_subfeature(name, feature,
331                                       SENSORS_SUBFEATURE_IN_MAX);
332        if (sfmin && sfmax)
333                printf("  (min = %+6.2f V, max = %+6.2f V)",
334                       get_value(name, sfmin),
335                       get_value(name, sfmax));
336        else if (sfmin)
337                printf("  (min = %+6.2f V)",
338                       get_value(name, sfmin));
339        else if (sfmax)
340                printf("  (max = %+6.2f V)",
341                       get_value(name, sfmax));
342
343        sf = sensors_get_subfeature(name, feature,
344                                    SENSORS_SUBFEATURE_IN_ALARM);
345        sfmin = sensors_get_subfeature(name, feature,
346                                       SENSORS_SUBFEATURE_IN_MIN_ALARM);
347        sfmax = sensors_get_subfeature(name, feature,
348                                       SENSORS_SUBFEATURE_IN_MAX_ALARM);
349        if (sfmin || sfmax) {
350                alarm_max = sfmax ? get_value(name, sfmax) : 0;
351                alarm_min = sfmin ? get_value(name, sfmin) : 0;
352
353                if (alarm_min || alarm_max) {
354                        printf(" ALARM (");
355
356                        if (alarm_min)
357                                printf("MIN");
358                        if (alarm_max)
359                                printf("%sMAX", (alarm_min) ? ", " : "");
360
361                        printf(")");
362                }
363        } else if (sf) {
364                printf("   %s",
365                       get_value(name, sf) ? "ALARM" : "");
366        }
367
368        printf("\n");
369}
370
371static void print_chip_fan(const sensors_chip_name *name,
372                           const sensors_feature *feature,
373                           int label_size)
374{
375        const sensors_subfeature *sf, *sfmin, *sfdiv;
376        double val;
377        char *label;
378
379        if (!(label = sensors_get_label(name, feature))) {
380                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
381                        feature->name);
382                return;
383        }
384        print_label(label, label_size);
385        free(label);
386
387        sf = sensors_get_subfeature(name, feature,
388                                    SENSORS_SUBFEATURE_FAN_FAULT);
389        if (sf && get_value(name, sf))
390                printf("   FAULT");
391        else {
392                sf = sensors_get_subfeature(name, feature,
393                                            SENSORS_SUBFEATURE_FAN_INPUT);
394                if (sf && get_input_value(name, sf, &val) == 0)
395                        printf("%4.0f RPM", val);
396                else
397                        printf("     N/A");
398        }
399
400        sfmin = sensors_get_subfeature(name, feature,
401                                       SENSORS_SUBFEATURE_FAN_MIN);
402        sfdiv = sensors_get_subfeature(name, feature,
403                                       SENSORS_SUBFEATURE_FAN_DIV);
404        if (sfmin && sfdiv)
405                printf("  (min = %4.0f RPM, div = %1.0f)",
406                       get_value(name, sfmin),
407                       get_value(name, sfdiv));
408        else if (sfmin)
409                printf("  (min = %4.0f RPM)",
410                       get_value(name, sfmin));
411        else if (sfdiv)
412                printf("  (div = %1.0f)",
413                       get_value(name, sfdiv));
414
415        sf = sensors_get_subfeature(name, feature,
416                                    SENSORS_SUBFEATURE_FAN_ALARM);
417        if (sf && get_value(name, sf)) {
418                printf("  ALARM");
419        }
420
421        printf("\n");
422}
423
424struct scale_table {
425        double upper_bound;
426        const char *unit;
427};
428
429static void scale_value(double *value, const char **prefixstr)
430{
431        double abs_value = fabs(*value);
432        double divisor = 1e-9;
433        static struct scale_table prefix_scales[] = {
434                {1e-6, "n"},
435                {1e-3, "u"},
436                {1,    "m"},
437                {1e3,   ""},
438                {1e6,  "k"},
439                {1e9,  "M"},
440                {0,    "G"}, /* no upper bound */
441        };
442        struct scale_table *scale = prefix_scales;
443
444        while (scale->upper_bound && abs_value > scale->upper_bound) {
445                divisor = scale->upper_bound;
446                scale++;
447        }
448
449        *value /= divisor;
450        *prefixstr = scale->unit;
451}
452
453static void print_chip_power(const sensors_chip_name *name,
454                             const sensors_feature *feature,
455                             int label_size)
456{
457        double val;
458        int need_space = 0;
459        const sensors_subfeature *sf, *sfmin, *sfmax, *sfint;
460        char *label;
461        const char *unit;
462
463        if (!(label = sensors_get_label(name, feature))) {
464                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
465                        feature->name);
466                return;
467        }
468        print_label(label, label_size);
469        free(label);
470
471        /* Power sensors come in 2 flavors: instantaneous and averaged.
472           To keep things simple, we assume that each sensor only implements
473           one flavor. */
474        sf = sensors_get_subfeature(name, feature,
475                                    SENSORS_SUBFEATURE_POWER_INPUT);
476        if (sf) {
477                sfmin = sensors_get_subfeature(name, feature,
478                                               SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST);
479                sfmax = sensors_get_subfeature(name, feature,
480                                               SENSORS_SUBFEATURE_POWER_INPUT_LOWEST);
481                sfint = NULL;
482        } else {
483                sf = sensors_get_subfeature(name, feature,
484                                            SENSORS_SUBFEATURE_POWER_AVERAGE);
485                sfmin = sensors_get_subfeature(name, feature,
486                                               SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST);
487                sfmax = sensors_get_subfeature(name, feature,
488                                               SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST);
489                sfint = sensors_get_subfeature(name, feature,
490                                               SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL);
491        }
492
493        if (sf && get_input_value(name, sf, &val) == 0) {
494                scale_value(&val, &unit);
495                printf("%6.2f %sW", val, unit);
496        } else
497                printf("     N/A");
498
499        if (sfmin || sfmax || sfint) {
500                printf("  (");
501
502                if (sfmin) {
503                        val = get_value(name, sfmin);
504                        scale_value(&val, &unit);
505                        printf("min = %6.2f %sW", val, unit);
506                        need_space = 1;
507                }
508
509                if (sfmax) {
510                        val = get_value(name, sfmax);
511                        scale_value(&val, &unit);
512                        printf("%smax = %6.2f %sW", (need_space ? ", " : ""),
513                               val, unit);
514                        need_space = 1;
515                }
516
517                if (sfint) {
518                        printf("%sinterval = %6.2f s", (need_space ? ", " : ""),
519                               get_value(name, sfint));
520                        need_space = 1;
521                }
522                printf(")");
523        }
524
525        printf("\n");
526}
527
528static void print_chip_energy(const sensors_chip_name *name,
529                              const sensors_feature *feature,
530                              int label_size)
531{
532        double val;
533        const sensors_subfeature *sf;
534        char *label;
535        const char *unit;
536
537        if (!(label = sensors_get_label(name, feature))) {
538                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
539                        feature->name);
540                return;
541        }
542        print_label(label, label_size);
543        free(label);
544
545        sf = sensors_get_subfeature(name, feature,
546                                    SENSORS_SUBFEATURE_ENERGY_INPUT);
547        if (sf && get_input_value(name, sf, &val) == 0) {
548                scale_value(&val, &unit);
549                printf("%6.2f %sJ", val, unit);
550        } else
551                printf("     N/A");
552
553        printf("\n");
554}
555
556static void print_chip_vid(const sensors_chip_name *name,
557                           const sensors_feature *feature,
558                           int label_size)
559{
560        char *label;
561        const sensors_subfeature *subfeature;
562        double vid;
563
564        subfeature = sensors_get_subfeature(name, feature,
565                                            SENSORS_SUBFEATURE_VID);
566        if (!subfeature)
567                return;
568
569        if ((label = sensors_get_label(name, feature))
570         && !sensors_get_value(name, subfeature->number, &vid)) {
571                print_label(label, label_size);
572                printf("%+6.3f V\n", vid);
573        }
574        free(label);
575}
576
577static void print_chip_beep_enable(const sensors_chip_name *name,
578                                   const sensors_feature *feature,
579                                   int label_size)
580{
581        char *label;
582        const sensors_subfeature *subfeature;
583        double beep_enable;
584
585        subfeature = sensors_get_subfeature(name, feature,
586                                            SENSORS_SUBFEATURE_BEEP_ENABLE);
587        if (!subfeature)
588                return;
589
590        if ((label = sensors_get_label(name, feature))
591         && !sensors_get_value(name, subfeature->number, &beep_enable)) {
592                print_label(label, label_size);
593                printf("%s\n", beep_enable ? "enabled" : "disabled");
594        }
595        free(label);
596}
597
598static void print_chip_curr(const sensors_chip_name *name,
599                            const sensors_feature *feature,
600                            int label_size)
601{
602        const sensors_subfeature *sf, *sfmin, *sfmax;
603        double alarm_max, alarm_min, val;
604        char *label;
605
606        if (!(label = sensors_get_label(name, feature))) {
607                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
608                        feature->name);
609                return;
610        }
611        print_label(label, label_size);
612        free(label);
613
614        sf = sensors_get_subfeature(name, feature,
615                                    SENSORS_SUBFEATURE_CURR_INPUT);
616        if (sf && get_input_value(name, sf, &val) == 0)
617                printf("%+6.2f A", val);
618        else
619                printf("     N/A");
620
621        sfmin = sensors_get_subfeature(name, feature,
622                                       SENSORS_SUBFEATURE_CURR_MIN);
623        sfmax = sensors_get_subfeature(name, feature,
624                                       SENSORS_SUBFEATURE_CURR_MAX);
625        if (sfmin && sfmax)
626                printf("  (min = %+6.2f A, max = %+6.2f A)",
627                       get_value(name, sfmin),
628                       get_value(name, sfmax));
629        else if (sfmin)
630                printf("  (min = %+6.2f A)",
631                       get_value(name, sfmin));
632        else if (sfmax)
633                printf("  (max = %+6.2f A)",
634                       get_value(name, sfmax));
635
636        sf = sensors_get_subfeature(name, feature,
637                                    SENSORS_SUBFEATURE_CURR_ALARM);
638        sfmin = sensors_get_subfeature(name, feature,
639                                       SENSORS_SUBFEATURE_CURR_MIN_ALARM);
640        sfmax = sensors_get_subfeature(name, feature,
641                                       SENSORS_SUBFEATURE_CURR_MAX_ALARM);
642        if (sfmin || sfmax) {
643                alarm_max = sfmax ? get_value(name, sfmax) : 0;
644                alarm_min = sfmin ? get_value(name, sfmin) : 0;
645
646                if (alarm_min || alarm_max) {
647                        printf(" ALARM (");
648
649                        if (alarm_min)
650                                printf("MIN");
651                        if (alarm_max)
652                                printf("%sMAX", (alarm_min) ? ", " : "");
653
654                        printf(")");
655                }
656        } else if (sf) {
657                printf("   %s",
658                       get_value(name, sf) ? "ALARM" : "");
659        }
660
661        printf("\n");
662}
663
664void print_chip(const sensors_chip_name *name)
665{
666        const sensors_feature *feature;
667        int i, label_size;
668
669        label_size = get_label_size(name);
670
671        i = 0;
672        while ((feature = sensors_get_features(name, &i))) {
673                switch (feature->type) {
674                case SENSORS_FEATURE_TEMP:
675                        print_chip_temp(name, feature, label_size);
676                        break;
677                case SENSORS_FEATURE_IN:
678                        print_chip_in(name, feature, label_size);
679                        break;
680                case SENSORS_FEATURE_FAN:
681                        print_chip_fan(name, feature, label_size);
682                        break;
683                case SENSORS_FEATURE_VID:
684                        print_chip_vid(name, feature, label_size);
685                        break;
686                case SENSORS_FEATURE_BEEP_ENABLE:
687                        print_chip_beep_enable(name, feature, label_size);
688                        break;
689                case SENSORS_FEATURE_POWER:
690                        print_chip_power(name, feature, label_size);
691                        break;
692                case SENSORS_FEATURE_ENERGY:
693                        print_chip_energy(name, feature, label_size);
694                        break;
695                case SENSORS_FEATURE_CURR:
696                        print_chip_curr(name, feature, label_size);
697                        break;
698                default:
699                        continue;
700                }
701        }
702}
Note: See TracBrowser for help on using the browser.