hammer2 - per-node sync threads
[dragonfly.git] / usr.bin / systat / sensors.c
blob2fef4f62802744483f9894ce1701db93ea2ab214
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 <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "systat.h"
33 #include "extern.h"
35 struct sensor sensor;
36 struct sensordev sensordev;
37 int row, sensor_cnt;
38 void printline(void);
39 static char * fmttime(double);
41 struct sensordev_xname {
42 char xname[24];
43 int xname_len;
44 u_int flags; /* XNAME_FLAG_ */
47 #define XNAME_FLAG_WILDCARD 0x1
49 static int sensors_enabled[SENSOR_MAX_TYPES];
51 #define XNAME_MAX 64
53 static int sensordev_xname_cnt;
54 static struct sensordev_xname sensordev_xname[XNAME_MAX];
56 WINDOW *
57 opensensors(void)
59 return (subwin(stdscr, LINES-5-1, 0, 5, 0));
62 void
63 closesensors(WINDOW *w)
65 if (w == NULL)
66 return;
67 wclear(w);
68 wrefresh(w);
69 delwin(w);
72 void
73 labelsensors(void)
75 wmove(wnd, 0, 0);
76 wclrtobot(wnd);
77 mvwaddstr(wnd, 0, 0, "Sensor");
78 mvwaddstr(wnd, 0, 34, "Value");
79 mvwaddstr(wnd, 0, 45, "Status");
80 mvwaddstr(wnd, 0, 58, "Description");
83 void
84 fetchsensors(void)
86 enum sensor_type type;
87 size_t slen, sdlen, idmax_len;
88 int mib[5], dev, numt, idmax;
89 int maxsensordevices;
91 maxsensordevices = MAXSENSORDEVICES;
92 idmax_len = sizeof(idmax);
93 if (sysctlbyname("hw.sensors.dev_idmax", &idmax, &idmax_len,
94 NULL, 0) == 0)
95 maxsensordevices = idmax;
97 mib[0] = CTL_HW;
98 mib[1] = HW_SENSORS;
99 slen = sizeof(struct sensor);
100 sdlen = sizeof(struct sensordev);
102 row = 1;
103 sensor_cnt = 0;
105 wmove(wnd, row, 0);
106 wclrtobot(wnd);
108 for (dev = 0; dev < maxsensordevices; dev++) {
109 mib[2] = dev;
110 if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
111 if (errno != ENOENT)
112 warn("sysctl");
113 continue;
116 if (sensordev_xname_cnt > 0) {
117 int i, match = 0, xname_len;
119 xname_len = strlen(sensordev.xname);
120 for (i = 0; i < sensordev_xname_cnt; ++i) {
121 const struct sensordev_xname *x;
123 x = &sensordev_xname[i];
124 if (x->flags & XNAME_FLAG_WILDCARD) {
125 if (xname_len <= x->xname_len)
126 continue;
127 if (!isdigit(
128 sensordev.xname[x->xname_len]))
129 continue;
130 if (strncmp(x->xname, sensordev.xname,
131 x->xname_len) == 0) {
132 match = 1;
133 break;
135 } else if (xname_len == x->xname_len &&
136 strcmp(x->xname, sensordev.xname) == 0) {
137 match = 1;
138 break;
141 if (!match)
142 continue;
145 for (type = 0; type < SENSOR_MAX_TYPES; type++) {
146 if (!sensors_enabled[type])
147 continue;
149 mib[3] = type;
150 for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
151 mib[4] = numt;
152 if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
153 == -1) {
154 if (errno != ENOENT)
155 warn("sysctl");
156 continue;
158 if (sensor.flags & SENSOR_FINVALID)
159 continue;
160 sensor_cnt++;
161 printline();
167 const char *drvstat[] = {
168 NULL,
169 "empty", "ready", "powerup", "online", "idle", "active",
170 "rebuild", "powerdown", "fail", "pfail"
173 void
174 showsensors(void)
176 if (sensor_cnt == 0)
177 mvwaddstr(wnd, row, 0, "No sensors found.");
181 initsensors(void)
183 int i;
185 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
186 sensors_enabled[i] = 1;
187 return (1);
190 void
191 printline(void)
193 mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname,
194 sensor_type_s[sensor.type], sensor.numt);
195 switch (sensor.type) {
196 case SENSOR_TEMP:
197 mvwprintw(wnd, row, 24, "%10.2f degC",
198 (sensor.value - 273150000) / 1000000.0);
199 break;
200 case SENSOR_FANRPM:
201 mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value);
202 break;
203 case SENSOR_VOLTS_DC:
204 mvwprintw(wnd, row, 24, "%10.2f V DC",
205 sensor.value / 1000000.0);
206 break;
207 case SENSOR_AMPS:
208 mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0);
209 break;
210 case SENSOR_INDICATOR:
211 mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off");
212 break;
213 case SENSOR_INTEGER:
214 mvwprintw(wnd, row, 24, "%11lld raw", sensor.value);
215 break;
216 case SENSOR_PERCENT:
217 mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0);
218 break;
219 case SENSOR_LUX:
220 mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0);
221 break;
222 case SENSOR_DRIVE:
223 if (0 < sensor.value &&
224 (size_t)sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) {
225 mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]);
226 break;
228 break;
229 case SENSOR_TIMEDELTA:
230 mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0));
231 break;
232 case SENSOR_WATTHOUR:
233 mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0);
234 break;
235 case SENSOR_AMPHOUR:
236 mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0);
237 break;
238 default:
239 mvwprintw(wnd, row, 24, "%10lld", sensor.value);
240 break;
242 if (sensor.desc[0] != '\0')
243 mvwprintw(wnd, row, 58, "(%s)", sensor.desc);
245 switch (sensor.status) {
246 case SENSOR_S_UNSPEC:
247 break;
248 case SENSOR_S_UNKNOWN:
249 mvwaddstr(wnd, row, 45, "unknown");
250 break;
251 case SENSOR_S_WARN:
252 mvwaddstr(wnd, row, 45, "WARNING");
253 break;
254 case SENSOR_S_CRIT:
255 mvwaddstr(wnd, row, 45, "CRITICAL");
256 break;
257 case SENSOR_S_OK:
258 mvwaddstr(wnd, row, 45, "OK");
259 break;
261 row++;
264 #define SECS_PER_DAY 86400
265 #define SECS_PER_HOUR 3600
266 #define SECS_PER_MIN 60
268 static char *
269 fmttime(double in)
271 int signbit = 1;
272 int tiny = 0;
273 const char *unit;
274 #define LEN 32
275 static char outbuf[LEN];
277 if (in < 0){
278 signbit = -1;
279 in *= -1;
282 if (in >= SECS_PER_DAY ){
283 unit = "days";
284 in /= SECS_PER_DAY;
285 } else if (in >= SECS_PER_HOUR ){
286 unit = "hr";
287 in /= SECS_PER_HOUR;
288 } else if (in >= SECS_PER_MIN ){
289 unit = "min";
290 in /= SECS_PER_MIN;
291 } else if (in >= 1 ){
292 unit = "s";
293 /* in *= 1; */ /* no op */
294 } else if (in == 0 ){ /* direct comparisons to floats are scary */
295 unit = "s";
296 } else if (in >= 1e-3 ){
297 unit = "ms";
298 in *= 1e3;
299 } else if (in >= 1e-6 ){
300 unit = "us";
301 in *= 1e6;
302 } else if (in >= 1e-9 ){
303 unit = "ns";
304 in *= 1e9;
305 } else {
306 unit = "ps";
307 if (in < 1e-13)
308 tiny = 1;
309 in *= 1e12;
312 snprintf(outbuf, LEN,
313 tiny ? "%s%lf %s" : "%s%.3lf %s",
314 signbit == -1 ? "-" : "", in, unit);
316 return outbuf;
320 cmdsensors(const char *cmd, char *args)
322 if (prefix(cmd, "type")) {
323 const char *t;
324 int i, has_type = 0;
326 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
327 sensors_enabled[i] = 0;
329 while ((t = strsep(&args, " ")) != NULL) {
330 if (*t == '\0')
331 continue;
333 has_type = 1;
334 for (i = 0; i < SENSOR_MAX_TYPES; ++i) {
335 if (strcmp(t, sensor_type_s[i]) == 0) {
336 sensors_enabled[i] = 1;
337 break;
342 if (!has_type) {
343 for (i = 0; i < SENSOR_MAX_TYPES; ++i)
344 sensors_enabled[i] = 1;
346 } else if (prefix(cmd, "match")) {
347 const char *xname;
349 sensordev_xname_cnt = 0;
350 while ((xname = strsep(&args, " ")) != NULL) {
351 struct sensordev_xname *x;
352 int xname_len, cp_len;
354 xname_len = strlen(xname);
355 if (xname_len == 0)
356 continue;
358 x = &sensordev_xname[sensordev_xname_cnt];
359 x->flags = 0;
361 if (xname[xname_len - 1] == '*') {
362 --xname_len;
363 if (xname_len == 0)
364 continue;
365 x->flags |= XNAME_FLAG_WILDCARD;
367 cp_len = xname_len;
368 if (cp_len >= (int)sizeof(x->xname))
369 cp_len = sizeof(x->xname) - 1;
371 memcpy(x->xname, xname, cp_len);
372 x->xname[cp_len] = '\0';
373 x->xname_len = strlen(x->xname);
375 sensordev_xname_cnt++;
376 if (sensordev_xname_cnt == XNAME_MAX)
377 break;
381 wclear(wnd);
382 labelsensors();
383 refresh();
384 return (1);