]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/systat/sensors.c
Import OpenBSD's sysctl hardware sensors framework.
[FreeBSD/FreeBSD.git] / usr.bin / systat / sensors.c
1 /*      $FreeBSD$       */
2 /*      $OpenBSD: sensors.c,v 1.12 2007/07/29 04:51:59 cnst 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
23 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
25
26 #include <sys/param.h>
27 #include <sys/sysctl.h>
28 #include <sys/sensors.h>
29
30 #include <err.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "systat.h"
36 #include "extern.h"
37
38 struct sensor sensor;
39 struct sensordev sensordev;
40 int row, sensor_cnt;
41 void printline(void);
42 static char * fmttime(double);
43
44 WINDOW *
45 opensensors(void)
46 {
47         return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
48 }
49
50 void
51 closesensors(WINDOW *w)
52 {
53         if (w == NULL)
54                 return;
55         wclear(w);
56         wrefresh(w);
57         delwin(w);
58 }
59
60 void
61 labelsensors(void)
62 {
63         wmove(wnd, 0, 0);
64         wclrtobot(wnd);
65         mvwaddstr(wnd, 0, 0, "Sensor");
66         mvwaddstr(wnd, 0, 34, "Value");
67         mvwaddstr(wnd, 0, 45, "Status");
68         mvwaddstr(wnd, 0, 58, "Description");
69 }
70
71 void
72 fetchsensors(void)
73 {
74         enum sensor_type type;
75         size_t           slen, sdlen;
76         int              mib[5], dev, numt;
77
78         mib[0] = CTL_HW;
79         mib[1] = HW_SENSORS;
80         slen = sizeof(struct sensor);
81         sdlen = sizeof(struct sensordev);
82
83         row = 1;
84         sensor_cnt = 0;
85
86         wmove(wnd, row, 0);
87         wclrtobot(wnd);
88
89         for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
90                 mib[2] = dev;
91                 if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
92                         if (errno != ENOENT)
93                                 warn("sysctl");
94                         continue;
95                 }
96                 for (type = 0; type < SENSOR_MAX_TYPES; type++) {
97                         mib[3] = type;
98                         for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
99                                 mib[4] = numt;
100                                 if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
101                                     == -1) {
102                                         if (errno != ENOENT)
103                                                 warn("sysctl");
104                                         continue;
105                                 }
106                                 if (sensor.flags & SENSOR_FINVALID)
107                                         continue;
108                                 sensor_cnt++;
109                                 printline();
110                         }
111                 }
112         }
113 }
114
115 const char *drvstat[] = {
116         NULL,
117         "empty", "ready", "powerup", "online", "idle", "active",
118         "rebuild", "powerdown", "fail", "pfail"
119 };
120
121 void
122 showsensors(void)
123 {
124         if (sensor_cnt == 0)
125                 mvwaddstr(wnd, row, 0, "No sensors found.");
126 }
127
128 int
129 initsensors(void)
130 {
131         return (1);
132 }
133
134 void
135 printline(void)
136 {
137         mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname,
138             sensor_type_s[sensor.type], sensor.numt);
139         switch (sensor.type) {
140         case SENSOR_TEMP:
141                 mvwprintw(wnd, row, 24, "%10.2f degC",
142                     (sensor.value - 273150000) / 1000000.0);
143                 break;
144         case SENSOR_FANRPM:
145                 mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value);
146                 break;
147         case SENSOR_VOLTS_DC:
148                 mvwprintw(wnd, row, 24, "%10.2f V DC",
149                     sensor.value / 1000000.0);
150                 break;
151         case SENSOR_AMPS:
152                 mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0);
153                 break;
154         case SENSOR_INDICATOR:
155                 mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off");
156                 break;
157         case SENSOR_INTEGER:
158                 mvwprintw(wnd, row, 24, "%11lld raw", sensor.value);
159                 break;
160         case SENSOR_PERCENT:
161                 mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0);
162                 break;
163         case SENSOR_LUX:
164                 mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0);
165                 break;
166         case SENSOR_DRIVE:
167                 if (0 < sensor.value &&
168                     sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) {
169                         mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]);
170                         break;
171                 }
172                 break;
173         case SENSOR_TIMEDELTA:
174                 mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0));
175                 break;
176         case SENSOR_WATTHOUR:
177                 mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0);
178                 break;
179         case SENSOR_AMPHOUR:
180                 mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0);
181                 break;
182         default:
183                 mvwprintw(wnd, row, 24, "%10lld", sensor.value);
184                 break;
185         }
186         if (sensor.desc[0] != '\0')
187                 mvwprintw(wnd, row, 58, "(%s)", sensor.desc);
188
189         switch (sensor.status) {
190         case SENSOR_S_UNSPEC:
191                 break;
192         case SENSOR_S_UNKNOWN:
193                 mvwaddstr(wnd, row, 45, "unknown");
194                 break;
195         case SENSOR_S_WARN:
196                 mvwaddstr(wnd, row, 45, "WARNING");
197                 break;
198         case SENSOR_S_CRIT:
199                 mvwaddstr(wnd, row, 45, "CRITICAL");
200                 break;
201         case SENSOR_S_OK:
202                 mvwaddstr(wnd, row, 45, "OK");
203                 break;
204         }
205         row++;
206 }
207
208 #define SECS_PER_DAY 86400
209 #define SECS_PER_HOUR 3600
210 #define SECS_PER_MIN 60
211
212 static char *
213 fmttime(double in)
214 {
215         int signbit = 1;
216         int tiny = 0;
217         char *unit;
218 #define LEN 32
219         static char outbuf[LEN];
220
221         if (in < 0){
222                 signbit = -1;
223                 in *= -1;
224         }
225
226         if (in >= SECS_PER_DAY ){
227                 unit = "days";
228                 in /= SECS_PER_DAY;
229         } else if (in >= SECS_PER_HOUR ){
230                 unit = "hr";
231                 in /= SECS_PER_HOUR;
232         } else if (in >= SECS_PER_MIN ){
233                 unit = "min";
234                 in /= SECS_PER_MIN;
235         } else if (in >= 1 ){
236                 unit = "s";
237                 /* in *= 1; */ /* no op */
238         } else if (in == 0 ){ /* direct comparisons to floats are scary */
239                 unit = "s";
240         } else if (in >= 1e-3 ){
241                 unit = "ms";
242                 in *= 1e3;
243         } else if (in >= 1e-6 ){
244                 unit = "us";
245                 in *= 1e6;
246         } else if (in >= 1e-9 ){
247                 unit = "ns";
248                 in *= 1e9;
249         } else {
250                 unit = "ps";
251                 if (in < 1e-13)
252                         tiny = 1;
253                 in *= 1e12;
254         }
255
256         snprintf(outbuf, LEN, 
257             tiny ? "%s%lf %s" : "%s%.3lf %s", 
258             signbit == -1 ? "-" : "", in, unit);
259
260         return outbuf;
261 }