toeplitz: Add comment.
[dragonfly.git] / usr.bin / systat / sensors.c
blob6f5e5031e8cf4f667b3f571552b3999fdc4123b2
1 /* $OpenBSD: sensors.c,v 1.11 2007/03/23 14:48:22 ckuethe Exp $ */
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>
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.
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.
21 #include <sys/param.h>
22 #include <sys/sysctl.h>
23 #include <sys/sensors.h>
25 #include <ctype.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <libutil.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
33 #include "systat.h"
34 #include "extern.h"
36 struct sensor sensor;
37 struct sensordev sensordev;
38 int row, sensor_cnt;
39 void printline(void);
40 static char * fmttime(double);
42 struct sensordev_xname {
43 char xname[24];
44 int xname_len;
45 u_int flags; /* XNAME_FLAG_ */
48 #define XNAME_FLAG_WILDCARD 0x1
50 static int sensors_enabled[SENSOR_MAX_TYPES];
52 #define XNAME_MAX 64
54 static int sensordev_xname_cnt;
55 static struct sensordev_xname sensordev_xname[XNAME_MAX];
57 WINDOW *
58 opensensors(void)
60 return (subwin(stdscr, LINES-5-1, 0, 5, 0));
63 void
64 closesensors(WINDOW *w)
66 if (w == NULL)
67 return;
68 wclear(w);
69 wrefresh(w);
70 delwin(w);
73 void
74 labelsensors(void)
76 wmove(wnd, 0, 0);
77 wclrtobot(wnd);
78 mvwaddstr(wnd, 0, 0, "Sensor");
79 mvwaddstr(wnd, 0, 34, "Value");
80 mvwaddstr(wnd, 0, 45, "Status");
81 mvwaddstr(wnd, 0, 58, "Description");
84 void
85 fetchsensors(void)
87 enum sensor_type type;
88 size_t slen, sdlen, idmax_len;
89 int mib[5], dev, numt, idmax;
90 int maxsensordevices;
92 maxsensordevices = MAXSENSORDEVICES;
93 idmax_len = sizeof(idmax);
94 if (sysctlbyname("hw.sensors.dev_idmax", &idmax, &idmax_len,
95 NULL, 0) == 0)
96 maxsensordevices = idmax;
98 mib[0] = CTL_HW;
99 mib[1] = HW_SENSORS;
100 slen = sizeof(struct sensor);
101 sdlen = sizeof(struct sensordev);
103 row = 1;
104 sensor_cnt = 0;
106 wmove(wnd, row, 0);
107 wclrtobot(wnd);
109 for (dev = 0; dev < maxsensordevices; dev++) {
110 mib[2] = dev;
111 if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
112 if (errno != ENOENT)
113 warn("sysctl");
114 continue;
117 if (sensordev_xname_cnt > 0) {
118 int i, match = 0, xname_len;
120 xname_len = strlen(sensordev.xname);
121 for (i = 0; i < sensordev_xname_cnt; ++i) {
122 const struct sensordev_xname *x;
124 x = &sensordev_xname[i];
125 if (x->flags & XNAME_FLAG_WILDCARD) {
126 if (xname_len <= x->xname_len)
127 continue;
128 if (!isdigit(
129 sensordev.xname[x->xname_len]))
130 continue;
131 if (strncmp(x->xname, sensordev.xname,
132 x->xname_len) == 0) {
133 match = 1;
134 break;
136 } else if (xname_len == x->xname_len &&
137 strcmp(x->xname, sensordev.xname) == 0) {
138 match = 1;
139 break;
142 if (!match)
143 continue;
146 for (type = 0; type < SENSOR_MAX_TYPES; type++) {
147 if (!sensors_enabled[type])
148 continue;
150 mib[3] = type;
151 for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
152 mib[4] = numt;
153 if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
154 == -1) {
155 if (errno != ENOENT)
156 warn("sysctl");
157 continue;
159 if (sensor.flags & SENSOR_FINVALID)
160 continue;
161 sensor_cnt++;
162 printline();
168 const char *drvstat[] = {
169 NULL,
170 "empty", "ready", "powerup", "online", "idle", "active",
171 "rebuild", "powerdown", "fail", "pfail"
174 void
175 showsensors(void)
177 if (sensor_cnt == 0)
178 mvwaddstr(wnd, row, 0, "No sensors found.");
182 initsensors(void)
184 int i;
186 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
187 sensors_enabled[i] = 1;
188 return (1);
191 void
192 printline(void)
194 char buf[9];
196 mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname,
197 sensor_type_s[sensor.type], sensor.numt);
198 switch (sensor.type) {
199 case SENSOR_TEMP:
200 mvwprintw(wnd, row, 24, "%10.2f degC",
201 (sensor.value - 273150000) / 1000000.0);
202 break;
203 case SENSOR_FANRPM:
204 mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value);
205 break;
206 case SENSOR_VOLTS_DC:
207 mvwprintw(wnd, row, 24, "%10.2f V DC",
208 sensor.value / 1000000.0);
209 break;
210 case SENSOR_WATTS:
211 mvwprintw(wnd, row, 24, "%13.2f W", sensor.value / 1000000.0);
212 break;
213 case SENSOR_AMPS:
214 mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0);
215 break;
216 case SENSOR_INDICATOR:
217 mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off");
218 break;
219 case SENSOR_INTEGER:
220 mvwprintw(wnd, row, 24, "%11lld raw", sensor.value);
221 break;
222 case SENSOR_PERCENT:
223 mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0);
224 break;
225 case SENSOR_LUX:
226 mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0);
227 break;
228 case SENSOR_DRIVE:
229 if (0 < sensor.value &&
230 (size_t)sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) {
231 mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]);
232 break;
234 break;
235 case SENSOR_TIMEDELTA:
236 mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0));
237 break;
238 case SENSOR_WATTHOUR:
239 mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0);
240 break;
241 case SENSOR_AMPHOUR:
242 mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0);
243 break;
244 case SENSOR_FREQ:
245 humanize_number(buf, sizeof(buf), sensor.value, "Hz",
246 HN_AUTOSCALE, HN_DIVISOR_1000 | HN_DECIMAL);
247 mvwprintw(wnd, row, 24, "%15s", buf);
248 break;
249 default:
250 mvwprintw(wnd, row, 24, "%10lld", sensor.value);
251 break;
253 if (sensor.desc[0] != '\0')
254 mvwprintw(wnd, row, 58, "(%s)", sensor.desc);
256 switch (sensor.status) {
257 case SENSOR_S_UNSPEC:
258 break;
259 case SENSOR_S_UNKNOWN:
260 mvwaddstr(wnd, row, 45, "unknown");
261 break;
262 case SENSOR_S_WARN:
263 mvwaddstr(wnd, row, 45, "WARNING");
264 break;
265 case SENSOR_S_CRIT:
266 mvwaddstr(wnd, row, 45, "CRITICAL");
267 break;
268 case SENSOR_S_OK:
269 mvwaddstr(wnd, row, 45, "OK");
270 break;
272 row++;
275 #define SECS_PER_DAY 86400
276 #define SECS_PER_HOUR 3600
277 #define SECS_PER_MIN 60
279 static char *
280 fmttime(double in)
282 int signbit = 1;
283 int tiny = 0;
284 const char *unit;
285 #define LEN 32
286 static char outbuf[LEN];
288 if (in < 0){
289 signbit = -1;
290 in *= -1;
293 if (in >= SECS_PER_DAY ){
294 unit = "days";
295 in /= SECS_PER_DAY;
296 } else if (in >= SECS_PER_HOUR ){
297 unit = "hr";
298 in /= SECS_PER_HOUR;
299 } else if (in >= SECS_PER_MIN ){
300 unit = "min";
301 in /= SECS_PER_MIN;
302 } else if (in >= 1 ){
303 unit = "s";
304 /* in *= 1; */ /* no op */
305 } else if (in == 0 ){ /* direct comparisons to floats are scary */
306 unit = "s";
307 } else if (in >= 1e-3 ){
308 unit = "ms";
309 in *= 1e3;
310 } else if (in >= 1e-6 ){
311 unit = "us";
312 in *= 1e6;
313 } else if (in >= 1e-9 ){
314 unit = "ns";
315 in *= 1e9;
316 } else {
317 unit = "ps";
318 if (in < 1e-13)
319 tiny = 1;
320 in *= 1e12;
323 snprintf(outbuf, LEN,
324 tiny ? "%s%lf %s" : "%s%.3lf %s",
325 signbit == -1 ? "-" : "", in, unit);
327 return outbuf;
331 cmdsensors(const char *cmd, char *args)
333 if (prefix(cmd, "type")) {
334 const char *t;
335 int i, has_type = 0;
337 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
338 sensors_enabled[i] = 0;
340 while ((t = strsep(&args, " ")) != NULL) {
341 if (*t == '\0')
342 continue;
344 has_type = 1;
345 for (i = 0; i < SENSOR_MAX_TYPES; ++i) {
346 if (strcmp(t, sensor_type_s[i]) == 0) {
347 sensors_enabled[i] = 1;
348 break;
353 if (!has_type) {
354 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
355 sensors_enabled[i] = 1;
357 } else if (prefix(cmd, "match")) {
358 const char *xname;
360 sensordev_xname_cnt = 0;
361 while ((xname = strsep(&args, " ")) != NULL) {
362 struct sensordev_xname *x;
363 int xname_len, cp_len;
365 xname_len = strlen(xname);
366 if (xname_len == 0)
367 continue;
369 x = &sensordev_xname[sensordev_xname_cnt];
370 x->flags = 0;
372 if (xname[xname_len - 1] == '*') {
373 --xname_len;
374 if (xname_len == 0)
375 continue;
376 x->flags |= XNAME_FLAG_WILDCARD;
378 cp_len = xname_len;
379 if (cp_len >= (int)sizeof(x->xname))
380 cp_len = sizeof(x->xname) - 1;
382 memcpy(x->xname, xname, cp_len);
383 x->xname[cp_len] = '\0';
384 x->xname_len = strlen(x->xname);
386 sensordev_xname_cnt++;
387 if (sensordev_xname_cnt == XNAME_MAX)
388 break;
392 wclear(wnd);
393 labelsensors();
394 refresh();
395 return (1);