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

Revision 6008, 21.4 KB (checked in by groeck, 3 years ago)

sensors: Display both instantaneous and average power

Some sensor chips report both instantaneous and average power.
Add support to display both.

  • 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 ? "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, *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        sfdiv = sensors_get_subfeature(name, feature,
439                                       SENSORS_SUBFEATURE_FAN_DIV);
440        if (sfmin && sfdiv)
441                printf("  (min = %4.0f RPM, div = %1.0f)",
442                       get_value(name, sfmin),
443                       get_value(name, sfdiv));
444        else if (sfmin)
445                printf("  (min = %4.0f RPM)",
446                       get_value(name, sfmin));
447        else if (sfdiv)
448                printf("  (div = %1.0f)",
449                       get_value(name, sfdiv));
450
451        sf = sensors_get_subfeature(name, feature,
452                                    SENSORS_SUBFEATURE_FAN_ALARM);
453        if (sf && get_value(name, sf)) {
454                printf("  ALARM");
455        }
456
457        printf("\n");
458}
459
460struct scale_table {
461        double upper_bound;
462        const char *unit;
463};
464
465static void scale_value(double *value, const char **prefixstr)
466{
467        double abs_value = fabs(*value);
468        double divisor = 1e-9;
469        static struct scale_table prefix_scales[] = {
470                {1e-6, "n"},
471                {1e-3, "u"},
472                {1,    "m"},
473                {1e3,   ""},
474                {1e6,  "k"},
475                {1e9,  "M"},
476                {0,    "G"}, /* no upper bound */
477        };
478        struct scale_table *scale = prefix_scales;
479
480        if (abs_value == 0) {
481                *prefixstr = "";
482                return;
483        }
484
485        while (scale->upper_bound && abs_value > scale->upper_bound) {
486                divisor = scale->upper_bound;
487                scale++;
488        }
489
490        *value /= divisor;
491        *prefixstr = scale->unit;
492}
493
494static const struct sensor_subfeature_list power_common_sensors[] = {
495        { SENSORS_SUBFEATURE_POWER_ALARM, NULL, 1, NULL },
496        { SENSORS_SUBFEATURE_POWER_MAX_ALARM, NULL, 1, "MAX" },
497        { SENSORS_SUBFEATURE_POWER_CRIT_ALARM, NULL, 1, "CRIT" },
498        { SENSORS_SUBFEATURE_POWER_CAP_ALARM, NULL, 1, "CAP" },
499        { SENSORS_SUBFEATURE_POWER_MAX, NULL, 0, "max" },
500        { SENSORS_SUBFEATURE_POWER_CRIT, NULL, 0, "crit" },
501        { SENSORS_SUBFEATURE_POWER_CAP, NULL, 0, "cap" },
502        { -1, NULL, 0, NULL }
503};
504
505static const struct sensor_subfeature_list power_inst_sensors[] = {
506        { SENSORS_SUBFEATURE_POWER_INPUT_LOWEST, NULL, 0, "lowest" },
507        { SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST, NULL, 0, "highest" },
508        { SENSORS_SUBFEATURE_POWER_AVERAGE, NULL, 0, "avg" },
509        { SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, NULL, 0, "avg lowest" },
510        { SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, NULL, 0, "avg highest" },
511        { SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL, NULL, 0,
512                "interval" },
513        { -1, NULL, 0, NULL }
514};
515
516static const struct sensor_subfeature_list power_avg_sensors[] = {
517        { SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, NULL, 0, "lowest" },
518        { SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, NULL, 0, "highest" },
519        { SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL, NULL, 0,
520                "interval" },
521        { -1, NULL, 0, NULL }
522};
523
524#define NUM_POWER_ALARMS        4
525#define NUM_POWER_SENSORS       (ARRAY_SIZE(power_common_sensors) \
526                                 + ARRAY_SIZE(power_inst_sensors) \
527                                 - NUM_POWER_ALARMS - 2)
528
529static void print_chip_power(const sensors_chip_name *name,
530                             const sensors_feature *feature,
531                             int label_size)
532{
533        double val;
534        const sensors_subfeature *sf;
535        struct sensor_subfeature_data sensors[NUM_POWER_SENSORS];
536        struct sensor_subfeature_data alarms[NUM_POWER_ALARMS];
537        int sensor_count, alarm_count;
538        char *label;
539        const char *unit;
540        int i;
541
542        if (!(label = sensors_get_label(name, feature))) {
543                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
544                        feature->name);
545                return;
546        }
547        print_label(label, label_size);
548        free(label);
549
550        sensor_count = alarm_count = 0;
551
552        /*
553         * Power sensors come in 2 flavors: instantaneous and averaged.
554         * Most devices only support one flavor, so we try to display the
555         * average power if the instantaneous power attribute does not exist.
556         * If both instantaneous power and average power are supported,
557         * average power is displayed as limit.
558         */
559        sf = sensors_get_subfeature(name, feature,
560                                    SENSORS_SUBFEATURE_POWER_INPUT);
561        get_sensor_limit_data(name, feature,
562                              sf ? power_inst_sensors : power_avg_sensors,
563                              sensors, &sensor_count, alarms, &alarm_count);
564        /* Add sensors common to both flavors. */
565        get_sensor_limit_data(name, feature, power_common_sensors,
566                              sensors, &sensor_count, alarms, &alarm_count);
567        if (!sf)
568                sf = sensors_get_subfeature(name, feature,
569                                            SENSORS_SUBFEATURE_POWER_AVERAGE);
570
571        if (sf && get_input_value(name, sf, &val) == 0) {
572                scale_value(&val, &unit);
573                printf("%6.2f %sW  ", val, unit);
574        } else
575                printf("     N/A  ");
576
577        for (i = 0; i < sensor_count; i++)
578                scale_value(&sensors[i].value, &sensors[i].unit);
579
580        print_limits(sensors, sensor_count, alarms, alarm_count,
581                     label_size, "%s = %6.2f %sW");
582
583        printf("\n");
584}
585
586static void print_chip_energy(const sensors_chip_name *name,
587                              const sensors_feature *feature,
588                              int label_size)
589{
590        double val;
591        const sensors_subfeature *sf;
592        char *label;
593        const char *unit;
594
595        if (!(label = sensors_get_label(name, feature))) {
596                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
597                        feature->name);
598                return;
599        }
600        print_label(label, label_size);
601        free(label);
602
603        sf = sensors_get_subfeature(name, feature,
604                                    SENSORS_SUBFEATURE_ENERGY_INPUT);
605        if (sf && get_input_value(name, sf, &val) == 0) {
606                scale_value(&val, &unit);
607                printf("%6.2f %sJ", val, unit);
608        } else
609                printf("     N/A");
610
611        printf("\n");
612}
613
614static void print_chip_vid(const sensors_chip_name *name,
615                           const sensors_feature *feature,
616                           int label_size)
617{
618        char *label;
619        const sensors_subfeature *subfeature;
620        double vid;
621
622        subfeature = sensors_get_subfeature(name, feature,
623                                            SENSORS_SUBFEATURE_VID);
624        if (!subfeature)
625                return;
626
627        if ((label = sensors_get_label(name, feature))
628         && !sensors_get_value(name, subfeature->number, &vid)) {
629                print_label(label, label_size);
630                printf("%+6.3f V\n", vid);
631        }
632        free(label);
633}
634
635static void print_chip_beep_enable(const sensors_chip_name *name,
636                                   const sensors_feature *feature,
637                                   int label_size)
638{
639        char *label;
640        const sensors_subfeature *subfeature;
641        double beep_enable;
642
643        subfeature = sensors_get_subfeature(name, feature,
644                                            SENSORS_SUBFEATURE_BEEP_ENABLE);
645        if (!subfeature)
646                return;
647
648        if ((label = sensors_get_label(name, feature))
649         && !sensors_get_value(name, subfeature->number, &beep_enable)) {
650                print_label(label, label_size);
651                printf("%s\n", beep_enable ? "enabled" : "disabled");
652        }
653        free(label);
654}
655
656static const struct sensor_subfeature_list current_sensors[] = {
657        { SENSORS_SUBFEATURE_CURR_ALARM, NULL, 1, NULL },
658        { SENSORS_SUBFEATURE_CURR_LCRIT_ALARM, NULL, 1, "LCRIT" },
659        { SENSORS_SUBFEATURE_CURR_MIN_ALARM, NULL, 1, "MIN" },
660        { SENSORS_SUBFEATURE_CURR_MAX_ALARM, NULL, 1, "MAX" },
661        { SENSORS_SUBFEATURE_CURR_CRIT_ALARM, NULL, 1, "CRIT" },
662        { SENSORS_SUBFEATURE_CURR_LCRIT, NULL, 0, "crit min" },
663        { SENSORS_SUBFEATURE_CURR_MIN, NULL, 0, "min" },
664        { SENSORS_SUBFEATURE_CURR_MAX, NULL, 0, "max" },
665        { SENSORS_SUBFEATURE_CURR_CRIT, NULL, 0, "crit max" },
666        { SENSORS_SUBFEATURE_CURR_AVERAGE, NULL, 0, "avg" },
667        { SENSORS_SUBFEATURE_CURR_LOWEST, NULL, 0, "lowest" },
668        { SENSORS_SUBFEATURE_CURR_HIGHEST, NULL, 0, "highest" },
669        { -1, NULL, 0, NULL }
670};
671
672#define NUM_CURR_ALARMS         5
673#define NUM_CURR_SENSORS        (ARRAY_SIZE(current_sensors) - NUM_CURR_ALARMS - 1)
674
675static void print_chip_curr(const sensors_chip_name *name,
676                            const sensors_feature *feature,
677                            int label_size)
678{
679        const sensors_subfeature *sf;
680        double val;
681        char *label;
682        struct sensor_subfeature_data sensors[NUM_CURR_SENSORS];
683        struct sensor_subfeature_data alarms[NUM_CURR_ALARMS];
684        int sensor_count, alarm_count;
685
686        if (!(label = sensors_get_label(name, feature))) {
687                fprintf(stderr, "ERROR: Can't get label of feature %s!\n",
688                        feature->name);
689                return;
690        }
691        print_label(label, label_size);
692        free(label);
693
694        sf = sensors_get_subfeature(name, feature,
695                                    SENSORS_SUBFEATURE_CURR_INPUT);
696        if (sf && get_input_value(name, sf, &val) == 0)
697                printf("%+6.2f A  ", val);
698        else
699                printf("     N/A  ");
700
701        sensor_count = alarm_count = 0;
702        get_sensor_limit_data(name, feature, current_sensors,
703                              sensors, &sensor_count, alarms, &alarm_count);
704
705        print_limits(sensors, sensor_count, alarms, alarm_count, label_size,
706                     "%s = %+6.2f A");
707
708        printf("\n");
709}
710
711static void print_chip_intrusion(const sensors_chip_name *name,
712                                 const sensors_feature *feature,
713                                 int label_size)
714{
715        char *label;
716        const sensors_subfeature *subfeature;
717        double alarm;
718
719        subfeature = sensors_get_subfeature(name, feature,
720                                            SENSORS_SUBFEATURE_INTRUSION_ALARM);
721        if (!subfeature)
722                return;
723
724        if ((label = sensors_get_label(name, feature))
725         && !sensors_get_value(name, subfeature->number, &alarm)) {
726                print_label(label, label_size);
727                printf("%s\n", alarm ? "ALARM" : "OK");
728        }
729        free(label);
730}
731
732void print_chip(const sensors_chip_name *name)
733{
734        const sensors_feature *feature;
735        int i, label_size;
736
737        label_size = get_label_size(name);
738
739        i = 0;
740        while ((feature = sensors_get_features(name, &i))) {
741                switch (feature->type) {
742                case SENSORS_FEATURE_TEMP:
743                        print_chip_temp(name, feature, label_size);
744                        break;
745                case SENSORS_FEATURE_IN:
746                        print_chip_in(name, feature, label_size);
747                        break;
748                case SENSORS_FEATURE_FAN:
749                        print_chip_fan(name, feature, label_size);
750                        break;
751                case SENSORS_FEATURE_VID:
752                        print_chip_vid(name, feature, label_size);
753                        break;
754                case SENSORS_FEATURE_BEEP_ENABLE:
755                        print_chip_beep_enable(name, feature, label_size);
756                        break;
757                case SENSORS_FEATURE_POWER:
758                        print_chip_power(name, feature, label_size);
759                        break;
760                case SENSORS_FEATURE_ENERGY:
761                        print_chip_energy(name, feature, label_size);
762                        break;
763                case SENSORS_FEATURE_CURR:
764                        print_chip_curr(name, feature, label_size);
765                        break;
766                case SENSORS_FEATURE_INTRUSION:
767                        print_chip_intrusion(name, feature, label_size);
768                        break;
769                default:
770                        continue;
771                }
772        }
773}
Note: See TracBrowser for help on using the browser.