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

Revision 6030, 22.2 KB (checked in by groeck, 2 months ago)

Fix power interval output

Power interval is measured in seconds, not Watt.

  • 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-2010  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
33#define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
34
35void print_chip_raw(const sensors_chip_name *name)
36{
37        int a, b, err;
38        const sensors_feature *feature;
39        const sensors_subfeature *sub;
40        char *label;
41        double val;
42
43        a = 0;
44        while ((feature = sensors_get_features(name, &a))) {
45                if (!(label = sensors_get_label(name, feature))) {
46                        fprintf(stderr, "ERROR: Can't get label of feature "
47                                "%s!\n", feature->name);
48                        continue;
49                }
50                printf("%s:\n", label);
51                free(label);
52
53                b = 0;
54                while ((sub = sensors_get_all_subfeatures(name, feature, &b))) {
55                        if (sub->flags & SENSORS_MODE_R) {
56                                if ((err = sensors_get_value(name, sub->number,
57                                                             &val)))
58                                        fprintf(stderr, "ERROR: Can't get "
59                                                "value of subfeature %s: %s\n",
60                                                sub->name,
61                                                sensors_strerror(err));
62                                else
63                                        printf("  %s: %.3f\n", sub->name, val);
64                        } else
65                                printf("(%s)\n", label);
66                }
67        }
68}
69
70static const char hyst_str[] = "hyst";
71
72static inline double deg_ctof(double cel)
73{
74        return cel * (9.0F / 5.0F) + 32.0F;
75}
76
77static void print_label(const char *label, int space)
78{
79        int len = strlen(label)+1;
80        printf("%s:%*s", label, space - len, "");
81}
82
83static double get_value(const sensors_chip_name *name,
84                        const sensors_subfeature *sub)
85{
86        double val;
87        int err;
88
89        err = sensors_get_value(name, sub->number, &val);
90        if (err) {
91                fprintf(stderr, "ERROR: Can't get value of subfeature %s: %s\n",
92                        sub->name, sensors_strerror(err));
93                val = 0;
94        }
95        return val;
96}
97
98/* A variant for input values, where we want to handle errors gracefully */
99static int get_input_value(const sensors_chip_name *name,
100                           const sensors_subfeature *sub,
101                           double *val)
102{
103        int err;
104
105        err = sensors_get_value(name, sub->number, val);
106        if (err && err != -SENSORS_ERR_ACCESS_R) {
107                fprintf(stderr, "ERROR: Can't get value of subfeature %s: %s\n",
108                        sub->name, sensors_strerror(err));
109        }
110        return err;
111}
112
113static int get_label_size(const sensors_chip_name *name)
114{
115        int i;
116        const sensors_feature *iter;
117        char *label;
118        unsigned int max_size = 11;     /* 11 as minumum label width */
119
120        i = 0;
121        while ((iter = sensors_get_features(name, &i))) {
122                if ((label = sensors_get_label(name, iter)) &&
123                    strlen(label) > max_size)
124                        max_size = strlen(label);
125                free(label);
126        }
127
128        /* One more for the colon, and one more to guarantee at least one
129           space between that colon and the value */
130        return max_size + 2;
131}
132
133static void print_alarms(struct sensor_subfeature_data *alarms, int alarm_count,
134                         int leading_spaces)
135{
136        int i, printed;
137
138        printf("%*s", leading_spaces + 7, "ALARM");
139        if (alarm_count > 1 || alarms[0].name) {
140                printf(" (");
141                for (i = printed = 0; i < alarm_count; i++) {
142                        if (alarms[i].name) {
143                                if (printed)
144                                        printf(", ");
145                                printf("%s", alarms[i].name);
146                                printed = 1;
147                        }
148                }
149                printf(")");
150        }
151}
152
153static void print_limits(struct sensor_subfeature_data *limits,
154                         int limit_count,
155                         struct sensor_subfeature_data *alarms,
156                         int alarm_count, int label_size,
157                         const char *fmt)
158{
159        int i, slot, skip;
160        int alarms_printed = 0;
161
162        /*
163         * We print limits on two columns, filling lines first, except for
164         * hysteresis which must always go on the right column, with the
165         * limit it relates to being in the left column on the same line.
166         */
167        for (i = slot = 0; i < limit_count; i++, slot++) {
168                if (!(slot & 1)) {
169                        if (slot)
170                                printf("\n%*s", label_size + 10, "");
171                        printf("(");
172                } else {
173                        printf(", ");
174                }
175                printf(fmt, limits[i].name, limits[i].value,
176                             limits[i].unit);
177
178                /* If needed, skip one slot to avoid hyst on first column */
179                skip = i + 2 < limit_count && limits[i + 2].name == hyst_str &&
180                       !(slot & 1);
181
182                if (((slot + skip) & 1) || i == limit_count - 1) {
183                        printf(")");
184                        if (alarm_count && !alarms_printed) {
185                                print_alarms(alarms, alarm_count,
186                                             (slot & 1) ? 0 : 16);
187                                alarms_printed = 1;
188                        }
189                }
190                slot += skip;
191        }
192        if (alarm_count && !alarms_printed)
193                print_alarms(alarms, alarm_count, 32);
194}
195
196/*
197 * Get sensor limit information.
198 * *num_limits and *num_alarms must be initialized by the caller.
199 */
200static void get_sensor_limit_data(const sensors_chip_name *name,
201                                  const sensors_feature *feature,
202                                  const struct sensor_subfeature_list *sfl,
203                                  struct sensor_subfeature_data *limits,
204                                  int *num_limits,
205                                  struct sensor_subfeature_data *alarms,
206                                  int *num_alarms)
207{
208        const sensors_subfeature *sf;
209
210        for (; sfl->subfeature >= 0; sfl++) {
211                sf = sensors_get_subfeature(name, feature, sfl->subfeature);
212                if (sf) {
213                        if (sfl->alarm) {
214                                /*
215                                 * Only queue alarm subfeatures if the alarm
216                                 * is active, and don't store the alarm value
217                                 * (it is implied to be active if queued).
218                                 */
219                                if (get_value(name, sf)) {
220                                        alarms[*num_alarms].name = sfl->name;
221                                        (*num_alarms)++;
222                                }
223                        } else {
224                                /*
225                                 * Always queue limit subfeatures with their value.
226                                 */
227                                limits[*num_limits].value = get_value(name, sf);
228                                limits[*num_limits].name = sfl->name;
229                                (*num_limits)++;
230                        }
231                        if (sfl->exists) {
232                                get_sensor_limit_data(name, feature, sfl->exists,
233                                                      limits, num_limits,
234                                                      alarms, num_alarms);
235                        }
236                }
237        }
238}
239
240static const struct sensor_subfeature_list temp_max_sensors[] = {
241        { SENSORS_SUBFEATURE_TEMP_MAX_HYST, NULL, 0, hyst_str },
242        { -1, NULL, 0, NULL }
243};
244
245static const struct sensor_subfeature_list temp_crit_sensors[] = {
246        { SENSORS_SUBFEATURE_TEMP_CRIT_HYST, NULL, 0, hyst_str },
247        { -1, NULL, 0, NULL }
248};
249
250static const struct sensor_subfeature_list temp_emergency_sensors[] = {
251        { SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST, NULL, 0,
252            hyst_str },
253        { -1, NULL, 0, NULL }
254};
255
256static const struct sensor_subfeature_list temp_sensors[] = {
257        { SENSORS_SUBFEATURE_TEMP_ALARM, NULL, 1, NULL },
258        { SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM, NULL, 1, "LCRIT" },
259        { SENSORS_SUBFEATURE_TEMP_MIN_ALARM, NULL, 1, "LOW" },
260        { SENSORS_SUBFEATURE_TEMP_MAX_ALARM, NULL, 1, "HIGH" },
261        { SENSORS_SUBFEATURE_TEMP_CRIT_ALARM, NULL, 1, "CRIT" },
262        { SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM, NULL, 1, "EMERGENCY" },
263        { SENSORS_SUBFEATURE_TEMP_MIN, NULL, 0, "low" },
264        { SENSORS_SUBFEATURE_TEMP_MAX, temp_max_sensors, 0, "high" },
265        { SENSORS_SUBFEATURE_TEMP_LCRIT, NULL, 0, "crit low" },
266        { SENSORS_SUBFEATURE_TEMP_CRIT, temp_crit_sensors, 0, "crit" },
267        { SENSORS_SUBFEATURE_TEMP_EMERGENCY, temp_emergency_sensors, 0,
268            "emerg" },
269        { SENSORS_SUBFEATURE_TEMP_LOWEST, NULL, 0, "lowest" },
270        { SENSORS_SUBFEATURE_TEMP_HIGHEST, NULL, 0, "highest" },
271        { -1, NULL, 0, NULL }
272};
273
274#define NUM_TEMP_ALARMS         6
275#define NUM_TEMP_SENSORS        (ARRAY_SIZE(temp_sensors) \
276                                 + ARRAY_SIZE(temp_max_sensors) \
277                                 + ARRAY_SIZE(temp_crit_sensors) \
278                                 + ARRAY_SIZE(temp_emergency_sensors) \
279                                 - NUM_TEMP_ALARMS - 4)
280
281static void print_chip_temp(const sensors_chip_name *name,
282                            const sensors_feature *feature,
283                            int label_size)
284{
285        struct sensor_subfeature_data sensors[NUM_TEMP_SENSORS];
286        struct sensor_subfeature_data alarms[NUM_TEMP_ALARMS];
287        int sensor_count, alarm_count;
288        const sensors_subfeature *sf;
289        double val;
290        char *label;
291        int i;
292
293        if (!(label = sensors_get_label(name, feature))) {
294                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
295                        feature->name);
296                return;
297        }
298        print_label(label, label_size);
299        free(label);
300
301        sf = sensors_get_subfeature(name, feature,
302                                    SENSORS_SUBFEATURE_TEMP_FAULT);
303        if (sf && get_value(name, sf)) {
304                printf("   FAULT  ");
305        } else {
306                sf = sensors_get_subfeature(name, feature,
307                                            SENSORS_SUBFEATURE_TEMP_INPUT);
308                if (sf && get_input_value(name, sf, &val) == 0) {
309                        get_input_value(name, sf, &val);
310                        if (fahrenheit)
311                                val = deg_ctof(val);
312                        printf("%+6.1f%s  ", val, degstr);
313                } else
314                        printf("     N/A  ");
315        }
316
317        sensor_count = alarm_count = 0;
318        get_sensor_limit_data(name, feature, temp_sensors,
319                              sensors, &sensor_count, alarms, &alarm_count);
320
321        for (i = 0; i < sensor_count; i++) {
322                if (fahrenheit)
323                        sensors[i].value = deg_ctof(sensors[i].value);
324                sensors[i].unit = degstr;
325        }
326
327        print_limits(sensors, sensor_count, alarms, alarm_count, label_size,
328                     "%-4s = %+5.1f%s");
329
330        /* print out temperature sensor info */
331        sf = sensors_get_subfeature(name, feature,
332                                    SENSORS_SUBFEATURE_TEMP_TYPE);
333        if (sf) {
334                int sens = (int)get_value(name, sf);
335
336                /* older kernels / drivers sometimes report a beta value for
337                   thermistors */
338                if (sens > 1000)
339                        sens = 4;
340
341                printf("  sensor = %s", sens == 0 ? "disabled" :
342                       sens == 1 ? "CPU diode" :
343                       sens == 2 ? "transistor" :
344                       sens == 3 ? "thermal diode" :
345                       sens == 4 ? "thermistor" :
346                       sens == 5 ? "AMD AMDSI" :
347                       sens == 6 ? "Intel PECI" : "unknown");
348        }
349        printf("\n");
350}
351
352static const struct sensor_subfeature_list voltage_sensors[] = {
353        { SENSORS_SUBFEATURE_IN_ALARM, NULL, 1, NULL },
354        { SENSORS_SUBFEATURE_IN_LCRIT_ALARM, NULL, 1, "LCRIT" },
355        { SENSORS_SUBFEATURE_IN_MIN_ALARM, NULL, 1, "MIN" },
356        { SENSORS_SUBFEATURE_IN_MAX_ALARM, NULL, 1, "MAX" },
357        { SENSORS_SUBFEATURE_IN_CRIT_ALARM, NULL, 1, "CRIT" },
358        { SENSORS_SUBFEATURE_IN_LCRIT, NULL, 0, "crit min" },
359        { SENSORS_SUBFEATURE_IN_MIN, NULL, 0, "min" },
360        { SENSORS_SUBFEATURE_IN_MAX, NULL, 0, "max" },
361        { SENSORS_SUBFEATURE_IN_CRIT, NULL, 0, "crit max" },
362        { SENSORS_SUBFEATURE_IN_AVERAGE, NULL, 0, "avg" },
363        { SENSORS_SUBFEATURE_IN_LOWEST, NULL, 0, "lowest" },
364        { SENSORS_SUBFEATURE_IN_HIGHEST, NULL, 0, "highest" },
365        { -1, NULL, 0, NULL }
366};
367
368#define NUM_IN_ALARMS   5
369#define NUM_IN_SENSORS  (ARRAY_SIZE(voltage_sensors) - NUM_IN_ALARMS - 1)
370
371static void print_chip_in(const sensors_chip_name *name,
372                          const sensors_feature *feature,
373                          int label_size)
374{
375        const sensors_subfeature *sf;
376        char *label;
377        struct sensor_subfeature_data sensors[NUM_IN_SENSORS];
378        struct sensor_subfeature_data alarms[NUM_IN_ALARMS];
379        int sensor_count, alarm_count;
380        double val;
381
382        if (!(label = sensors_get_label(name, feature))) {
383                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
384                        feature->name);
385                return;
386        }
387        print_label(label, label_size);
388        free(label);
389
390        sf = sensors_get_subfeature(name, feature,
391                                    SENSORS_SUBFEATURE_IN_INPUT);
392        if (sf && get_input_value(name, sf, &val) == 0)
393                printf("%+6.2f V  ", val);
394        else
395                printf("     N/A  ");
396
397        sensor_count = alarm_count = 0;
398        get_sensor_limit_data(name, feature, voltage_sensors,
399                              sensors, &sensor_count, alarms, &alarm_count);
400
401        print_limits(sensors, sensor_count, alarms, alarm_count, label_size,
402                     "%s = %+6.2f V");
403
404        printf("\n");
405}
406
407static void print_chip_fan(const sensors_chip_name *name,
408                           const sensors_feature *feature,
409                           int label_size)
410{
411        const sensors_subfeature *sf, *sfmin, *sfmax, *sfdiv;
412        double val;
413        char *label;
414
415        if (!(label = sensors_get_label(name, feature))) {
416                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
417                        feature->name);
418                return;
419        }
420        print_label(label, label_size);
421        free(label);
422
423        sf = sensors_get_subfeature(name, feature,
424                                    SENSORS_SUBFEATURE_FAN_FAULT);
425        if (sf && get_value(name, sf))
426                printf("   FAULT");
427        else {
428                sf = sensors_get_subfeature(name, feature,
429                                            SENSORS_SUBFEATURE_FAN_INPUT);
430                if (sf && get_input_value(name, sf, &val) == 0)
431                        printf("%4.0f RPM", val);
432                else
433                        printf("     N/A");
434        }
435
436        sfmin = sensors_get_subfeature(name, feature,
437                                       SENSORS_SUBFEATURE_FAN_MIN);
438        sfmax = sensors_get_subfeature(name, feature,
439                                       SENSORS_SUBFEATURE_FAN_MAX);
440        sfdiv = sensors_get_subfeature(name, feature,
441                                       SENSORS_SUBFEATURE_FAN_DIV);
442        if (sfmin || sfmax || sfdiv) {
443                printf("  (");
444                if (sfmin)
445                        printf("min = %4.0f RPM",
446                               get_value(name, sfmin));
447                if (sfmax)
448                        printf("%smax = %4.0f RPM",
449                               sfmin ? ", " : "",
450                               get_value(name, sfmax));
451                if (sfdiv)
452                        printf("%sdiv = %1.0f",
453                               (sfmin || sfmax) ? ", " : "",
454                               get_value(name, sfdiv));
455                printf(")");
456        }
457
458        sf = sensors_get_subfeature(name, feature,
459                                    SENSORS_SUBFEATURE_FAN_ALARM);
460        sfmin = sensors_get_subfeature(name, feature,
461                                       SENSORS_SUBFEATURE_FAN_MIN_ALARM);
462        sfmax = sensors_get_subfeature(name, feature,
463                                       SENSORS_SUBFEATURE_FAN_MAX_ALARM);
464        if ((sf && get_value(name, sf)) ||
465            (sfmin && get_value(name, sfmin)) ||
466            (sfmax && get_value(name, sfmax)))
467                printf("  ALARM");
468
469        printf("\n");
470}
471
472struct scale_table {
473        double upper_bound;
474        const char *unit;
475};
476
477static void scale_value(double *value, const char **prefixstr)
478{
479        double abs_value = fabs(*value);
480        double divisor = 1e-9;
481        static struct scale_table prefix_scales[] = {
482                {1e-6, "n"},
483                {1e-3, "u"},
484                {1,    "m"},
485                {1e3,   ""},
486                {1e6,  "k"},
487                {1e9,  "M"},
488                {0,    "G"}, /* no upper bound */
489        };
490        struct scale_table *scale = prefix_scales;
491
492        if (abs_value == 0) {
493                *prefixstr = "";
494                return;
495        }
496
497        while (scale->upper_bound && abs_value > scale->upper_bound) {
498                divisor = scale->upper_bound;
499                scale++;
500        }
501
502        *value /= divisor;
503        *prefixstr = scale->unit;
504}
505
506static const struct sensor_subfeature_list power_common_sensors[] = {
507        { SENSORS_SUBFEATURE_POWER_ALARM, NULL, 1, NULL },
508        { SENSORS_SUBFEATURE_POWER_MAX_ALARM, NULL, 1, "MAX" },
509        { SENSORS_SUBFEATURE_POWER_CRIT_ALARM, NULL, 1, "CRIT" },
510        { SENSORS_SUBFEATURE_POWER_CAP_ALARM, NULL, 1, "CAP" },
511        { SENSORS_SUBFEATURE_POWER_MAX, NULL, 0, "max" },
512        { SENSORS_SUBFEATURE_POWER_CRIT, NULL, 0, "crit" },
513        { SENSORS_SUBFEATURE_POWER_CAP, NULL, 0, "cap" },
514        { -1, NULL, 0, NULL }
515};
516
517static const struct sensor_subfeature_list power_inst_sensors[] = {
518        { SENSORS_SUBFEATURE_POWER_INPUT_LOWEST, NULL, 0, "lowest" },
519        { SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST, NULL, 0, "highest" },
520        { SENSORS_SUBFEATURE_POWER_AVERAGE, NULL, 0, "avg" },
521        { SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, NULL, 0, "avg lowest" },
522        { SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, NULL, 0, "avg highest" },
523        { SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL, NULL, 0,
524                "interval" },
525        { -1, NULL, 0, NULL }
526};
527
528static const struct sensor_subfeature_list power_avg_sensors[] = {
529        { SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, NULL, 0, "lowest" },
530        { SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, NULL, 0, "highest" },
531        { SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL, NULL, 0,
532                "interval" },
533        { -1, NULL, 0, NULL }
534};
535
536#define NUM_POWER_ALARMS        4
537#define NUM_POWER_SENSORS       (ARRAY_SIZE(power_common_sensors) \
538                                 + ARRAY_SIZE(power_inst_sensors) \
539                                 - NUM_POWER_ALARMS - 2)
540
541static void print_chip_power(const sensors_chip_name *name,
542                             const sensors_feature *feature,
543                             int label_size)
544{
545        double val;
546        const sensors_subfeature *sf;
547        struct sensor_subfeature_data sensors[NUM_POWER_SENSORS];
548        struct sensor_subfeature_data alarms[NUM_POWER_ALARMS];
549        int sensor_count, alarm_count;
550        char *label;
551        const char *unit;
552        int i;
553
554        if (!(label = sensors_get_label(name, feature))) {
555                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
556                        feature->name);
557                return;
558        }
559        print_label(label, label_size);
560        free(label);
561
562        sensor_count = alarm_count = 0;
563
564        /*
565         * Power sensors come in 2 flavors: instantaneous and averaged.
566         * Most devices only support one flavor, so we try to display the
567         * average power if the instantaneous power attribute does not exist.
568         * If both instantaneous power and average power are supported,
569         * average power is displayed as limit.
570         */
571        sf = sensors_get_subfeature(name, feature,
572                                    SENSORS_SUBFEATURE_POWER_INPUT);
573        get_sensor_limit_data(name, feature,
574                              sf ? power_inst_sensors : power_avg_sensors,
575                              sensors, &sensor_count, alarms, &alarm_count);
576        /* Add sensors common to both flavors. */
577        get_sensor_limit_data(name, feature, power_common_sensors,
578                              sensors, &sensor_count, alarms, &alarm_count);
579        if (!sf)
580                sf = sensors_get_subfeature(name, feature,
581                                            SENSORS_SUBFEATURE_POWER_AVERAGE);
582
583        if (sf && get_input_value(name, sf, &val) == 0) {
584                scale_value(&val, &unit);
585                printf("%6.2f %sW%*s", val, unit, 2 - (int)strlen(unit), "");
586        } else
587                printf("     N/A  ");
588
589        for (i = 0; i < sensor_count; i++) {
590                /*
591                 * Unit is W and needs to be scaled for all attributes except
592                 * interval, which does not need to be scaled and is reported in
593                 * seconds.
594                 */
595                if (strcmp(sensors[i].name, "interval")) {
596                        char *tmpstr;
597
598                        tmpstr = alloca(4);
599                        scale_value(&sensors[i].value, &unit);
600                        snprintf(tmpstr, 4, "%sW", unit);
601                        sensors[i].unit = tmpstr;
602                } else {
603                        sensors[i].unit = "s";
604                }
605        }
606        print_limits(sensors, sensor_count, alarms, alarm_count,
607                     label_size, "%s = %6.2f %s");
608
609        printf("\n");
610}
611
612static void print_chip_energy(const sensors_chip_name *name,
613                              const sensors_feature *feature,
614                              int label_size)
615{
616        double val;
617        const sensors_subfeature *sf;
618        char *label;
619        const char *unit;
620
621        if (!(label = sensors_get_label(name, feature))) {
622                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
623                        feature->name);
624                return;
625        }
626        print_label(label, label_size);
627        free(label);
628
629        sf = sensors_get_subfeature(name, feature,
630                                    SENSORS_SUBFEATURE_ENERGY_INPUT);
631        if (sf && get_input_value(name, sf, &val) == 0) {
632                scale_value(&val, &unit);
633                printf("%6.2f %sJ", val, unit);
634        } else
635                printf("     N/A");
636
637        printf("\n");
638}
639
640static void print_chip_vid(const sensors_chip_name *name,
641                           const sensors_feature *feature,
642                           int label_size)
643{
644        char *label;
645        const sensors_subfeature *subfeature;
646        double vid;
647
648        subfeature = sensors_get_subfeature(name, feature,
649                                            SENSORS_SUBFEATURE_VID);
650        if (!subfeature)
651                return;
652
653        if ((label = sensors_get_label(name, feature))
654         && !sensors_get_value(name, subfeature->number, &vid)) {
655                print_label(label, label_size);
656                printf("%+6.3f V\n", vid);
657        }
658        free(label);
659}
660
661static void print_chip_beep_enable(const sensors_chip_name *name,
662                                   const sensors_feature *feature,
663                                   int label_size)
664{
665        char *label;
666        const sensors_subfeature *subfeature;
667        double beep_enable;
668
669        subfeature = sensors_get_subfeature(name, feature,
670                                            SENSORS_SUBFEATURE_BEEP_ENABLE);
671        if (!subfeature)
672                return;
673
674        if ((label = sensors_get_label(name, feature))
675         && !sensors_get_value(name, subfeature->number, &beep_enable)) {
676                print_label(label, label_size);
677                printf("%s\n", beep_enable ? "enabled" : "disabled");
678        }
679        free(label);
680}
681
682static const struct sensor_subfeature_list current_sensors[] = {
683        { SENSORS_SUBFEATURE_CURR_ALARM, NULL, 1, NULL },
684        { SENSORS_SUBFEATURE_CURR_LCRIT_ALARM, NULL, 1, "LCRIT" },
685        { SENSORS_SUBFEATURE_CURR_MIN_ALARM, NULL, 1, "MIN" },
686        { SENSORS_SUBFEATURE_CURR_MAX_ALARM, NULL, 1, "MAX" },
687        { SENSORS_SUBFEATURE_CURR_CRIT_ALARM, NULL, 1, "CRIT" },
688        { SENSORS_SUBFEATURE_CURR_LCRIT, NULL, 0, "crit min" },
689        { SENSORS_SUBFEATURE_CURR_MIN, NULL, 0, "min" },
690        { SENSORS_SUBFEATURE_CURR_MAX, NULL, 0, "max" },
691        { SENSORS_SUBFEATURE_CURR_CRIT, NULL, 0, "crit max" },
692        { SENSORS_SUBFEATURE_CURR_AVERAGE, NULL, 0, "avg" },
693        { SENSORS_SUBFEATURE_CURR_LOWEST, NULL, 0, "lowest" },
694        { SENSORS_SUBFEATURE_CURR_HIGHEST, NULL, 0, "highest" },
695        { -1, NULL, 0, NULL }
696};
697
698#define NUM_CURR_ALARMS         5
699#define NUM_CURR_SENSORS        (ARRAY_SIZE(current_sensors) - NUM_CURR_ALARMS - 1)
700
701static void print_chip_curr(const sensors_chip_name *name,
702                            const sensors_feature *feature,
703                            int label_size)
704{
705        const sensors_subfeature *sf;
706        double val;
707        char *label;
708        struct sensor_subfeature_data sensors[NUM_CURR_SENSORS];
709        struct sensor_subfeature_data alarms[NUM_CURR_ALARMS];
710        int sensor_count, alarm_count;
711
712        if (!(label = sensors_get_label(name, feature))) {
713                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
714                        feature->name);
715                return;
716        }
717        print_label(label, label_size);
718        free(label);
719
720        sf = sensors_get_subfeature(name, feature,
721                                    SENSORS_SUBFEATURE_CURR_INPUT);
722        if (sf && get_input_value(name, sf, &val) == 0)
723                printf("%+6.2f A  ", val);
724        else
725                printf("     N/A  ");
726
727        sensor_count = alarm_count = 0;
728        get_sensor_limit_data(name, feature, current_sensors,
729                              sensors, &sensor_count, alarms, &alarm_count);
730
731        print_limits(sensors, sensor_count, alarms, alarm_count, label_size,
732                     "%s = %+6.2f A");
733
734        printf("\n");
735}
736
737static void print_chip_intrusion(const sensors_chip_name *name,
738                                 const sensors_feature *feature,
739                                 int label_size)
740{
741        char *label;
742        const sensors_subfeature *subfeature;
743        double alarm;
744
745        subfeature = sensors_get_subfeature(name, feature,
746                                            SENSORS_SUBFEATURE_INTRUSION_ALARM);
747        if (!subfeature)
748                return;
749
750        if ((label = sensors_get_label(name, feature))
751         && !sensors_get_value(name, subfeature->number, &alarm)) {
752                print_label(label, label_size);
753                printf("%s\n", alarm ? "ALARM" : "OK");
754        }
755        free(label);
756}
757
758void print_chip(const sensors_chip_name *name)
759{
760        const sensors_feature *feature;
761        int i, label_size;
762
763        label_size = get_label_size(name);
764
765        i = 0;
766        while ((feature = sensors_get_features(name, &i))) {
767                switch (feature->type) {
768                case SENSORS_FEATURE_TEMP:
769                        print_chip_temp(name, feature, label_size);
770                        break;
771                case SENSORS_FEATURE_IN:
772                        print_chip_in(name, feature, label_size);
773                        break;
774                case SENSORS_FEATURE_FAN:
775                        print_chip_fan(name, feature, label_size);
776                        break;
777                case SENSORS_FEATURE_VID:
778                        print_chip_vid(name, feature, label_size);
779                        break;
780                case SENSORS_FEATURE_BEEP_ENABLE:
781                        print_chip_beep_enable(name, feature, label_size);
782                        break;
783                case SENSORS_FEATURE_POWER:
784                        print_chip_power(name, feature, label_size);
785                        break;
786                case SENSORS_FEATURE_ENERGY:
787                        print_chip_energy(name, feature, label_size);
788                        break;
789                case SENSORS_FEATURE_CURR:
790                        print_chip_curr(name, feature, label_size);
791                        break;
792                case SENSORS_FEATURE_INTRUSION:
793                        print_chip_intrusion(name, feature, label_size);
794                        break;
795                default:
796                        continue;
797                }
798        }
799}
Note: See TracBrowser for help on using the browser.