[BACK]Return to sensors.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/sensors.c, Revision 1.30

1.30    ! deraadt     1: /*     $OpenBSD: sensors.c,v 1.29 2014/10/08 04:10:04 doug Exp $       */
1.8       deanna      2:
1.1       deanna      3: /*
                      4:  * Copyright (c) 2007 Deanna Phillips <deanna@openbsd.org>
                      5:  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
1.4       deraadt     6:  * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
1.1       deanna      7:  *
                      8:  * Permission to use, copy, modify, and distribute this software for any
                      9:  * purpose with or without fee is hereby granted, provided that the above
                     10:  * copyright notice and this permission notice appear in all copies.
                     11:  *
                     12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     19:  *
                     20:  */
                     21:
1.30    ! deraadt    22: #include <sys/types.h>
        !            23: #include <sys/signal.h>
1.1       deanna     24: #include <sys/sysctl.h>
                     25: #include <sys/sensors.h>
                     26:
                     27: #include <err.h>
                     28: #include <errno.h>
                     29: #include <stdio.h>
                     30: #include <stdlib.h>
1.13      canacar    31: #include <string.h>
1.1       deanna     32: #include "systat.h"
                     33:
                     34: struct sensor sensor;
                     35: struct sensordev sensordev;
                     36:
1.13      canacar    37: struct sensinfo {
                     38:        int sn_dev;
                     39:        struct sensor sn_sensor;
                     40: };
                     41: #define sn_type sn_sensor.type
                     42: #define sn_numt sn_sensor.numt
                     43: #define sn_desc sn_sensor.desc
                     44: #define sn_status sn_sensor.status
                     45: #define sn_value sn_sensor.value
                     46:
1.21      deraadt    47: #define SYSTAT_MAXSENSORDEVICES 1024
                     48: char *devnames[SYSTAT_MAXSENSORDEVICES];
