1 /*
2 * Copyright (c) 2001-2005 Willem Dijkstra
3 * Copyright (c) 2006/2007 Constantine A. Murenin
4 * <cnst+symon@bugmail.mojo.ru>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33 /*
34 * Get sensor data from the kernel and return in symon_buf as
35 *
36 * num : value
37 *
38 */
39
40 #include "conf.h"
41
42 #include <sys/param.h>
43 #include <sys/sensors.h>
44 #include <sys/sysctl.h>
45
46 #include <errno.h>
47 #include <limits.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
51
52 #include "error.h"
53 #include "symon.h"
54 #include "xmalloc.h"
55
56 #ifndef MAXSENSORDEVICES
57 #define MAXSENSORDEVICES 1024
58 #endif
59
60 /* Globals for this module start with sn_ */
61 static struct sensor sn_sensor;
62
63 void
privinit_sensor()64 privinit_sensor()
65 {
66 /* EMPTY */
67 }
68
69 void
init_sensor(struct stream * st)70 init_sensor(struct stream *st)
71 {
72 #ifndef HAS_SENSORDEV
73
74 long l = strtol(st->arg, NULL, 10);
75 st->parg.sn.mib[0] = CTL_HW;
76 st->parg.sn.mib[1] = HW_SENSORS;
77 st->parg.sn.mib[2] = (int) (l & SYMON_SENSORMASK);
78
79 #else /* HAS_SENSORDEV */
80
81 char *devname, *typename, *bufp, *bufpo;
82 int dev, numt, i;
83 enum sensor_type type;
84 struct sensordev sensordev;
85 size_t sdlen = sizeof(sensordev);
86
87 st->parg.sn.mib[0] = CTL_HW;
88 st->parg.sn.mib[1] = HW_SENSORS;
89
90 bufpo = xstrdup(st->arg);
91 bufp = bufpo;
92
93 if ((devname = strsep(&bufp, ".")) == NULL)
94 fatal("%s:%d: sensor(%.200s): incomplete specification",
95 __FILE__, __LINE__, st->arg);
96
97 /* convert sensor device string to an integer */
98 for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
99 st->parg.sn.mib[2] = dev;
100 if (sysctl(st->parg.sn.mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
101 if (errno == ENOENT)
102 break;
103 if (errno == ENXIO)
104 continue;
105 fatal("%s:%d: sensor(%.200s): sensor %d unknown errno %d",
106 __FILE__, __LINE__, st->arg, dev, errno);
107 }
108 if (strcmp(devname, sensordev.xname) == 0)
109 break;
110 }
111 if (strcmp(devname, sensordev.xname) != 0)
112 fatal("sensor(%.200s): device not found: %.200s",
113 st->arg, devname);
114
115 /* convert sensor_type string to an integer */
116 if ((typename = strsep(&bufp, ".")) == NULL)
117 fatal("%s:%d: sensor(%.200s): incomplete specification",
118 __FILE__, __LINE__, st->arg);
119 numt = -1;
120 for (i = 0; typename[i] != '\0'; i++)
121 if (isdigit(typename[i])) {
122 numt = atoi(&typename[i]);
123 typename[i] = '\0';
124 break;
125 }
126 for (type = 0; type < SENSOR_MAX_TYPES; type++)
127 if (strcmp(typename, sensor_type_s[type]) == 0)
128 break;
129 if (type == SENSOR_MAX_TYPES)
130 fatal("sensor(%.200s): sensor type not recognised: %.200s",
131 st->arg, typename);
132 if (sensordev.maxnumt[type] == 0)
133 fatal("sensor(%.200s): no sensors of such type on this device: %.200s",
134 st->arg, typename);
135 st->parg.sn.mib[3] = type;
136
137 if (numt == -1) {
138 warning("sensor(%.200s): sensor number not specified, using 0",
139 st->arg);
140 numt = 0;
141 }
142 if (!(numt < sensordev.maxnumt[type]))
143 fatal("sensor(%.200s): no such sensor attached to this device: %.200s%i",
144 st->arg, typename, numt);
145 st->parg.sn.mib[4] = numt;
146
147 xfree(bufpo);
148
149 #endif /* !HAS_SENSORDEV */
150
151 info("started module sensor(%.200s)", st->arg);
152 }
153
154 int
get_sensor(char * symon_buf,int maxlen,struct stream * st)155 get_sensor(char *symon_buf, int maxlen, struct stream *st)
156 {
157 size_t len = sizeof(sn_sensor);
158 double t;
159
160 if (sysctl(st->parg.sn.mib,
161 sizeof(st->parg.sn.mib)/sizeof(st->parg.sn.mib[0]),
162 &sn_sensor, &len, NULL, 0) == -1) {
163 if (errno != ENOENT)
164 warning("%s:%d: sensor(%.200s): sysctl error: %.200s",
165 __FILE__, __LINE__, st->arg, strerror(errno));
166 else
167 warning("sensor(%.200s): sensor not found",
168 st->arg);
169
170 return 0;
171 } else {
172 switch (sn_sensor.type) {
173 case SENSOR_TEMP:
174 t = (double) (sn_sensor.value / 1000.0 / 1000.0) - 273.15;
175 break;
176 case SENSOR_FANRPM:
177 t = (double) sn_sensor.value;
178 break;
179 case SENSOR_VOLTS_DC:
180 t = (double) (sn_sensor.value / 1000.0 / 1000.0);
181 break;
182 default:
183 t = (double) sn_sensor.value;
184 }
185
186 return snpack(symon_buf, maxlen, st->arg, MT_SENSOR, t);
187 }
188 }
189