xref: /dragonfly/usr.bin/systat/sensors.c (revision f746689a)
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.2 2008/11/10 04:59:45 swildner 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 		    (size_t)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 	const 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