1 /* $OpenBSD: sensors.c,v 1.11 2007/03/23 14:48:22 ckuethe Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Deanna Phillips <deanna@openbsd.org> 5 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 6 * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> 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 #include <sys/param.h> 22 #include <sys/sysctl.h> 23 #include <sys/sensors.h> 24 25 #include <err.h> 26 #include <errno.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 30 #include "systat.h" 31 #include "extern.h" 32 33 struct sensor sensor; 34 struct sensordev sensordev; 35 int row, sensor_cnt; 36 void printline(void); 37 static char * fmttime(double); 38 39 WINDOW * 40 opensensors(void) 41 { 42 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 43 } 44 45 void 46 closesensors(WINDOW *w) 47 { 48 if (w == NULL) 49 return; 50 wclear(w); 51 wrefresh(w); 52 delwin(w); 53 } 54 55 void 56 labelsensors(void) 57 { 58 wmove(wnd, 0, 0); 59 wclrtobot(wnd); 60 mvwaddstr(wnd, 0, 0, "Sensor"); 61 mvwaddstr(wnd, 0, 34, "Value"); 62 mvwaddstr(wnd, 0, 45, "Status"); 63 mvwaddstr(wnd, 0, 58, "Description"); 64 } 65 66 void 67 fetchsensors(void) 68 { 69 enum sensor_type type; 70 size_t slen, sdlen; 71 int mib[5], dev, numt; 72 73 mib[0] = CTL_HW; 74 mib[1] = HW_SENSORS; 75 slen = sizeof(struct sensor); 76 sdlen = sizeof(struct sensordev); 77 78 row = 1; 79 sensor_cnt = 0; 80 81 wmove(wnd, row, 0); 82 wclrtobot(wnd); 83 84 for (dev = 0; dev < MAXSENSORDEVICES; dev++) { 85 mib[2] = dev; 86 if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) { 87 if (errno != ENOENT) 88 warn("sysctl"); 89 continue; 90 } 91 for (type = 0; type < SENSOR_MAX_TYPES; type++) { 92 mib[3] = type; 93 for (numt = 0; numt < sensordev.maxnumt[type]; numt++) { 94 mib[4] = numt; 95 if (sysctl(mib, 5, &sensor, &slen, NULL, 0) 96 == -1) { 97 if (errno != ENOENT) 98 warn("sysctl"); 99 continue; 100 } 101 if (sensor.flags & SENSOR_FINVALID) 102 continue; 103 sensor_cnt++; 104 printline(); 105 } 106 } 107 } 108 } 109 110 const char *drvstat[] = { 111 NULL, 112 "empty", "ready", "powerup", "online", "idle", "active", 113 "rebuild", "powerdown", "fail", "pfail" 114 }; 115 116 void 117 showsensors(void) 118 { 119 if (sensor_cnt == 0) 120 mvwaddstr(wnd, row, 0, "No sensors found."); 121 } 122 123 int 124 initsensors(void) 125 { 126 return (1); 127 } 128 129 void 130 printline(void) 131 { 132 mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname, 133 sensor_type_s[sensor.type], sensor.numt); 134 switch (sensor.type) { 135 case SENSOR_TEMP: 136 mvwprintw(wnd, row, 24, "%10.2f degC", 137 (sensor.value - 273150000) / 1000000.0); 138 break; 139 case SENSOR_FANRPM: 140 mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value); 141 break; 142 case SENSOR_VOLTS_DC: 143 mvwprintw(wnd, row, 24, "%10.2f V DC", 144 sensor.value / 1000000.0); 145 break; 146 case SENSOR_AMPS: 147 mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0); 148 break; 149 case SENSOR_INDICATOR: 150 mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off"); 151 break; 152 case SENSOR_INTEGER: 153 mvwprintw(wnd, row, 24, "%11lld raw", sensor.value); 154 break; 155 case SENSOR_PERCENT: 156 mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0); 157 break; 158 case SENSOR_LUX: 159 mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0); 160 break; 161 case SENSOR_DRIVE: 162 if (0 < sensor.value && 163 (size_t)sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) { 164 mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]); 165 break; 166 } 167 break; 168 case SENSOR_TIMEDELTA: 169 mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0)); 170 break; 171 case SENSOR_WATTHOUR: 172 mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0); 173 break; 174 case SENSOR_AMPHOUR: 175 mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0); 176 break; 177 default: 178 mvwprintw(wnd, row, 24, "%10lld", sensor.value); 179 break; 180 } 181 if (sensor.desc[0] != '\0') 182 mvwprintw(wnd, row, 58, "(%s)", sensor.desc); 183 184 switch (sensor.status) { 185 case SENSOR_S_UNSPEC: 186 break; 187 case SENSOR_S_UNKNOWN: 188 mvwaddstr(wnd, row, 45, "unknown"); 189 break; 190 case SENSOR_S_WARN: 191 mvwaddstr(wnd, row, 45, "WARNING"); 192 break; 193 case SENSOR_S_CRIT: 194 mvwaddstr(wnd, row, 45, "CRITICAL"); 195 break; 196 case SENSOR_S_OK: 197 mvwaddstr(wnd, row, 45, "OK"); 198 break; 199 } 200 row++; 201 } 202 203 #define SECS_PER_DAY 86400 204 #define SECS_PER_HOUR 3600 205 #define SECS_PER_MIN 60 206 207 static char * 208 fmttime(double in) 209 { 210 int signbit = 1; 211 int tiny = 0; 212 const char *unit; 213 #define LEN 32 214 static char outbuf[LEN]; 215 216 if (in < 0){ 217 signbit = -1; 218 in *= -1; 219 } 220 221 if (in >= SECS_PER_DAY ){ 222 unit = "days"; 223 in /= SECS_PER_DAY; 224 } else if (in >= SECS_PER_HOUR ){ 225 unit = "hr"; 226 in /= SECS_PER_HOUR; 227 } else if (in >= SECS_PER_MIN ){ 228 unit = "min"; 229 in /= SECS_PER_MIN; 230 } else if (in >= 1 ){ 231 unit = "s"; 232 /* in *= 1; */ /* no op */ 233 } else if (in == 0 ){ /* direct comparisons to floats are scary */ 234 unit = "s"; 235 } else if (in >= 1e-3 ){ 236 unit = "ms"; 237 in *= 1e3; 238 } else if (in >= 1e-6 ){ 239 unit = "us"; 240 in *= 1e6; 241 } else if (in >= 1e-9 ){ 242 unit = "ns"; 243 in *= 1e9; 244 } else { 245 unit = "ps"; 246 if (in < 1e-13) 247 tiny = 1; 248 in *= 1e12; 249 } 250 251 snprintf(outbuf, LEN, 252 tiny ? "%s%lf %s" : "%s%.3lf %s", 253 signbit == -1 ? "-" : "", in, unit); 254 255 return outbuf; 256 } 257