Merge branch 'vendor/GCC50'
[dragonfly.git] / usr.bin / systat / sensors.c
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, idmax_len;
71         int              mib[5], dev, numt, idmax;
72         int              maxsensordevices;
73
74         maxsensordevices = MAXSENSORDEVICES;
75         idmax_len = sizeof(idmax);
76         if (sysctlbyname("hw.sensors.dev_idmax", &idmax, &idmax_len,
77             NULL, 0) == 0)
78                 maxsensordevices = idmax;
79
80         mib[0] = CTL_HW;
81         mib[1] = HW_SENSORS;
82         slen = sizeof(struct sensor);
83         sdlen = sizeof(struct sensordev);
84
85         row = 1;
86         sensor_cnt = 0;
87
88         wmove(wnd, row, 0);
89         wclrtobot(wnd);
90
91         for (dev = 0; dev < maxsensordevices; dev++) {
92                 mib[2] = dev;
93                 if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
94                         if (errno != ENOENT)
95                                 warn("sysctl");
96                         continue;
97                 }
98                 for (type = 0; type < SENSOR_MAX_TYPES; type++) {
99                         mib[3] = type;
100                         for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
101                                 mib[4] = numt;
102                                 if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
103                                     == -1) {
104                                         if (errno != ENOENT)
105                                                 warn("sysctl");
106                                         continue;
107                                 }
108                                 if (sensor.flags & SENSOR_FINVALID)
109                                         continue;
110                                 sensor_cnt++;
111                                 printline();
112                         }
113                 }
114         }
115 }
116
117 const char *drvstat[] = {
118         NULL,
119         "empty", "ready", "powerup", "online", "idle", "active",
120         "rebuild", "powerdown", "fail", "pfail"
121 };
122
123 void
124 showsensors(void)
125 {
126         if (sensor_cnt == 0)
127                 mvwaddstr(wnd, row, 0, "No sensors found.");
128 }
129
130 int
131 initsensors(void)
132 {
133         return (1);
134 }
135
136 void
137 printline(void)
138 {
139         mvwprintw(wnd, row, 0, "%s.%s%d", sensordev.xname,
140             sensor_type_s[sensor.type], sensor.numt);
141         switch (sensor.type) {
142         case SENSOR_TEMP:
143                 mvwprintw(wnd, row, 24, "%10.2f degC",
144                     (sensor.value - 273150000) / 1000000.0);
145                 break;
146         case SENSOR_FANRPM:
147                 mvwprintw(wnd, row, 24, "%11lld RPM", sensor.value);
148                 break;
149         case SENSOR_VOLTS_DC:
150                 mvwprintw(wnd, row, 24, "%10.2f V DC",
151                     sensor.value / 1000000.0);
152                 break;
153         case SENSOR_AMPS:
154                 mvwprintw(wnd, row, 24, "%10.2f A", sensor.value / 1000000.0);
155                 break;
156         case SENSOR_INDICATOR:
157                 mvwprintw(wnd, row, 24, "%15s", sensor.value? "On" : "Off");
158                 break;
159         case SENSOR_INTEGER:
160                 mvwprintw(wnd, row, 24, "%11lld raw", sensor.value);
161                 break;
162         case SENSOR_PERCENT:
163                 mvwprintw(wnd, row, 24, "%14.2f%%", sensor.value / 1000.0);
164                 break;
165         case SENSOR_LUX:
166                 mvwprintw(wnd, row, 24, "%15.2f lx", sensor.value / 1000000.0);
167                 break;
168         case SENSOR_DRIVE:
169                 if (0 < sensor.value &&
170                     (size_t)sensor.value < sizeof(drvstat)/sizeof(drvstat[0])) {
171                         mvwprintw(wnd, row, 24, "%15s", drvstat[sensor.value]);
172                         break;
173                 }
174                 break;
175         case SENSOR_TIMEDELTA:
176                 mvwprintw(wnd, row, 24, "%15s", fmttime(sensor.value / 1000000000.0));
177                 break;
178         case SENSOR_WATTHOUR:
179                 mvwprintw(wnd, row, 24, "%12.2f Wh", sensor.value / 1000000.0);
180                 break;
181         case SENSOR_AMPHOUR:
182                 mvwprintw(wnd, row, 24, "%10.2f Ah", sensor.value / 1000000.0);
183                 break;
184         default:
185                 mvwprintw(wnd, row, 24, "%10lld", sensor.value);
186                 break;
187         }
188         if (sensor.desc[0] != '\0')
189                 mvwprintw(wnd, row, 58, "(%s)", sensor.desc);
190
191         switch (sensor.status) {
192         case SENSOR_S_UNSPEC:
193                 break;
194         case SENSOR_S_UNKNOWN:
195                 mvwaddstr(wnd, row, 45, "unknown");
196                 break;
197         case SENSOR_S_WARN:
198                 mvwaddstr(wnd, row, 45, "WARNING");
199                 break;
200         case SENSOR_S_CRIT:
201                 mvwaddstr(wnd, row, 45, "CRITICAL");
202                 break;
203         case SENSOR_S_OK:
204                 mvwaddstr(wnd, row, 45, "OK");
205                 break;
206         }
207         row++;
208 }
209
210 #define SECS_PER_DAY 86400
211 #define SECS_PER_HOUR 3600
212 #define SECS_PER_MIN 60
213
214 static char *
215 fmttime(double in)
216 {
217         int signbit = 1;
218         int tiny = 0;
219         const char *unit;
220 #define LEN 32
221         static char outbuf[LEN];
222
223         if (in < 0){
224                 signbit = -1;
225                 in *= -1;
226         }
227
228         if (in >= SECS_PER_DAY ){
229                 unit = "days";
230                 in /= SECS_PER_DAY;
231         } else if (in >= SECS_PER_HOUR ){
232                 unit = "hr";
233                 in /= SECS_PER_HOUR;
234         } else if (in >= SECS_PER_MIN ){
235                 unit = "min";
236                 in /= SECS_PER_MIN;
237         } else if (in >= 1 ){
238                 unit = "s";
239                 /* in *= 1; */ /* no op */
240         } else if (in == 0 ){ /* direct comparisons to floats are scary */
241                 unit = "s";
242         } else if (in >= 1e-3 ){
243                 unit = "ms";
244                 in *= 1e3;
245         } else if (in >= 1e-6 ){
246                 unit = "us";
247                 in *= 1e6;
248         } else if (in >= 1e-9 ){
249                 unit = "ns";
250                 in *= 1e9;
251         } else {
252                 unit = "ps";
253                 if (in < 1e-13)
254                         tiny = 1;
255                 in *= 1e12;
256         }
257
258         snprintf(outbuf, LEN, 
259             tiny ? "%s%lf %s" : "%s%.3lf %s", 
260             signbit == -1 ? "-" : "", in, unit);
261
262         return outbuf;
263 }