| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: swsensor.c,v 1.11 2011/06/19 04:08:48 pgoyette Exp $ */ | | 1 | /* $NetBSD: swsensor.c,v 1.12 2011/06/19 15:52:48 pgoyette Exp $ */ |
2 | /* | | 2 | /* |
3 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 3 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
4 | * All rights reserved. | | 4 | * All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -17,27 +17,27 @@ | | | @@ -17,27 +17,27 @@ |
17 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | | 17 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY | | 19 | * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | | 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
24 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | | 24 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | | 25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: swsensor.c,v 1.11 2011/06/19 04:08:48 pgoyette Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: swsensor.c,v 1.12 2011/06/19 15:52:48 pgoyette Exp $"); |
31 | | | 31 | |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/kernel.h> | | 33 | #include <sys/kernel.h> |
34 | #include <sys/module.h> | | 34 | #include <sys/module.h> |
35 | #include <sys/sysctl.h> | | 35 | #include <sys/sysctl.h> |
36 | | | 36 | |
37 | #include <dev/sysmon/sysmonvar.h> | | 37 | #include <dev/sysmon/sysmonvar.h> |
38 | #include <dev/sysmon/sysmon_envsysvar.h> | | 38 | #include <dev/sysmon/sysmon_envsysvar.h> |
39 | | | 39 | |
40 | #include <prop/proplib.h> | | 40 | #include <prop/proplib.h> |
41 | | | 41 | |
42 | #ifndef _MODULE | | 42 | #ifndef _MODULE |
43 | #include "opt_modular.h" | | 43 | #include "opt_modular.h" |
| @@ -93,26 +93,35 @@ sysctl_swsensor_setup(void) | | | @@ -93,26 +93,35 @@ sysctl_swsensor_setup(void) |
93 | sensor_value_sysctl = me->sysctl_num; | | 93 | sensor_value_sysctl = me->sysctl_num; |
94 | } | | 94 | } |
95 | | | 95 | |
96 | /* | | 96 | /* |
97 | * "Polling" routine to update sensor value | | 97 | * "Polling" routine to update sensor value |
98 | */ | | 98 | */ |
99 | static | | 99 | static |
100 | void | | 100 | void |
101 | swsensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | | 101 | swsensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) |
102 | { | | 102 | { |
103 | | | 103 | |
104 | edata->value_cur = sw_sensor_value; | | 104 | edata->value_cur = sw_sensor_value; |
105 | | | 105 | |
| | | 106 | /* If value outside of legal range, mark it invalid */ |
| | | 107 | if ((edata->flags & ENVSYS_FVALID_MIN && |
| | | 108 | edata->value_cur < edata->value_min) || |
| | | 109 | (edata->flags & ENVSYS_FVALID_MAX && |
| | | 110 | edata->value_cur > edata->value_max)) { |
| | | 111 | edata->state = ENVSYS_SINVALID; |
| | | 112 | return; |
| | | 113 | } |
| | | 114 | |
106 | /* | | 115 | /* |
107 | * Set state. If we're handling the limits ourselves, do the | | 116 | * Set state. If we're handling the limits ourselves, do the |
108 | * compare; otherwise just assume the value is valid. | | 117 | * compare; otherwise just assume the value is valid. |
109 | */ | | 118 | */ |
110 | if ((sw_sensor_mode == 2) && (edata->upropset & PROP_CRITMIN) && | | 119 | if ((sw_sensor_mode == 2) && (edata->upropset & PROP_CRITMIN) && |
111 | (edata->upropset & PROP_DRIVER_LIMITS) && | | 120 | (edata->upropset & PROP_DRIVER_LIMITS) && |
112 | (edata->value_cur < edata->limits.sel_critmin)) | | 121 | (edata->value_cur < edata->limits.sel_critmin)) |
113 | edata->state = ENVSYS_SCRITUNDER; | | 122 | edata->state = ENVSYS_SCRITUNDER; |
114 | else | | 123 | else |
115 | edata->state = ENVSYS_SVALID; | | 124 | edata->state = ENVSYS_SVALID; |
116 | } | | 125 | } |
117 | | | 126 | |
118 | /* | | 127 | /* |
| @@ -149,27 +158,27 @@ swsensor_set_limits(struct sysmon_envsys | | | @@ -149,27 +158,27 @@ swsensor_set_limits(struct sysmon_envsys |
149 | *props |= PROP_DRIVER_LIMITS; | | 158 | *props |= PROP_DRIVER_LIMITS; |
150 | else | | 159 | else |
151 | *props &= ~PROP_DRIVER_LIMITS; | | 160 | *props &= ~PROP_DRIVER_LIMITS; |
152 | } | | 161 | } |
153 | | | 162 | |
154 | /* | | 163 | /* |
155 | * Module management | | 164 | * Module management |
156 | */ | | 165 | */ |
157 | | | 166 | |
158 | static | | 167 | static |
159 | int | | 168 | int |
160 | swsensor_init(void *arg) | | 169 | swsensor_init(void *arg) |
161 | { | | 170 | { |
162 | int error; | | 171 | int error, val = 0; |
163 | const char *key, *str; | | 172 | const char *key, *str; |
164 | prop_dictionary_t pd = (prop_dictionary_t)arg; | | 173 | prop_dictionary_t pd = (prop_dictionary_t)arg; |
165 | prop_object_t po, obj; | | 174 | prop_object_t po, obj; |
166 | prop_object_iterator_t iter; | | 175 | prop_object_iterator_t iter; |
167 | prop_type_t type; | | 176 | prop_type_t type; |
168 | const struct sme_descr_entry *descr; | | 177 | const struct sme_descr_entry *descr; |
169 | | | 178 | |
170 | swsensor_sme = sysmon_envsys_create(); | | 179 | swsensor_sme = sysmon_envsys_create(); |
171 | if (swsensor_sme == NULL) | | 180 | if (swsensor_sme == NULL) |
172 | return ENOTTY; | | 181 | return ENOTTY; |
173 | | | 182 | |
174 | swsensor_sme->sme_name = "swsensor"; | | 183 | swsensor_sme->sme_name = "swsensor"; |
175 | swsensor_sme->sme_cookie = &swsensor_edata; | | 184 | swsensor_sme->sme_cookie = &swsensor_edata; |
| @@ -185,160 +194,155 @@ swsensor_init(void *arg) | | | @@ -185,160 +194,155 @@ swsensor_init(void *arg) |
185 | sw_sensor_value = 0; | | 194 | sw_sensor_value = 0; |
186 | sw_sensor_limit = 0; | | 195 | sw_sensor_limit = 0; |
187 | | | 196 | |
188 | /* Iterate over the provided dictionary, if any */ | | 197 | /* Iterate over the provided dictionary, if any */ |
189 | if (pd != NULL) { | | 198 | if (pd != NULL) { |
190 | iter = prop_dictionary_iterator(pd); | | 199 | iter = prop_dictionary_iterator(pd); |
191 | if (iter == NULL) | | 200 | if (iter == NULL) |
192 | return ENOMEM; | | 201 | return ENOMEM; |
193 | | | 202 | |
194 | while ((obj = prop_object_iterator_next(iter)) != NULL) { | | 203 | while ((obj = prop_object_iterator_next(iter)) != NULL) { |
195 | key = prop_dictionary_keysym_cstring_nocopy(obj); | | 204 | key = prop_dictionary_keysym_cstring_nocopy(obj); |
196 | po = prop_dictionary_get_keysym(pd, obj); | | 205 | po = prop_dictionary_get_keysym(pd, obj); |
197 | type = prop_object_type(po); | | 206 | type = prop_object_type(po); |
| | | 207 | if (type == PROP_TYPE_NUMBER) |
| | | 208 | val = prop_number_integer_value(po); |
198 | | | 209 | |
199 | /* Sensor type/units */ | | 210 | /* Sensor type/units */ |
200 | if (strcmp(key, "type") == 0) { | | 211 | if (strcmp(key, "type") == 0) { |
201 | if (type == PROP_TYPE_NUMBER) { | | 212 | if (type == PROP_TYPE_NUMBER) { |
202 | swsensor_edata.units = | | 213 | descr = sme_find_table_entry( |
203 | prop_number_integer_value(po); | | 214 | SME_DESC_UNITS, val); |
| | | 215 | if (descr == NULL) |
| | | 216 | return EINVAL; |
| | | 217 | swsensor_edata.units = descr->type; |
204 | continue; | | 218 | continue; |
205 | } | | 219 | } |
206 | if (type != PROP_TYPE_STRING) | | 220 | if (type != PROP_TYPE_STRING) |
207 | return EINVAL; | | 221 | return EINVAL; |
208 | str = prop_string_cstring_nocopy(po); | | 222 | str = prop_string_cstring_nocopy(po); |
209 | descr = sme_find_table_desc(SME_DESC_UNITS, | | 223 | descr = sme_find_table_desc(SME_DESC_UNITS, |
210 | str); | | 224 | str); |
211 | if (descr->type < 0) | | 225 | if (descr == NULL) |
212 | return EINVAL; | | 226 | return EINVAL; |
213 | swsensor_edata.units = descr->type; | | 227 | swsensor_edata.units = descr->type; |
214 | continue; | | 228 | continue; |
215 | } | | 229 | } |
216 | | | 230 | |
217 | /* Sensor flags */ | | 231 | /* Sensor flags */ |
218 | if (strcmp(key, "flags") == 0) { | | 232 | if (strcmp(key, "flags") == 0) { |
219 | if (type != PROP_TYPE_NUMBER) | | 233 | if (type != PROP_TYPE_NUMBER) |
220 | return EINVAL; | | 234 | return EINVAL; |
221 | swsensor_edata.flags = | | 235 | swsensor_edata.flags = val; |
222 | prop_number_integer_value(po); | | | |
223 | continue; | | 236 | continue; |
224 | } | | 237 | } |
225 | | | 238 | |
226 | /* Sensor limit behavior | | 239 | /* Sensor limit behavior |
227 | * 0 - simple sensor, no hw limits | | 240 | * 0 - simple sensor, no hw limits |
228 | * 1 - simple sensor, hw provides initial limit | | 241 | * 1 - simple sensor, hw provides initial limit |
229 | * 2 - complex sensor, hw provides settable | | 242 | * 2 - complex sensor, hw provides settable |
230 | * limits and does its own limit checking | | 243 | * limits and does its own limit checking |
231 | */ | | 244 | */ |
232 | if (strcmp(key, "mode") == 0) { | | 245 | if (strcmp(key, "mode") == 0) { |
233 | if (type != PROP_TYPE_NUMBER) | | 246 | if (type != PROP_TYPE_NUMBER) |
234 | return EINVAL; | | 247 | return EINVAL; |
235 | sw_sensor_mode = prop_number_integer_value(po); | | 248 | sw_sensor_mode = val; |
236 | if (sw_sensor_mode > 2) | | 249 | if (sw_sensor_mode > 2) |
237 | sw_sensor_mode = 2; | | 250 | sw_sensor_mode = 2; |
238 | else if (sw_sensor_mode < 0) | | 251 | else if (sw_sensor_mode < 0) |
239 | sw_sensor_mode = 0; | | 252 | sw_sensor_mode = 0; |
240 | continue; | | 253 | continue; |
241 | } | | 254 | } |
242 | | | 255 | |
243 | /* Grab any limit that might be specified */ | | 256 | /* Grab any limit that might be specified */ |
244 | if (strcmp(key, "limit") == 0) { | | 257 | if (strcmp(key, "limit") == 0) { |
245 | if (type != PROP_TYPE_NUMBER) | | 258 | if (type != PROP_TYPE_NUMBER) |
246 | return EINVAL; | | 259 | return EINVAL; |
247 | sw_sensor_limit = prop_number_integer_value(po); | | 260 | sw_sensor_limit = val; |
248 | continue; | | 261 | continue; |
249 | } | | 262 | } |
250 | | | 263 | |
251 | /* Grab the initial value */ | | 264 | /* Grab the initial value */ |
252 | if (strcmp(key, "value") == 0) { | | 265 | if (strcmp(key, "value") == 0) { |
253 | if (type != PROP_TYPE_NUMBER) | | 266 | if (type != PROP_TYPE_NUMBER) |
254 | return EINVAL; | | 267 | return EINVAL; |
255 | sw_sensor_value = prop_number_integer_value(po); | | 268 | sw_sensor_value = val; |
256 | continue; | | 269 | continue; |
257 | } | | 270 | } |
258 | | | 271 | |
259 | /* Grab value_min and value_max */ | | 272 | /* Grab value_min and value_max */ |
260 | if (strcmp(key, "value_min") == 0) { | | 273 | if (strcmp(key, "value_min") == 0) { |
261 | if (type != PROP_TYPE_NUMBER) | | 274 | if (type != PROP_TYPE_NUMBER) |
262 | return EINVAL; | | 275 | return EINVAL; |
263 | swsensor_edata.value_min = | | 276 | swsensor_edata.value_min = val; |
264 | prop_number_integer_value(po); | | | |
265 | swsensor_edata.flags |= ENVSYS_FVALID_MIN; | | 277 | swsensor_edata.flags |= ENVSYS_FVALID_MIN; |
266 | continue; | | 278 | continue; |
267 | } | | 279 | } |
268 | if (strcmp(key, "value_max") == 0) { | | 280 | if (strcmp(key, "value_max") == 0) { |
269 | if (type != PROP_TYPE_NUMBER) | | 281 | if (type != PROP_TYPE_NUMBER) |
270 | return EINVAL; | | 282 | return EINVAL; |
271 | swsensor_edata.value_max = | | 283 | swsensor_edata.value_max = val; |
272 | prop_number_integer_value(po); | | | |
273 | swsensor_edata.flags |= ENVSYS_FVALID_MAX; | | 284 | swsensor_edata.flags |= ENVSYS_FVALID_MAX; |
274 | continue; | | 285 | continue; |
275 | } | | 286 | } |
276 | | | 287 | |
277 | /* See if sensor reports percentages vs raw values */ | | 288 | /* See if sensor reports percentages vs raw values */ |
278 | if (strcmp(key, "percentage") == 0) { | | 289 | if (strcmp(key, "percentage") == 0) { |
279 | if (type != PROP_TYPE_BOOL) | | 290 | if (type != PROP_TYPE_BOOL) |
280 | return EINVAL; | | 291 | return EINVAL; |
281 | if (prop_bool_true(po)) | | 292 | if (prop_bool_true(po)) |
282 | swsensor_edata.flags |= ENVSYS_FPERCENT; | | 293 | swsensor_edata.flags |= ENVSYS_FPERCENT; |
283 | continue; | | 294 | continue; |
284 | } | | 295 | } |
285 | | | 296 | |
286 | /* Unrecognized dicttionary object */ | | 297 | /* Unrecognized dicttionary object */ |
| | | 298 | #ifdef DEBUG |
| | | 299 | printf("%s: unknown attribute %s\n", __func__, key); |
| | | 300 | #endif |
287 | return EINVAL; | | 301 | return EINVAL; |
288 | | | 302 | |
289 | } /* while */ | | 303 | } /* while */ |
290 | prop_object_iterator_release(iter); | | 304 | prop_object_iterator_release(iter); |
291 | } | | 305 | } |
292 | | | 306 | |
293 | /* Initialize limit processing */ | | 307 | /* Initialize limit processing */ |
294 | if (sw_sensor_mode >= 1) | | 308 | if (sw_sensor_mode >= 1) |
295 | swsensor_sme->sme_get_limits = swsensor_get_limits; | | 309 | swsensor_sme->sme_get_limits = swsensor_get_limits; |
296 | | | 310 | |
297 | if (sw_sensor_mode == 2) | | 311 | if (sw_sensor_mode == 2) |
298 | swsensor_sme->sme_set_limits = swsensor_set_limits; | | 312 | swsensor_sme->sme_set_limits = swsensor_set_limits; |
299 | | | 313 | |
300 | if (sw_sensor_mode != 0) { | | 314 | if (sw_sensor_mode != 0) { |
301 | swsensor_edata.flags |= ENVSYS_FMONLIMITS; | | 315 | swsensor_edata.flags |= ENVSYS_FMONLIMITS; |
302 | swsensor_get_limits(swsensor_sme, &swsensor_edata, | | 316 | swsensor_get_limits(swsensor_sme, &swsensor_edata, |
303 | &sw_sensor_deflims, &sw_sensor_defprops); | | 317 | &sw_sensor_deflims, &sw_sensor_defprops); |
304 | } | | 318 | } |
305 | | | 319 | |
306 | /* | | | |
307 | * If {min, max} value range was specified, make sure that the | | | |
308 | * current value is within the range. | | | |
309 | */ | | | |
310 | if (swsensor_edata.flags & ENVSYS_FVALID_MAX && | | | |
311 | sw_sensor_value > swsensor_edata.value_max) | | | |
312 | swsensor_edata.state = ENVSYS_SINVALID; | | | |
313 | if (swsensor_edata.flags & ENVSYS_FVALID_MIN && | | | |
314 | sw_sensor_value < swsensor_edata.value_min) | | | |
315 | swsensor_edata.state = ENVSYS_SINVALID; | | | |
316 | else | | | |
317 | swsensor_edata.state = ENVSYS_SVALID; | | | |
318 | swsensor_edata.value_cur = sw_sensor_value; | | | |
319 | | | | |
320 | strlcpy(swsensor_edata.desc, "sensor", ENVSYS_DESCLEN); | | 320 | strlcpy(swsensor_edata.desc, "sensor", ENVSYS_DESCLEN); |
321 | | | 321 | |
| | | 322 | /* Wait for refresh to validate the sensor value */ |
| | | 323 | swsensor_edata.state = ENVSYS_SINVALID; |
| | | 324 | |
322 | error = sysmon_envsys_sensor_attach(swsensor_sme, &swsensor_edata); | | 325 | error = sysmon_envsys_sensor_attach(swsensor_sme, &swsensor_edata); |
323 | if (error != 0) { | | 326 | if (error != 0) { |
324 | aprint_error("sysmon_envsys_sensor_attach failed: %d\n", error); | | 327 | aprint_error("sysmon_envsys_sensor_attach failed: %d\n", error); |
325 | return error; | | 328 | return error; |
326 | } | | 329 | } |
327 | | | 330 | |
328 | error = sysmon_envsys_register(swsensor_sme); | | 331 | error = sysmon_envsys_register(swsensor_sme); |
329 | if (error != 0) | | 332 | if (error != 0) { |
330 | aprint_error("sysmon_envsys_register failed: %d\n", error); | | 333 | aprint_error("sysmon_envsys_register failed: %d\n", error); |
331 | return error; | | 334 | return error; |
| | | 335 | } |
332 | | | 336 | |
333 | sysctl_swsensor_setup(); | | 337 | sysctl_swsensor_setup(); |
334 | aprint_normal("swsensor: initialized\n"); | | 338 | aprint_normal("swsensor: initialized\n"); |
335 | | | 339 | |
336 | return 0; | | 340 | return 0; |
337 | } | | 341 | } |
338 | | | 342 | |
339 | static | | 343 | static |
340 | int | | 344 | int |
341 | swsensor_fini(void *arg) | | 345 | swsensor_fini(void *arg) |
342 | { | | 346 | { |
343 | | | 347 | |
344 | sysmon_envsys_unregister(swsensor_sme); | | 348 | sysmon_envsys_unregister(swsensor_sme); |