1.13      canacar    49:
                     50: #define ADD_ALLOC 100
                     51: static size_t sensor_cnt = 0;
                     52: static size_t num_alloc = 0;
                     53: static struct sensinfo *sensors = NULL;
                     54:
                     55: static char *fmttime(double);
                     56: static void showsensor(struct sensinfo *s);
                     57:
                     58: void print_sn(void);
                     59: int read_sn(void);
                     60: int select_sn(void);
                     61:
                     62: const char *drvstat[] = {
                     63:        NULL,
1.16      okan       64:        "empty", "ready", "powering up", "online", "idle", "active",
                     65:        "rebuilding", "powering down", "failed", "degraded"
1.13      canacar    66: };
                     67:
                     68:
                     69: field_def fields_sn[] = {
                     70:        {"SENSOR", 16, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
                     71:        {"VALUE", 16, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
                     72:        {"STATUS", 5, 8, 1, FLD_ALIGN_CENTER, -1, 0, 0, 0},
                     73:        {"DESCRIPTION", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}
                     74: };
                     75:
1.24      jasper     76: #define FLD_SN_SENSOR  FIELD_ADDR(fields_sn,0)
                     77: #define FLD_SN_VALUE   FIELD_ADDR(fields_sn,1)
                     78: #define FLD_SN_STATUS  FIELD_ADDR(fields_sn,2)
                     79: #define FLD_SN_DESCR   FIELD_ADDR(fields_sn,3)
1.13      canacar    80:
                     81: /* Define views */
                     82: field_def *view_sn_0[] = {
                     83:        FLD_SN_SENSOR, FLD_SN_VALUE, FLD_SN_STATUS, FLD_SN_DESCR, NULL
                     84: };
                     85:
                     86:
                     87: /* Define view managers */
                     88: struct view_manager sensors_mgr = {
                     89:        "Sensors", select_sn, read_sn, NULL, print_header,
                     90:        print_sn, keyboard_callback, NULL, NULL
                     91: };
                     92:
                     93: field_view views_sn[] = {
                     94:        {view_sn_0, "sensors", '3', &sensors_mgr},
                     95:        {NULL, NULL, 0, NULL}
                     96: };
                     97:
                     98: struct sensinfo *
                     99: next_sn(void)
1.1       deanna    100: {
1.13      canacar   101:        if (num_alloc <= sensor_cnt) {
                    102:                struct sensinfo *s;
                    103:                size_t a = num_alloc + ADD_ALLOC;
                    104:                if (a < num_alloc)
                    105:                        return NULL;
1.29      doug      106:                s = reallocarray(sensors, a, sizeof(struct sensinfo));
1.13      canacar   107:                if (s == NULL)
                    108:                        return NULL;
                    109:                sensors = s;
                    110:                num_alloc = a;
                    111:        }
                    112:
                    113:        return &sensors[sensor_cnt++];
1.1       deanna    114: }
                    115:
                    116:
1.13      canacar   117: int
                    118: select_sn(void)
1.1       deanna    119: {
1.13      canacar   120:        num_disp = sensor_cnt;
                    121:        return (0);
1.1       deanna    122: }
                    123:
1.13      canacar   124: int
                    125: read_sn(void)
1.1       deanna    126: {
                    127:        enum sensor_type type;
                    128:        size_t           slen, sdlen;
                    129:        int              mib[5], dev, numt;
1.13      canacar   130:        struct sensinfo *s;
1.1       deanna    131:
                    132:        mib[0] = CTL_HW;
                    133:        mib[1] = HW_SENSORS;
                    134:
                    135:        sensor_cnt = 0;
1.8       deanna    136:
1.21      deraadt   137:        for (dev = 0; dev < SYSTAT_MAXSENSORDEVICES; dev++) {
1.1       deanna    138:                mib[2] = dev;
1.13      canacar   139:                sdlen = sizeof(struct sensordev);
1.1       deanna    140:                if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
1.21      deraadt   141:                        if (errno == ENOENT)
                    142:                                break;
                    143:                        if (errno == ENXIO)
                    144:                                continue;
                    145:                        error("sysctl: %s", strerror(errno));
1.1       deanna    146:                }
1.13      canacar   147:
                    148:                if (devnames[dev] && strcmp(devnames[dev], sensordev.xname)) {
                    149:                        free(devnames[dev]);
                    150:                        devnames[dev] = NULL;
                    151:                }
                    152:                if (devnames[dev] == NULL)
                    153:                        devnames[dev] = strdup(sensordev.xname);
                    154:
1.1       deanna    155:                for (type = 0; type < SENSOR_MAX_TYPES; type++) {
                    156:                        mib[3] = type;
                    157:                        for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
                    158:                                mib[4] = numt;
1.13      canacar   159:                                slen = sizeof(struct sensor);
1.2       deraadt   160:                                if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
1.1       deanna    161:                                    == -1) {
                    162:                                        if (errno != ENOENT)
1.13      canacar   163:                                                error("sysctl: %s", strerror(errno));
1.1       deanna    164:                                        continue;
                    165:                                }
                    166:                                if (sensor.flags & SENSOR_FINVALID)
                    167:                                        continue;
1.13      canacar   168:
                    169:                                s = next_sn();
                    170:                                s->sn_sensor = sensor;
                    171:                                s->sn_dev = dev;
1.1       deanna    172:                        }
                    173:                }
                    174:        }
1.13      canacar   175:
                    176:        num_disp = sensor_cnt;
                    177:        return 0;
1.1       deanna    178: }
                    179:
                    180:
                    181: void
1.13      canacar   182: print_sn(void)
1.1       deanna    183: {
1.13      canacar   184:        int n, count = 0;
                    185:
                    186:        for (n = dispstart; n < num_disp; n++) {
                    187:                showsensor(sensors + n);
                    188:                count++;
                    189:                if (maxprint > 0 && count >= maxprint)
                    190:                        break;
                    191:        }
1.1       deanna    192: }
                    193:
                    194: int
                    195: initsensors(void)
                    196: {
1.13      canacar   197:        field_view *v;
                    198:
                    199:        memset(devnames, 0, sizeof(devnames));
                    200:
                    201:        for (v = views_sn; v->name != NULL; v++)
                    202:                add_view(v);
                    203:
                    204:        return(1);
1.1       deanna    205: }
                    206:
1.13      canacar   207: static void
                    208: showsensor(struct sensinfo *s)
