xref: /dragonfly/usr.bin/systat/sensors.c (revision 19380330)
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