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