1.1       deanna    209: {
1.13      canacar   210:        tb_start();
                    211:        tbprintf("%s.%s%d", devnames[s->sn_dev],
                    212:                 sensor_type_s[s->sn_type], s->sn_numt);
                    213:        print_fld_tb(FLD_SN_SENSOR);
                    214:
                    215:        if (s->sn_desc[0] != '\0')
                    216:                print_fld_str(FLD_SN_DESCR, s->sn_desc);
                    217:
                    218:        tb_start();
                    219:
                    220:        switch (s->sn_type) {
1.1       deanna    221:        case SENSOR_TEMP:
1.13      canacar   222:                tbprintf("%10.2f degC",
                    223:                    (s->sn_value - 273150000) / 1000000.0);
1.1       deanna    224:                break;
                    225:        case SENSOR_FANRPM:
1.13      canacar   226:                tbprintf("%11lld RPM", s->sn_value);
1.1       deanna    227:                break;
1.26      yuo       228:        case SENSOR_VOLTS_DC:
                    229:                tbprintf("%10.2f V DC",
                    230:                    s->sn_value / 1000000.0);
                    231:                break;
1.25      yuo       232:        case SENSOR_VOLTS_AC:
                    233:                tbprintf("%10.2f V AC",
                    234:                    s->sn_value / 1000000.0);
                    235:                break;
1.26      yuo       236:        case SENSOR_OHMS:
                    237:                tbprintf("%11lld ohm", s->sn_value);
1.18      cnst      238:                break;
                    239:        case SENSOR_WATTS:
                    240:                tbprintf("%10.2f W", s->sn_value / 1000000.0);
1.1       deanna    241:                break;
                    242:        case SENSOR_AMPS:
1.13      canacar   243:                tbprintf("%10.2f A", s->sn_value / 1000000.0);
1.1       deanna    244:                break;
1.26      yuo       245:        case SENSOR_WATTHOUR:
                    246:                tbprintf("%12.2f Wh", s->sn_value / 1000000.0);
                    247:                break;
                    248:        case SENSOR_AMPHOUR:
                    249:                tbprintf("%10.2f Ah", s->sn_value / 1000000.0);
                    250:                break;
1.1       deanna    251:        case SENSOR_INDICATOR:
1.13      canacar   252:                tbprintf("%15s", s->sn_value ? "On" : "Off");
1.1       deanna    253:                break;
                    254:        case SENSOR_INTEGER:
1.13      canacar   255:                tbprintf("%11lld raw", s->sn_value);
1.1       deanna    256:                break;
                    257:        case SENSOR_PERCENT:
1.13      canacar   258:                tbprintf("%14.2f%%", s->sn_value / 1000.0);
1.1       deanna    259:                break;
                    260:        case SENSOR_LUX:
1.13      canacar   261:                tbprintf("%15.2f lx", s->sn_value / 1000000.0);
1.1       deanna    262:                break;
                    263:        case SENSOR_DRIVE:
1.13      canacar   264:                if (0 < s->sn_value &&
1.17      deraadt   265:                    s->sn_value < sizeof(drvstat)/sizeof(drvstat[0])) {
1.13      canacar   266:                        tbprintf("%15s", drvstat[s->sn_value]);
1.1       deanna    267:                        break;
                    268:                }
1.3       deraadt   269:                break;
1.1       deanna    270:        case SENSOR_TIMEDELTA:
1.13      canacar   271:                tbprintf("%15s", fmttime(s->sn_value / 1000000000.0));
1.19      yuo       272:                break;
                    273:        case SENSOR_HUMIDITY:
                    274:                tbprintf("%3.2f%%", s->sn_value / 1000.0);
1.20      oga       275:                break;
                    276:        case SENSOR_FREQ:
1.25      yuo       277:                tbprintf("%11.2f Hz", s->sn_value / 1000000.0);
1.22      deraadt   278:                break;
                    279:        case SENSOR_ANGLE:
1.23      deraadt   280:                tbprintf("%3.4f degrees", s->sn_value / 1000000.0);
1.27      yuo       281:                break;
                    282:        case SENSOR_DISTANCE:
1.28      jasper    283:                tbprintf("%.2f mm", s->sn_value / 1000.0);
1.27      yuo       284:                break;
                    285:        case SENSOR_PRESSURE:
1.28      jasper    286:                tbprintf("%.2f Pa", s->sn_value / 1000.0);
1.27      yuo       287:                break;
                    288:        case SENSOR_ACCEL:
1.28      jasper    289:                tbprintf("%2.4f m/s^2", s->sn_value / 1000000.0);
1.1       deanna    290:                break;
                    291:        default:
1.13      canacar   292:                tbprintf("%10lld", s->sn_value);
1.3       deraadt   293:                break;
1.1       deanna    294:        }
1.2       deraadt   295:
1.13      canacar   296:        print_fld_tb(FLD_SN_VALUE);
                    297:
                    298:        switch (s->sn_status) {
1.8       deanna    299:        case SENSOR_S_UNSPEC:
                    300:                break;
1.1       deanna    301:        case SENSOR_S_UNKNOWN:
1.13      canacar   302:                print_fld_str(FLD_SN_STATUS, "unknown");
1.1       deanna    303:                break;
                    304:        case SENSOR_S_WARN:
1.13      canacar   305:                print_fld_str(FLD_SN_STATUS, "WARNING");
1.1       deanna    306:                break;
                    307:        case SENSOR_S_CRIT:
1.13      canacar   308:                print_fld_str(FLD_SN_STATUS, "CRITICAL");
1.1       deanna    309:                break;
1.3       deraadt   310:        case SENSOR_S_OK:
1.13      canacar   311:                print_fld_str(FLD_SN_STATUS, "OK");
1.1       deanna    312:                break;
                    313:        }
1.13      canacar   314:        end_line();
1.9       ckuethe   315: }
                    316:
                    317: #define SECS_PER_DAY 86400
                    318: #define SECS_PER_HOUR 3600
                    319: #define SECS_PER_MIN 60
                    320:
                    321: static char *
                    322: fmttime(double in)
                    323: {
                    324:        int signbit = 1;
                    325:        int tiny = 0;
                    326:        char *unit;
                    327: #define LEN 32
                    328:        static char outbuf[LEN];
                    329:
                    330:        if (in < 0){
                    331:                signbit = -1;
                    332:                in *= -1;
                    333:        }
                    334:
                    335:        if (in >= SECS_PER_DAY ){
                    336:                unit = "days";
                    337:                in /= SECS_PER_DAY;
                    338:        } else if (in >= SECS_PER_HOUR ){
                    339:                unit = "hr";
                    340:                in /= SECS_PER_HOUR;
                    341:        } else if (in >= SECS_PER_MIN ){
                    342:                unit = "min";
                    343:                in /= SECS_PER_MIN;
                    344:        } else if (in >= 1 ){
1.11      ckuethe   345:                unit = "s";
1.9       ckuethe   346:                /* in *= 1; */ /* no op */
1.10      ckuethe   347:        } else if (in == 0 ){ /* direct comparisons to floats are scary */
1.11      ckuethe   348:                unit = "s";
1.9       ckuethe   349:        } else if (in >= 1e-3 ){
1.11      ckuethe   350:                unit = "ms";
1.9       ckuethe   351:                in *= 1e3;
                    352:        } else if (in >= 1e-6 ){
1.11      ckuethe   353:                unit = "us";
1.9       ckuethe   354:                in *= 1e6;
                    355:        } else if (in >= 1e-9 ){
1.11      ckuethe   356:                unit = "ns";
1.9       ckuethe   357:                in *= 1e9;
                    358:        } else {
1.11      ckuethe   359:                unit = "ps";
1.9       ckuethe   360:                if (in < 1e-13)
                    361:                        tiny = 1;
                    362:                in *= 1e12;
                    363:        }
                    364:
                    365:        snprintf(outbuf, LEN,
1.14      canacar   366:            tiny ? "%s%f %s" : "%s%.3f %s",
1.9       ckuethe   367:            signbit == -1 ? "-" : "", in, unit);
                    368:
                    369:        return outbuf;
1.1       deanna    370: }