1 /* $OpenBSD: sensors.c,v 1.11 2007/03/23 14:48:22 ckuethe Exp $ */
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>
37 struct sensordev sensordev
;
40 static char * fmttime(double);
42 struct sensordev_xname
{
45 u_int flags
; /* XNAME_FLAG_ */
48 #define XNAME_FLAG_WILDCARD 0x1
50 static int sensors_enabled
[SENSOR_MAX_TYPES
];
54 static int sensordev_xname_cnt
;
55 static struct sensordev_xname sensordev_xname
[XNAME_MAX
];
60 return (subwin(stdscr
, LINES
-5-1, 0, 5, 0));
64 closesensors(WINDOW
*w
)
78 mvwaddstr(wnd
, 0, 0, "Sensor");
79 mvwaddstr(wnd
, 0, 34, "Value");
80 mvwaddstr(wnd
, 0, 45, "Status");
81 mvwaddstr(wnd
, 0, 58, "Description");
87 enum sensor_type type
;
88 size_t slen
, sdlen
, idmax_len
;
89 int mib
[5], dev
, numt
, idmax
;
92 maxsensordevices
= MAXSENSORDEVICES
;
93 idmax_len
= sizeof(idmax
);
94 if (sysctlbyname("hw.sensors.dev_idmax", &idmax
, &idmax_len
,
96 maxsensordevices
= idmax
;
100 slen
= sizeof(struct sensor
);
101 sdlen
= sizeof(struct sensordev
);
109 for (dev
= 0; dev
< maxsensordevices
; dev
++) {
111 if (sysctl(mib
, 3, &sensordev
, &sdlen
, NULL
, 0) == -1) {
117 if (sensordev_xname_cnt
> 0) {
118 int i
, match
= 0, xname_len
;
120 xname_len
= strlen(sensordev
.xname
);
121 for (i
= 0; i
< sensordev_xname_cnt
; ++i
) {
122 const struct sensordev_xname
*x
;
124 x
= &sensordev_xname
[i
];
125 if (x
->flags
& XNAME_FLAG_WILDCARD
) {
126 if (xname_len
<= x
->xname_len
)
129 sensordev
.xname
[x
->xname_len
]))
131 if (strncmp(x
->xname
, sensordev
.xname
,
132 x
->xname_len
) == 0) {
136 } else if (xname_len
== x
->xname_len
&&
137 strcmp(x
->xname
, sensordev
.xname
) == 0) {
146 for (type
= 0; type
< SENSOR_MAX_TYPES
; type
++) {
147 if (!sensors_enabled
[type
])
151 for (numt
= 0; numt
< sensordev
.maxnumt
[type
]; numt
++) {
153 if (sysctl(mib
, 5, &sensor
, &slen
, NULL
, 0)
159 if (sensor
.flags
& SENSOR_FINVALID
)
168 const char *drvstat
[] = {
170 "empty", "ready", "powerup", "online", "idle", "active",
171 "rebuild", "powerdown", "fail", "pfail"
178 mvwaddstr(wnd
, row
, 0, "No sensors found.");
186 for (i
= 0; i
< SENSOR_MAX_TYPES
; ++i
)
187 sensors_enabled
[i
] = 1;
196 mvwprintw(wnd
, row
, 0, "%s.%s%d", sensordev
.xname
,
197 sensor_type_s
[sensor
.type
], sensor
.numt
);
198 switch (sensor
.type
) {
200 mvwprintw(wnd
, row
, 24, "%10.2f degC",
201 (sensor
.value
- 273150000) / 1000000.0);
204 mvwprintw(wnd
, row
, 24, "%11lld RPM", sensor
.value
);
206 case SENSOR_VOLTS_DC
:
207 mvwprintw(wnd
, row
, 24, "%10.2f V DC",
208 sensor
.value
/ 1000000.0);
211 mvwprintw(wnd
, row
, 24, "%13.2f W", sensor
.value
/ 1000000.0);
214 mvwprintw(wnd
, row
, 24, "%10.2f A", sensor
.value
/ 1000000.0);
216 case SENSOR_INDICATOR
:
217 mvwprintw(wnd
, row
, 24, "%15s", sensor
.value
? "On" : "Off");
220 mvwprintw(wnd
, row
, 24, "%11lld raw", sensor
.value
);
223 mvwprintw(wnd
, row
, 24, "%14.2f%%", sensor
.value
/ 1000.0);
226 mvwprintw(wnd
, row
, 24, "%15.2f lx", sensor
.value
/ 1000000.0);
229 if (0 < sensor
.value
&&
230 (size_t)sensor
.value
< sizeof(drvstat
)/sizeof(drvstat
[0])) {
231 mvwprintw(wnd
, row
, 24, "%15s", drvstat
[sensor
.value
]);
235 case SENSOR_TIMEDELTA
:
236 mvwprintw(wnd
, row
, 24, "%15s", fmttime(sensor
.value
/ 1000000000.0));
238 case SENSOR_WATTHOUR
:
239 mvwprintw(wnd
, row
, 24, "%12.2f Wh", sensor
.value
/ 1000000.0);
242 mvwprintw(wnd
, row
, 24, "%10.2f Ah", sensor
.value
/ 1000000.0);
245 humanize_number(buf
, sizeof(buf
), sensor
.value
, "Hz",
246 HN_AUTOSCALE
, HN_DIVISOR_1000
| HN_DECIMAL
);
247 mvwprintw(wnd
, row
, 24, "%15s", buf
);
250 mvwprintw(wnd
, row
, 24, "%10lld", sensor
.value
);
253 if (sensor
.desc
[0] != '\0')
254 mvwprintw(wnd
, row
, 58, "(%s)", sensor
.desc
);
256 switch (sensor
.status
) {
257 case SENSOR_S_UNSPEC
:
259 case SENSOR_S_UNKNOWN
:
260 mvwaddstr(wnd
, row
, 45, "unknown");
263 mvwaddstr(wnd
, row
, 45, "WARNING");
266 mvwaddstr(wnd
, row
, 45, "CRITICAL");
269 mvwaddstr(wnd
, row
, 45, "OK");
275 #define SECS_PER_DAY 86400
276 #define SECS_PER_HOUR 3600
277 #define SECS_PER_MIN 60
286 static char outbuf
[LEN
];
293 if (in
>= SECS_PER_DAY
){
296 } else if (in
>= SECS_PER_HOUR
){
299 } else if (in
>= SECS_PER_MIN
){
302 } else if (in
>= 1 ){
304 /* in *= 1; */ /* no op */
305 } else if (in
== 0 ){ /* direct comparisons to floats are scary */
307 } else if (in
>= 1e-3 ){
310 } else if (in
>= 1e-6 ){
313 } else if (in
>= 1e-9 ){
323 snprintf(outbuf
, LEN
,
324 tiny
? "%s%lf %s" : "%s%.3lf %s",
325 signbit
== -1 ? "-" : "", in
, unit
);
331 cmdsensors(const char *cmd
, char *args
)
333 if (prefix(cmd
, "type")) {
337 for (i
= 0; i
< SENSOR_MAX_TYPES
; ++i
)
338 sensors_enabled
[i
] = 0;
340 while ((t
= strsep(&args
, " ")) != NULL
) {
345 for (i
= 0; i
< SENSOR_MAX_TYPES
; ++i
) {
346 if (strcmp(t
, sensor_type_s
[i
]) == 0) {
347 sensors_enabled
[i
] = 1;
354 for (i
= 0; i
< SENSOR_MAX_TYPES
; ++i
)
355 sensors_enabled
[i
] = 1;
357 } else if (prefix(cmd
, "match")) {
360 sensordev_xname_cnt
= 0;
361 while ((xname
= strsep(&args
, " ")) != NULL
) {
362 struct sensordev_xname
*x
;
363 int xname_len
, cp_len
;
365 xname_len
= strlen(xname
);
369 x
= &sensordev_xname
[sensordev_xname_cnt
];
372 if (xname
[xname_len
- 1] == '*') {
376 x
->flags
|= XNAME_FLAG_WILDCARD
;
379 if (cp_len
>= (int)sizeof(x
->xname
))
380 cp_len
= sizeof(x
->xname
) - 1;
382 memcpy(x
->xname
, xname
, cp_len
);
383 x
->xname
[cp_len
] = '\0';
384 x
->xname_len
= strlen(x
->xname
);
386 sensordev_xname_cnt
++;
387 if (sensordev_xname_cnt
== XNAME_MAX
)