sht3x.c revision 1.1 1 /* $NetBSD: sht3x.c,v 1.1 2021/11/06 13:34:40 brad Exp $ */
2
3 /*
4 * Copyright (c) 2021 Brad Spencer <brad (at) anduin.eldar.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/cdefs.h>
20 __KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.1 2021/11/06 13:34:40 brad Exp $");
21
22 /*
23 Driver for the Sensirion SHT30/SHT31/SHT35
24 */
25
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/kernel.h>
29 #include <sys/device.h>
30 #include <sys/module.h>
31 #include <sys/conf.h>
32 #include <sys/sysctl.h>
33 #include <sys/mutex.h>
34 #include <sys/condvar.h>
35 #include <sys/kthread.h>
36 #include <sys/pool.h>
37 #include <sys/kmem.h>
38
39 #include <dev/sysmon/sysmonvar.h>
40 #include <dev/i2c/i2cvar.h>
41 #include <dev/i2c/sht3xreg.h>
42 #include <dev/i2c/sht3xvar.h>
43
44
45 static int sht3x_take_break(void *, bool);
46 static int sht3x_get_status_register(void *, uint16_t *, bool);
47 static int sht3x_clear_status_register(void *, bool);
48 static uint8_t sht3x_crc(uint8_t *, size_t);
49 static int sht3x_cmdr(struct sht3x_sc *, uint16_t, uint8_t *, size_t);
50 static int sht3x_poke(i2c_tag_t, i2c_addr_t, bool);
51 static int sht3x_match(device_t, cfdata_t, void *);
52 static void sht3x_attach(device_t, device_t, void *);
53 static int sht3x_detach(device_t, int);
54 static void sht3x_refresh(struct sysmon_envsys *, envsys_data_t *);
55 /* The chip that I had would not allow the limits to actually be set
56 * for reasons which are not obvious. The chip took the command just
57 * fine, but a read back of the limit registers showed that no change
58 * was made, so disable limits for now.
59 */
60 #ifdef __did_not_work
61 static void sht3x_get_limits(struct sysmon_envsys *, envsys_data_t *,
62 sysmon_envsys_lim_t *, uint32_t *);
63 static void sht3x_set_limits(struct sysmon_envsys *, envsys_data_t *,
64 sysmon_envsys_lim_t *, uint32_t *);
65 #endif
66 static int sht3x_verify_sysctl(SYSCTLFN_ARGS);
67 static int sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS);
68 static int sht3x_verify_sysctl_modes(SYSCTLFN_ARGS);
69 static int sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS);
70 static int sht3x_verify_sysctl_rate(SYSCTLFN_ARGS);
71 static int sht3x_set_heater(struct sht3x_sc *);
72 static void sht3x_thread(void *);
73 static int sht3x_init_periodic_measurement(void *, int *);
74 static void sht3x_take_periodic_measurement(void *);
75 static void sht3x_start_thread(void *);
76 static void sht3x_stop_thread(void *);
77 static int sht3x_activate(device_t, enum devact);
78
79 #define SHT3X_DEBUG
80 #ifdef SHT3X_DEBUG
81 #define DPRINTF(s, l, x) \
82 do { \
83 if (l <= s->sc_sht3xdebug) \
84 printf x; \
85 } while (/*CONSTCOND*/0)
86 #else
87 #define DPRINTF(s, l, x)
88 #endif
89
90 CFATTACH_DECL_NEW(sht3xtemp, sizeof(struct sht3x_sc),
91 sht3x_match, sht3x_attach, sht3x_detach, sht3x_activate);
92
93 extern struct cfdriver sht3xtemp_cd;
94
95 static dev_type_open(sht3xopen);
96 static dev_type_read(sht3xread);
97 static dev_type_close(sht3xclose);
98 const struct cdevsw sht3x_cdevsw = {
99 .d_open = sht3xopen,
100 .d_close = sht3xclose,
101 .d_read = sht3xread,
102 .d_write = nowrite,
103 .d_ioctl = noioctl,
104 .d_stop = nostop,
105 .d_tty = notty,
106 .d_poll = nopoll,
107 .d_mmap = nommap,
108 .d_kqfilter = nokqfilter,
109 .d_discard = nodiscard,
110 .d_flag = D_OTHER
111 };
112
113 static struct sht3x_sensor sht3x_sensors[] = {
114 {
115 .desc = "humidity",
116 .type = ENVSYS_SRELHUMIDITY,
117 },
118 {
119 .desc = "temperature",
120 .type = ENVSYS_STEMP,
121 }
122 };
123
124 /* The typical delays are MOSTLY documented in the datasheet for the chip.
125 There is no need to be very accurate with these, just rough estimates
126 will work fine.
127 */
128
129 static struct sht3x_timing sht3x_timings[] = {
130 {
131 .cmd = SHT3X_SOFT_RESET,
132 .typicaldelay = 3000,
133 },
134 {
135 .cmd = SHT3X_GET_STATUS_REGISTER,
136 .typicaldelay = 100,
137 },
138 {
139 .cmd = SHT3X_BREAK,
140 .typicaldelay = 100,
141 },
142 {
143 .cmd = SHT3X_CLEAR_STATUS_REGISTER,
144 .typicaldelay = 100,
145 },
146 {
147 .cmd = SHT3X_MEASURE_REPEATABILITY_CS_HIGH,
148 .typicaldelay = 15000,
149 },
150 {
151 .cmd = SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM,
152 .typicaldelay = 6000,
153 },
154 {
155 .cmd = SHT3X_MEASURE_REPEATABILITY_CS_LOW,
156 .typicaldelay = 4000,
157 },
158 {
159 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH,
160 .typicaldelay = 15000,
161 },
162 {
163 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM,
164 .typicaldelay = 6000,
165 },
166 {
167 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW,
168 .typicaldelay = 4000,
169 },
170 {
171 .cmd = SHT3X_WRITE_HIGH_ALERT_SET,
172 .typicaldelay = 5000,
173 },
174 {
175 .cmd = SHT3X_WRITE_HIGH_ALERT_CLEAR,
176 .typicaldelay = 5000,
177 },
178 {
179 .cmd = SHT3X_WRITE_LOW_ALERT_SET,
180 .typicaldelay = 5000,
181 },
182 {
183 .cmd = SHT3X_WRITE_LOW_ALERT_CLEAR,
184 .typicaldelay = 5000,
185 }
186 };
187
188 /* In single shot mode, find the command */
189
190 static struct sht3x_repeatability sht3x_repeatability_ss[] = {
191 {
192 .text = "high",
193 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH,
194 },
195 {
196 .text = "medium",
197 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM,
198 },
199 {
200 .text = "low",
201 .cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW,
202 }
203 };
204
205
206 /* For periodic, look at the repeatability and the rate.
207 * ART is a bit fake here, as the repeatability is not really
208 * used.
209 */
210
211 static struct sht3x_periodic sht3x_periodic_rate[] = {
212 {
213 .repeatability = "high",
214 .rate = "0.5mps",
215 .sdelay = 1000,
216 .cmd = SHT3X_HALF_MPS_HIGH,
217 },
218 {
219 .repeatability = "medium",
220 .rate = "0.5mps",
221 .sdelay = 1000,
222 .cmd = SHT3X_HALF_MPS_MEDIUM,
223 },
224 {
225 .repeatability = "low",
226 .rate = "0.5mps",
227 .sdelay = 1000,
228 .cmd = SHT3X_HALF_MPS_LOW,
229 },
230 {
231 .repeatability = "high",
232 .rate = "1.0mps",
233 .sdelay = 500,
234 .cmd = SHT3X_ONE_MPS_HIGH,
235 },
236 {
237 .repeatability = "medium",
238 .rate = "1.0mps",
239 .sdelay = 500,
240 .cmd = SHT3X_ONE_MPS_MEDIUM,
241 },
242 {
243 .repeatability = "low",
244 .rate = "1.0mps",
245 .sdelay = 500,
246 .cmd = SHT3X_ONE_MPS_LOW,
247 },
248 {
249 .repeatability = "high",
250 .rate = "2.0mps",
251 .sdelay = 250,
252 .cmd = SHT3X_TWO_MPS_HIGH,
253 },
254 {
255 .repeatability = "medium",
256 .rate = "2.0mps",
257 .sdelay = 250,
258 .cmd = SHT3X_TWO_MPS_MEDIUM,
259 },
260 {
261 .repeatability = "low",
262 .rate = "2.0mps",
263 .sdelay = 250,
264 .cmd = SHT3X_TWO_MPS_LOW,
265 },
266 {
267 .repeatability = "high",
268 .rate = "4.0mps",
269 .sdelay = 100,
270 .cmd = SHT3X_FOUR_MPS_HIGH,
271 },
272 {
273 .repeatability = "medium",
274 .rate = "4.0mps",
275 .sdelay = 100,
276 .cmd = SHT3X_FOUR_MPS_MEDIUM,
277 },
278 {
279 .repeatability = "low",
280 .rate = "4.0mps",
281 .sdelay = 100,
282 .cmd = SHT3X_FOUR_MPS_LOW,
283 },
284 {
285 .repeatability = "high",
286 .rate = "10.0mps",
287 .sdelay = 50,
288 .cmd = SHT3X_TEN_MPS_HIGH,
289 },
290 {
291 .repeatability = "medium",
292 .rate = "10.0mps",
293 .sdelay = 50,
294 .cmd = SHT3X_FOUR_MPS_MEDIUM,
295 },
296 {
297 .repeatability = "low",
298 .rate = "10.0mps",
299 .sdelay = 50,
300 .cmd = SHT3X_FOUR_MPS_LOW,
301 },
302 {
303 .repeatability = "high",
304 .rate = "ART",
305 .sdelay = 100,
306 .cmd = SHT3X_ART_ENABLE,
307 },
308 {
309 .repeatability = "medium",
310 .rate = "ART",
311 .sdelay = 100,
312 .cmd = SHT3X_ART_ENABLE,
313 },
314 {
315 .repeatability = "low",
316 .rate = "ART",
317 .sdelay = 100,
318 .cmd = SHT3X_ART_ENABLE,
319 }
320 };
321
322 static const char sht3x_rate_names[] =
323 "0.5mps, 1.0mps, 2.0mps, 4.0mps, 10.0mps, ART";
324
325 static const char sht3x_mode_names[] =
326 "single-shot, periodic";
327
328 static const char sht3x_repeatability_names[] =
329 "high, medium, low";
330
331 static int
332 sht3x_take_break(void *aux, bool have_bus)
333 {
334 struct sht3x_sc *sc;
335 sc = aux;
336 int error = 0;
337
338 if (! have_bus) {
339 error = iic_acquire_bus(sc->sc_tag, 0);
340 if (error) {
341 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for breaking %d\n",
342 device_xname(sc->sc_dev), error));
343 goto out;
344 }
345 }
346 error = sht3x_cmdr(sc, SHT3X_BREAK, NULL, 0);
347 if (error) {
348 DPRINTF(sc, 2, ("%s: Error breaking: %d\n",
349 device_xname(sc->sc_dev), error));
350 }
351 out:
352 if (! have_bus) {
353 iic_release_bus(sc->sc_tag, 0);
354 }
355
356 sc->sc_isperiodic = false;
357 strlcpy(sc->sc_mode,"single-shot",SHT3X_MODE_NAME);
358
359 return error;
360 }
361
362 static int
363 sht3x_get_status_register(void *aux, uint16_t *reg, bool have_bus)
364 {
365 struct sht3x_sc *sc;
366 sc = aux;
367 uint8_t buf[3];
368 int error = 0;
369
370 if (! have_bus) {
371 error = iic_acquire_bus(sc->sc_tag, 0);
372 if (error) {
373 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for getting status %d\n",
374 device_xname(sc->sc_dev), error));
375 goto out;
376 }
377 }
378 error = sht3x_cmdr(sc, SHT3X_GET_STATUS_REGISTER, buf, 3);
379 if (error) {
380 DPRINTF(sc, 2, ("%s: Error getting status: %d\n",
381 device_xname(sc->sc_dev), error));
382 }
383 out:
384 if (! have_bus) {
385 iic_release_bus(sc->sc_tag, 0);
386 }
387
388 if (!error) {
389 uint8_t c;
390
391 c = sht3x_crc(&buf[0],2);
392 if (c == buf[2]) {
393 *reg = buf[0] << 8 | buf[1];
394 } else {
395 error = EINVAL;
396 }
397 }
398
399 return error;
400 }
401
402 static int
403 sht3x_clear_status_register(void *aux, bool have_bus)
404 {
405 struct sht3x_sc *sc;
406 sc = aux;
407 int error = 0;
408
409 if (! have_bus) {
410 error = iic_acquire_bus(sc->sc_tag, 0);
411 if (error) {
412 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for clearing status %d\n",
413 device_xname(sc->sc_dev), error));
414 goto out;
415 }
416 }
417 error = sht3x_cmdr(sc, SHT3X_CLEAR_STATUS_REGISTER, NULL, 0);
418 if (error) {
419 DPRINTF(sc, 2, ("%s: Error clear status register: %d\n",
420 device_xname(sc->sc_dev), error));
421 }
422 out:
423 if (! have_bus) {
424 iic_release_bus(sc->sc_tag, 0);
425 }
426
427 return error;
428 }
429
430 void
431 sht3x_thread(void *aux)
432 {
433 struct sht3x_sc *sc = aux;
434 int error, rv;
435 int sdelay = 100;
436
437 mutex_enter(&sc->sc_threadmutex);
438
439 while (!sc->sc_stopping && !sc->sc_dying) {
440 if (sc->sc_initperiodic) {
441 error = sht3x_init_periodic_measurement(sc,&sdelay);
442 if (error) {
443 DPRINTF(sc, 2, ("%s: Error initing periodic measurement "
444 "in thread: %d\n", device_xname(sc->sc_dev), error));
445 }
446 sc->sc_initperiodic = false;
447 }
448 rv = cv_timedwait(&sc->sc_condvar, &sc->sc_threadmutex,
449 mstohz(sdelay));
450 if (rv == EWOULDBLOCK && !sc->sc_stopping && !sc->sc_initperiodic && !sc->sc_dying) {
451 sht3x_take_periodic_measurement(sc);
452 }
453 }
454 mutex_exit(&sc->sc_threadmutex);
455 kthread_exit(0);
456 }
457
458 int
459 sht3x_init_periodic_measurement(void *aux, int *sdelay)
460 {
461 struct sht3x_sc *sc;
462 sc = aux;
463 int i,error = 0;
464 uint16_t r = 0;
465
466 for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) {
467 if (strncmp(sc->sc_repeatability,sht3x_periodic_rate[i].repeatability,SHT3X_REP_NAME) == 0 &&
468 strncmp(sc->sc_periodic_rate, sht3x_periodic_rate[i].rate,SHT3X_RATE_NAME) == 0) {
469 r = sht3x_periodic_rate[i].cmd;
470 *sdelay = sht3x_periodic_rate[i].sdelay;
471 break;
472 }
473 }
474
475 if (i == __arraycount(sht3x_periodic_rate)) {
476 error = 1;
477 *sdelay = 100;
478 }
479
480 DPRINTF(sc, 2, ("%s: Would init with: %x\n",
481 device_xname(sc->sc_dev), r));
482
483 if (error == 0) {
484 mutex_enter(&sc->sc_mutex);
485
486 error = iic_acquire_bus(sc->sc_tag, 0);
487 if (error) {
488 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: "
489 " %d\n", device_xname(sc->sc_dev), error));
490 } else {
491 error = sht3x_take_break(sc,true);
492 if (error) {
493 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: "
494 " %d\n", device_xname(sc->sc_dev), error));
495 }
496
497 error = sht3x_cmdr(sc, r, NULL, 0);
498 if (error) {
499 DPRINTF(sc, 2, ("%s: Error sending periodic measurement command: %d\n",
500 device_xname(sc->sc_dev), error));
501 }
502 iic_release_bus(sc->sc_tag, 0);
503 sc->sc_isperiodic = true;
504 strlcpy(sc->sc_mode,"periodic",SHT3X_MODE_NAME);
505 }
506 mutex_exit(&sc->sc_mutex);
507 }
508
509 return error;
510 }
511
512 static void
513 sht3x_take_periodic_measurement(void *aux)
514 {
515 struct sht3x_sc *sc;
516 sc = aux;
517 int error = 0, data_error = 0;
518 uint8_t rawbuf[6];
519 struct sht3x_read_q *pp;
520
521 mutex_enter(&sc->sc_mutex);
522 error = iic_acquire_bus(sc->sc_tag, 0);
523 if (error) {
524 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for getting "
525 "periodic data: %d\n", device_xname(sc->sc_dev), error));
526 } else {
527 uint16_t status_reg;
528
529 error = sht3x_get_status_register(sc, &status_reg, true);
530 if (error) {
531 DPRINTF(sc, 2, ("%s: Error getting status register periodic: %d\n",
532 device_xname(sc->sc_dev), error));
533 } else {
534 if (status_reg & SHT3X_RESET_DETECTED) {
535 aprint_error_dev(sc->sc_dev, "Reset detected in periodic mode. Heater may have been reset.\n");
536 delay(3000);
537 sht3x_take_break(sc,true);
538 sht3x_clear_status_register(sc, true);
539 sc->sc_heateron = status_reg & SHT3X_HEATER_STATUS;
540 sc->sc_initperiodic = true;
541 } else {
542 data_error = sht3x_cmdr(sc, SHT3X_PERIODIC_FETCH_DATA, rawbuf, 6);
543 /* EIO is actually expected if the poll interval is faster
544 * than the rate that the sensor is set to. Unfortunally,
545 * this will also mess with the ability to detect an actual problem
546 * with the sensor in periodic mode, so we do the best we can here.
547 */
548 if (data_error && data_error != EIO) {
549 DPRINTF(sc, 2, ("%s: Error sending periodic fetch command: %d\n",
550 device_xname(sc->sc_dev), data_error));
551 }
552 }
553 }
554 iic_release_bus(sc->sc_tag, 0);
555 /* If there was no errors from anything then the data should be
556 * valid.
557 */
558 if (!data_error && !error) {
559 DPRINTF(sc, 2, ("%s: Raw periodic: %x%x - %x -- %x%x - %x\n",
560 device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], rawbuf[2],
561 rawbuf[3], rawbuf[4], rawbuf[5]));
562 memcpy(sc->sc_pbuffer,rawbuf,6);
563
564 if (sc->sc_opened) {
565 mutex_enter(&sc->sc_read_mutex);
566 pp = pool_cache_get(sc->sc_readpool,PR_NOWAIT);
567 if (pp != NULL) {
568 memcpy(pp->measurement,rawbuf,6);
569 DPRINTF(sc, 4, ("%s: Queue insert\n",device_xname(sc->sc_dev)));
570 SIMPLEQ_INSERT_HEAD(&sc->sc_read_queue,pp,read_q);
571 } else {
572 aprint_error("Could not allocate memory for pool read\n");
573 }
574 cv_signal(&sc->sc_condreadready);
575 mutex_exit(&sc->sc_read_mutex);
576 }
577
578 } else {
579 /* We are only going to worry about errors when it was not related
580 * to actually getting data. That is a likely indicator of a problem
581 * with the sensor.
582 */
583 if (error) {
584 DPRINTF(sc, 2, ("%s: Raw periodic with error: %x%x - %x -- %x%x - %x -- %d\n",
585 device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], rawbuf[2],
586 rawbuf[3], rawbuf[4], rawbuf[5], error));
587 uint8_t bad[6] = "dedbef";
588 memcpy(sc->sc_pbuffer, bad, 6);
589 }
590 }
591
592 }
593 mutex_exit(&sc->sc_mutex);
594 }
595
596 static void
597 sht3x_stop_thread(void *aux)
598 {
599 struct sht3x_sc *sc;
600 sc = aux;
601
602 if (!sc->sc_isperiodic) {
603 return;
604 }
605
606 mutex_enter(&sc->sc_threadmutex);
607 sc->sc_stopping = true;
608 cv_signal(&sc->sc_condvar);
609 mutex_exit(&sc->sc_threadmutex);
610
611 /* wait for the thread to exit */
612 kthread_join(sc->sc_thread);
613
614 mutex_enter(&sc->sc_mutex);
615 sht3x_take_break(sc,false);
616 mutex_exit(&sc->sc_mutex);
617 }
618
619 static void
620 sht3x_start_thread(void *aux)
621 {
622 struct sht3x_sc *sc;
623 sc = aux;
624 int error;
625
626 error = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
627 sht3x_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev));
628 if (error) {
629 DPRINTF(sc, 2, ("%s: Unable to create measurement thread: %d\n",
630 device_xname(sc->sc_dev), error));
631 }
632 }
633
634 int
635 sht3x_verify_sysctl(SYSCTLFN_ARGS)
636 {
637 int error, t;
638 struct sysctlnode node;
639
640 node = *rnode;
641 t = *(int *)rnode->sysctl_data;
642 node.sysctl_data = &t;
643 error = sysctl_lookup(SYSCTLFN_CALL(&node));
644 if (error || newp == NULL)
645 return error;
646
647 if (t < 0)
648 return EINVAL;
649
650 *(int *)rnode->sysctl_data = t;
651
652 return 0;
653 }
654
655 int
656 sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS)
657 {
658 int error;
659 bool t;
660 struct sht3x_sc *sc;
661 struct sysctlnode node;
662
663 node = *rnode;
664 sc = node.sysctl_data;
665 t = sc->sc_heateron;
666 node.sysctl_data = &t;
667 error = sysctl_lookup(SYSCTLFN_CALL(&node));
668 if (error || newp == NULL)
669 return error;
670
671 sc->sc_heateron = t;
672 error = sht3x_set_heater(sc);
673
674 return error;
675 }
676
677 static int
678 sht3x_set_heater(struct sht3x_sc *sc)
679 {
680 int error = 0;
681 uint16_t cmd;
682
683 mutex_enter(&sc->sc_mutex);
684 error = iic_acquire_bus(sc->sc_tag, 0);
685 if (error) {
686 DPRINTF(sc, 2, ("%s:%s: Failed to acquire bus: %d\n",
687 device_xname(sc->sc_dev), __func__, error));
688 return error;
689 }
690
691 if (sc->sc_heateron) {
692 cmd = SHT3X_HEATER_ENABLE;
693 } else {
694 cmd = SHT3X_HEATER_DISABLE;
695 }
696
697 error = sht3x_cmdr(sc, cmd, NULL, 0);
698
699 iic_release_bus(sc->sc_tag,0);
700 mutex_exit(&sc->sc_mutex);
701
702 return error;
703 }
704
705 int
706 sht3x_verify_sysctl_modes(SYSCTLFN_ARGS)
707 {
708 char buf[SHT3X_MODE_NAME];
709 struct sht3x_sc *sc;
710 struct sysctlnode node;
711 int error = 0;
712 bool is_ss = false;
713 bool is_periodic = false;
714
715 node = *rnode;
716 sc = node.sysctl_data;
717 (void) memcpy(buf, sc->sc_mode, SHT3X_MODE_NAME);
718 node.sysctl_data = buf;
719 error = sysctl_lookup(SYSCTLFN_CALL(&node));
720 if (error || newp == NULL)
721 return error;
722
723 if (sc->sc_opened) {
724 return EINVAL;
725 }
726
727 is_ss = (strncmp(node.sysctl_data, "single-shot", SHT3X_MODE_NAME) == 0);
728 is_periodic = (strncmp(node.sysctl_data, "periodic", SHT3X_MODE_NAME) == 0);
729
730 if (is_ss || is_periodic) {
731 (void) memcpy(sc->sc_mode, node.sysctl_data, SHT3X_MODE_NAME);
732 } else {
733 error = EINVAL;
734 }
735
736 if (error == 0) {
737 if (is_ss) {
738 sht3x_stop_thread(sc);
739 sc->sc_stopping = false;
740 sc->sc_initperiodic = false;
741 sc->sc_isperiodic = false;
742 }
743 if (is_periodic) {
744 sc->sc_stopping = false;
745 sc->sc_initperiodic = true;
746 sc->sc_isperiodic = true;
747 sht3x_start_thread(sc);
748 }
749 }
750
751 return error;
752 }
753
754 int
755 sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS)
756 {
757 char buf[SHT3X_REP_NAME];
758 struct sht3x_sc *sc;
759 struct sysctlnode node;
760 int error = 0;
761 size_t i;
762
763 node = *rnode;
764 sc = node.sysctl_data;
765 (void) memcpy(buf, sc->sc_repeatability, SHT3X_REP_NAME);
766 node.sysctl_data = buf;
767 error = sysctl_lookup(SYSCTLFN_CALL(&node));
768 if (error || newp == NULL)
769 return error;
770
771 for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) {
772 if (strncmp(node.sysctl_data, sht3x_repeatability_ss[i].text,
773 SHT3X_REP_NAME) == 0) {
774 break;
775 }
776 }
777
778 if (i == __arraycount(sht3x_repeatability_ss))
779 return EINVAL;
780 (void) memcpy(sc->sc_repeatability, node.sysctl_data, SHT3X_REP_NAME);
781
782 if (sc->sc_isperiodic) {
783 sc->sc_initperiodic = true;
784 }
785
786 return error;
787 }
788
789 int
790 sht3x_verify_sysctl_rate(SYSCTLFN_ARGS)
791 {
792 char buf[SHT3X_RATE_NAME];
793 struct sht3x_sc *sc;
794 struct sysctlnode node;
795 int error = 0;
796 size_t i;
797
798 node = *rnode;
799 sc = node.sysctl_data;
800 (void) memcpy(buf, sc->sc_periodic_rate, SHT3X_RATE_NAME);
801 node.sysctl_data = buf;
802 error = sysctl_lookup(SYSCTLFN_CALL(&node));
803 if (error || newp == NULL)
804 return error;
805
806 for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) {
807 if (strncmp(node.sysctl_data, sht3x_periodic_rate[i].rate,
808 SHT3X_RATE_NAME) == 0) {
809 break;
810 }
811 }
812
813 if (i == __arraycount(sht3x_periodic_rate))
814 return EINVAL;
815 (void) memcpy(sc->sc_periodic_rate, node.sysctl_data, SHT3X_RATE_NAME);
816
817 if (sc->sc_isperiodic) {
818 sc->sc_initperiodic = true;
819 }
820
821 return error;
822 }
823
824 static int
825 sht3x_cmddelay(uint16_t cmd)
826 {
827 int r = -2;
828
829 for(int i = 0;i < __arraycount(sht3x_timings);i++) {
830 if (cmd == sht3x_timings[i].cmd) {
831 r = sht3x_timings[i].typicaldelay;
832 break;
833 }
834 }
835
836 if (r == -2) {
837 r = -1;
838 }
839
840 return r;
841 }
842
843 static int
844 sht3x_cmd(i2c_tag_t tag, i2c_addr_t addr, uint16_t *cmd,
845 uint8_t clen, uint8_t *buf, size_t blen, int readattempts)
846 {
847 int error;
848 int cmddelay;
849 uint8_t cmd8[2];
850
851 /* All commands are two bytes and must be in a proper order */
852 KASSERT(clen == 2);
853
854 cmd8[0] = cmd[0] >> 8;
855 cmd8[1] = cmd[0] & 0x00ff;
856
857 error = iic_exec(tag,I2C_OP_WRITE_WITH_STOP,addr,&cmd8[0],clen,NULL,0,0);
858
859 if (error == 0) {
860 cmddelay = sht3x_cmddelay(cmd[0]);
861 if (cmddelay != -1) {
862 delay(cmddelay);
863 }
864
865 /* Not all commands return anything */
866 if (blen > 0) {
867 for (int aint = 0; aint < readattempts; aint++) {
868 error = iic_exec(tag,I2C_OP_READ_WITH_STOP,addr,NULL,0,buf,blen,0);
869 if (error == 0)
870 break;
871 delay(1000);
872 }
873 }
874 }
875
876 return error;
877 }
878
879 static int
880 sht3x_cmdr(struct sht3x_sc *sc, uint16_t cmd, uint8_t *buf, size_t blen)
881 {
882 return sht3x_cmd(sc->sc_tag, sc->sc_addr, &cmd, 2, buf, blen, sc->sc_readattempts);
883 }
884
885 static uint8_t
886 sht3x_crc(uint8_t * data, size_t size)
887 {
888 uint8_t crc = 0xFF;
889
890 for (size_t i = 0; i < size; i++) {
891 crc ^= data[i];
892 for (size_t j = 8; j > 0; j--) {
893 if (crc & 0x80)
894 crc = (crc << 1) ^ 0x31;
895 else
896 crc <<= 1;
897 }
898 }
899 return crc;
900 }
901
902 static int
903 sht3x_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug)
904 {
905 uint16_t reg = SHT3X_GET_STATUS_REGISTER;
906 uint8_t buf[3];
907 int error;
908
909 error = sht3x_cmd(tag, addr, ®, 2, buf, 3, 10);
910 if (matchdebug) {
911 printf("poke X 1: %d\n", error);
912 }
913 return error;
914 }
915
916 static int
917 sht3x_sysctl_init(struct sht3x_sc *sc)
918 {
919 int error;
920 const struct sysctlnode *cnode;
921 int sysctlroot_num;
922
923 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
924 0, CTLTYPE_NODE, device_xname(sc->sc_dev),
925 SYSCTL_DESCR("sht3x controls"), NULL, 0, NULL, 0, CTL_HW,
926 CTL_CREATE, CTL_EOL)) != 0)
927 return error;
928
929 sysctlroot_num = cnode->sysctl_num;
930
931 #ifdef SHT3X_DEBUG
932 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
933 CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
934 SYSCTL_DESCR("Debug level"), sht3x_verify_sysctl, 0,
935 &sc->sc_sht3xdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
936 CTL_EOL)) != 0)
937 return error;
938
939 #endif
940
941 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
942 CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts",
943 SYSCTL_DESCR("The number of times to attempt to read the values"),
944 sht3x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW,
945 sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
946 return error;
947
948 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
949 CTLFLAG_READONLY, CTLTYPE_STRING, "modes",
950 SYSCTL_DESCR("Valid modes"), 0, 0,
951 __UNCONST(sht3x_mode_names),
952 sizeof(sht3x_mode_names) + 1,
953 CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
954 return error;
955
956 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
957 CTLFLAG_READWRITE, CTLTYPE_STRING, "mode",
958 SYSCTL_DESCR("Mode for measurement collection"),
959 sht3x_verify_sysctl_modes, 0, (void *) sc,
960 SHT3X_MODE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
961 return error;
962
963 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
964 CTLFLAG_READONLY, CTLTYPE_STRING, "repeatabilities",
965 SYSCTL_DESCR("Valid repeatability values"), 0, 0,
966 __UNCONST(sht3x_repeatability_names),
967 sizeof(sht3x_repeatability_names) + 1,
968 CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
969 return error;
970
971 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
972 CTLFLAG_READWRITE, CTLTYPE_STRING, "repeatability",
973 SYSCTL_DESCR("Repeatability of RH and Temp"),
974 sht3x_verify_sysctl_repeatability, 0, (void *) sc,
975 SHT3X_REP_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
976 return error;
977
978 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
979 CTLFLAG_READONLY, CTLTYPE_STRING, "rates",
980 SYSCTL_DESCR("Valid peridoic rates"), 0, 0,
981 __UNCONST(sht3x_rate_names),
982 sizeof(sht3x_rate_names) + 1,
983 CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
984 return error;
985
986 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
987 CTLFLAG_READWRITE, CTLTYPE_STRING, "rate",
988 SYSCTL_DESCR("Rate for periodic measurements"),
989 sht3x_verify_sysctl_rate, 0, (void *) sc,
990 SHT3X_RATE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
991 return error;
992
993 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
994 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc",
995 SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc,
996 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
997 return error;
998
999 if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
1000 CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron",
1001 SYSCTL_DESCR("Heater on"), sht3x_verify_sysctl_heateron, 0,
1002 (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
1003 return error;
1004
1005 return 0;
1006 }
1007
1008 static int
1009 sht3x_match(device_t parent, cfdata_t match, void *aux)
1010 {
1011 struct i2c_attach_args *ia = aux;
1012 int error, match_result;
1013 const bool matchdebug = false;
1014
1015 if (iic_use_direct_match(ia, match, NULL, &match_result))
1016 return match_result;
1017
1018 if (matchdebug) {
1019 printf("Looking at ia_addr: %x\n",ia->ia_addr);
1020 }
1021
1022 /* indirect config - check for configured address */
1023 if (ia->ia_addr == SHT3X_TYPICAL_ADDR_1 ||
1024 ia->ia_addr == SHT3X_TYPICAL_ADDR_2) {
1025 /*
1026 * Check to see if something is really at this i2c address. This will
1027 * keep phantom devices from appearing
1028 */
1029 if (iic_acquire_bus(ia->ia_tag, 0) != 0) {
1030 if (matchdebug)
1031 printf("in match acquire bus failed\n");
1032 return 0;
1033 }
1034
1035 error = sht3x_poke(ia->ia_tag, ia->ia_addr, matchdebug);
1036 iic_release_bus(ia->ia_tag, 0);
1037
1038 return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0;
1039 } else {
1040 return 0;
1041 }
1042 }
1043
1044 static void
1045 sht3x_attach(device_t parent, device_t self, void *aux)
1046 {
1047 struct sht3x_sc *sc;
1048 struct i2c_attach_args *ia;
1049 int error, i;
1050 int ecount = 0;
1051 uint8_t buf[6];
1052 uint32_t serialnumber;
1053 uint8_t sncrcpt1, sncrcpt2;
1054
1055 ia = aux;
1056 sc = device_private(self);
1057
1058 sc->sc_dev = self;
1059 sc->sc_tag = ia->ia_tag;
1060 sc->sc_addr = ia->ia_addr;
1061 sc->sc_sht3xdebug = 0;
1062 strlcpy(sc->sc_mode,"single-shot",SHT3X_MODE_NAME);
1063 sc->sc_isperiodic = false;
1064 strlcpy(sc->sc_repeatability,"high",SHT3X_REP_NAME);
1065 strlcpy(sc->sc_periodic_rate,"1.0mps",SHT3X_RATE_NAME);
1066 sc->sc_readattempts = 10;
1067 sc->sc_ignorecrc = false;
1068 sc->sc_heateron = false;
1069 sc->sc_sme = NULL;
1070 sc->sc_stopping = false;
1071 sc->sc_initperiodic = false;
1072 sc->sc_opened = false;
1073 sc->sc_dying = false;
1074 sc->sc_readpoolname = NULL;
1075
1076 aprint_normal("\n");
1077
1078 mutex_init(&sc->sc_dying_mutex, MUTEX_DEFAULT, IPL_NONE);
1079 mutex_init(&sc->sc_read_mutex, MUTEX_DEFAULT, IPL_NONE);
1080 mutex_init(&sc->sc_threadmutex, MUTEX_DEFAULT, IPL_NONE);
1081 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
1082 cv_init(&sc->sc_condvar, "sht3xcv");
1083 cv_init(&sc->sc_condreadready, "sht3xread");
1084 cv_init(&sc->sc_cond_dying, "sht3xdie");
1085 sc->sc_numsensors = __arraycount(sht3x_sensors);
1086
1087 if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
1088 aprint_error_dev(self,
1089 "Unable to create sysmon structure\n");
1090 sc->sc_sme = NULL;
1091 return;
1092 }
1093 if ((error = sht3x_sysctl_init(sc)) != 0) {
1094 aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error);
1095 goto out;
1096 }
1097
1098 sc->sc_readpoolname = kmem_asprintf("sht3xrp%d",device_unit(self));
1099 sc->sc_readpool = pool_cache_init(sizeof(struct sht3x_read_q),0,0,0,sc->sc_readpoolname,NULL,IPL_VM,NULL,NULL,NULL);
1100 pool_cache_sethiwat(sc->sc_readpool,100);
1101
1102 SIMPLEQ_INIT(&sc->sc_read_queue);
1103
1104 error = iic_acquire_bus(sc->sc_tag, 0);
1105 if (error) {
1106 aprint_error_dev(self, "Could not acquire iic bus: %d\n",
1107 error);
1108 goto out;
1109 }
1110
1111 error = sht3x_cmdr(sc, SHT3X_SOFT_RESET, NULL, 0);
1112 if (error != 0)
1113 aprint_error_dev(self, "Reset failed: %d\n", error);
1114
1115 error = sht3x_clear_status_register(sc, true);
1116 if (error) {
1117 aprint_error_dev(self, "Failed to clear status register: %d\n",
1118 error);
1119 ecount++;
1120 }
1121
1122 uint16_t status_reg;
1123 error = sht3x_get_status_register(sc, &status_reg, true);
1124 if (error) {
1125 aprint_error_dev(self, "Failed to read status register: %d\n",
1126 error);
1127 ecount++;
1128 }
1129
1130 DPRINTF(sc, 2, ("%s: read status register values: %04x\n",
1131 device_xname(sc->sc_dev), status_reg));
1132
1133 error = sht3x_cmdr(sc, SHT3X_READ_SERIAL_NUMBER, buf, 6);
1134 if (error) {
1135 aprint_error_dev(self, "Failed to read serial number: %d\n",
1136 error);
1137 ecount++;
1138 }
1139
1140 sncrcpt1 = sht3x_crc(&buf[0],2);
1141 sncrcpt2 = sht3x_crc(&buf[3],2);
1142 serialnumber = (buf[0] << 24) | (buf[1] << 16) | (buf[3] << 8) | buf[4];
1143
1144 DPRINTF(sc, 2, ("%s: read serial number values: %02x%02x - %02x - %02x%02x - %02x -- %02x %02x\n",
1145 device_xname(sc->sc_dev), buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], sncrcpt1, sncrcpt2));
1146
1147 iic_release_bus(sc->sc_tag, 0);
1148 if (error != 0) {
1149 aprint_error_dev(self, "Unable to setup device\n");
1150 goto out;
1151 }
1152
1153 for (i = 0; i < sc->sc_numsensors; i++) {
1154 strlcpy(sc->sc_sensors[i].desc, sht3x_sensors[i].desc,
1155 sizeof(sc->sc_sensors[i].desc));
1156
1157 sc->sc_sensors[i].units = sht3x_sensors[i].type;
1158 sc->sc_sensors[i].state = ENVSYS_SINVALID;
1159 #ifdef __did_not_work
1160 sc->sc_sensors[i].flags |= ENVSYS_FMONLIMITS;
1161 #endif
1162
1163 DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i,
1164 sc->sc_sensors[i].desc));
1165
1166 error = sysmon_envsys_sensor_attach(sc->sc_sme,
1167 &sc->sc_sensors[i]);
1168 if (error) {
1169 aprint_error_dev(self,
1170 "Unable to attach sensor %d: %d\n", i, error);
1171 goto out;
1172 }
1173 }
1174
1175 sc->sc_sme->sme_name = device_xname(sc->sc_dev);
1176 sc->sc_sme->sme_cookie = sc;
1177 sc->sc_sme->sme_refresh = sht3x_refresh;
1178 #ifdef __did_not_work
1179 sc->sc_sme->sme_get_limits = sht3x_get_limits;
1180 sc->sc_sme->sme_set_limits = sht3x_set_limits;
1181 #endif
1182
1183 DPRINTF(sc, 2, ("sht3x_attach: registering with envsys\n"));
1184
1185 if (sysmon_envsys_register(sc->sc_sme)) {
1186 aprint_error_dev(self,
1187 "unable to register with sysmon\n");
1188 sysmon_envsys_destroy(sc->sc_sme);
1189 sc->sc_sme = NULL;
1190 return;
1191 }
1192
1193 /* There is no documented way to ask the chip what version it is. This
1194 is likely fine as the only apparent difference is in how precise the
1195 measurements will be. The actual conversation with the chip is
1196 identical no matter which one you are talking to.
1197 */
1198
1199 aprint_normal_dev(self, "Sensirion SHT30/SHT31/SHT35, "
1200 "Serial number: %x%s",
1201 serialnumber,
1202 (sncrcpt1 == buf[2] && sncrcpt2 == buf[5]) ? "\n" : " (bad crc)\n");
1203 return;
1204 out:
1205 sysmon_envsys_destroy(sc->sc_sme);
1206 sc->sc_sme = NULL;
1207 }
1208
1209 static uint16_t
1210 sht3x_compute_measure_command_ss(char *repeatability)
1211 {
1212 int i;
1213 uint16_t r;
1214
1215 for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) {
1216 if (strncmp(repeatability, sht3x_repeatability_ss[i].text,
1217 SHT3X_REP_NAME) == 0) {
1218 r = sht3x_repeatability_ss[i].cmd;
1219 break;
1220 }
1221 }
1222
1223 if (i == __arraycount(sht3x_repeatability_ss))
1224 panic("Single-shot could not find command for repeatability: %s\n", repeatability);
1225
1226 return r;
1227 }
1228
1229 /*
1230 The documented conversion calculations for the raw values are as follows:
1231
1232 %RH = (-6 + 125 * rawvalue / 65535)
1233
1234 T in Celsius = (-45 + 175 * rawvalue / 65535)
1235
1236 It follows then:
1237
1238 T in Kelvin = (228.15 + 175 * rawvalue / 65535)
1239
1240 given the relationship between Celsius and Kelvin
1241
1242 What follows reorders the calculation a bit and scales it up to avoid
1243 the use of any floating point. All that would really have to happen
1244 is a scale up to 10^6 for the sysenv framework, which wants
1245 temperature in micro-kelvin and percent relative humidity scaled up
1246 10^6, but since this conversion uses 64 bits due to intermediate
1247 values that are bigger than 32 bits the conversion first scales up to
1248 10^9 and the scales back down by 10^3 at the end. This preserves some
1249 precision in the conversion that would otherwise be lost.
1250 */
1251
1252 static uint64_t
1253 sht3x_compute_temp_from_raw(uint8_t msb, uint8_t lsb) {
1254 uint64_t svalue;
1255 int64_t v1;
1256 uint64_t v2;
1257 uint64_t d1 = 65535;
1258 uint64_t mul1;
1259 uint64_t mul2;
1260 uint64_t div1 = 10000;
1261 uint64_t q;
1262
1263 svalue = msb << 8 | lsb;
1264
1265 v1 = 22815; /* this is scaled up already from 228.15 */
1266 v2 = 175;
1267 mul1 = 10000000000;
1268 mul2 = 100000000;
1269
1270 svalue = svalue * mul1;
1271 v1 = v1 * mul2;
1272 /* Perform the conversion */
1273 q = ((v2 * (svalue / d1)) + v1) / div1;
1274
1275 return q;
1276 }
1277
1278 static uint64_t
1279 sht3x_compute_rh_from_raw(uint8_t msb, uint8_t lsb) {
1280 uint64_t svalue;
1281 int64_t v1;
1282 uint64_t v2;
1283 uint64_t d1 = 65535;
1284 uint64_t mul1;
1285 uint64_t mul2;
1286 uint64_t div1 = 10000;
1287 uint64_t q;
1288
1289 svalue = msb << 8 | lsb;
1290
1291 v1 = 0;
1292 v2 = 100;
1293 mul1 = 10000000000;
1294 mul2 = 10000000000;
1295
1296 svalue = svalue * mul1;
1297 v1 = v1 * mul2;
1298 /* Perform the conversion */
1299 q = ((v2 * (svalue / d1)) + v1) / div1;
1300
1301 return q;
1302 }
1303
1304 /* These are the the same as above except solved for the raw tick rather than
1305 * temperature or humidity. These are needed for setting the alert limits, but
1306 * since that did not work, disable these too for now.
1307 */
1308 #ifdef __did_not_work
1309 static uint16_t
1310 sht3x_compute_raw_from_temp(uint32_t temp)
1311 {
1312 uint64_t i1;
1313 uint32_t tempc;
1314
1315 tempc = temp - 272150000;
1316 tempc = tempc / 1000000;
1317
1318 i1 = (13107 * tempc) + 589815;
1319 return (uint16_t)(i1 / 35);
1320 }
1321
1322 static uint16_t
1323 sht3x_compute_raw_from_rh(uint32_t mrh)
1324 {
1325 uint64_t i1;
1326 uint32_t rh;
1327
1328 rh = mrh / 1000000;
1329
1330 i1 = 13107 * rh;
1331 return (uint16_t)(i1 / 20);
1332 }
1333 #endif
1334
1335 static void
1336 sht3x_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
1337 {
1338 struct sht3x_sc *sc;
1339 sc = sme->sme_cookie;
1340 int error;
1341 uint8_t rawdata[6];
1342 uint16_t measurement_command_ss;
1343 uint64_t current_value;
1344 uint8_t *svalptr;
1345
1346 edata->state = ENVSYS_SINVALID;
1347
1348 mutex_enter(&sc->sc_mutex);
1349
1350 if (!sc->sc_isperiodic) {
1351 error = iic_acquire_bus(sc->sc_tag, 0);
1352 if (error) {
1353 DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
1354 device_xname(sc->sc_dev), error));
1355 goto out;
1356 }
1357
1358 measurement_command_ss = sht3x_compute_measure_command_ss(sc->sc_repeatability);
1359 DPRINTF(sc, 2, ("%s: Measurement command: %04x\n",
1360 device_xname(sc->sc_dev), measurement_command_ss));
1361 error = sht3x_cmdr(sc,measurement_command_ss,rawdata,6);
1362 if (error == 0) {
1363 DPRINTF(sc, 2, ("%s: Raw data ss: %02x%02x %02x - %02x%02x %02x\n",
1364 device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2],
1365 rawdata[3], rawdata[4], rawdata[5]));
1366 switch (edata->sensor) {
1367 case SHT3X_TEMP_SENSOR:
1368 svalptr = &rawdata[0];
1369 current_value = sht3x_compute_temp_from_raw(rawdata[0],rawdata[1]);
1370 break;
1371 case SHT3X_HUMIDITY_SENSOR:
1372 svalptr = &rawdata[3];
1373 current_value = sht3x_compute_rh_from_raw(rawdata[3],rawdata[4]);
1374 break;
1375 default:
1376 error = EINTR;
1377 break;
1378 }
1379
1380 if (error == 0) {
1381 uint8_t testcrc;
1382
1383 /* Fake out the CRC check if being asked to ignore CRC */
1384 if (sc->sc_ignorecrc) {
1385 testcrc = *(svalptr + 2);
1386 } else {
1387 testcrc = sht3x_crc(svalptr,2);
1388 }
1389
1390 if (*(svalptr + 2) == testcrc) {
1391 edata->value_cur = (uint32_t) current_value;
1392 edata->state = ENVSYS_SVALID;
1393 } else {
1394 error = EINVAL;
1395 }
1396 }
1397 }
1398
1399 if (error) {
1400 DPRINTF(sc, 2, ("%s: Failed to get new status in refresh for single-shot %d\n",
1401 device_xname(sc->sc_dev), error));
1402 }
1403
1404 uint16_t sbuf;
1405 int status_error;
1406
1407 status_error = sht3x_get_status_register(sc, &sbuf, true);
1408
1409 if (!status_error) {
1410 DPRINTF(sc, 2, ("%s: read status register single-shot: %04x\n",
1411 device_xname(sc->sc_dev), sbuf));
1412
1413 if (sbuf & SHT3X_RESET_DETECTED) {
1414 aprint_error_dev(sc->sc_dev, "Reset detected in single shot mode. Heater may have been reset\n");
1415 sht3x_clear_status_register(sc, true);
1416 }
1417
1418 sc->sc_heateron = sbuf & SHT3X_HEATER_STATUS;
1419 }
1420
1421 iic_release_bus(sc->sc_tag, 0);
1422 } else {
1423 error = 0;
1424 memcpy(rawdata,sc->sc_pbuffer,6);
1425
1426 DPRINTF(sc, 2, ("%s: Raw data periodic: %02x%02x %02x - %02x%02x %02x\n",
1427 device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2],
1428 rawdata[3], rawdata[4], rawdata[5]));
1429
1430 switch (edata->sensor) {
1431 case SHT3X_TEMP_SENSOR:
1432 svalptr = &rawdata[0];
1433 current_value = sht3x_compute_temp_from_raw(rawdata[0],rawdata[1]);
1434 break;
1435 case SHT3X_HUMIDITY_SENSOR:
1436 svalptr = &rawdata[3];
1437 current_value = sht3x_compute_rh_from_raw(rawdata[3],rawdata[4]);
1438 break;
1439 default:
1440 error = EINTR;
1441 break;
1442 }
1443
1444 if (error == 0) {
1445 uint8_t testcrc;
1446
1447 /* Fake out the CRC check if being asked to ignore CRC */
1448 if (sc->sc_ignorecrc) {
1449 testcrc = *(svalptr + 2);
1450 } else {
1451 testcrc = sht3x_crc(svalptr,2);
1452 }
1453
1454 if (*(svalptr + 2) == testcrc) {
1455 edata->value_cur = (uint32_t) current_value;
1456 edata->state = ENVSYS_SVALID;
1457 } else {
1458 error = EINVAL;
1459 }
1460 }
1461
1462 if (error) {
1463 DPRINTF(sc, 2, ("%s: Failed to get new status in refresh for periodic %d\n",
1464 device_xname(sc->sc_dev), error));
1465 }
1466 }
1467 out:
1468 mutex_exit(&sc->sc_mutex);
1469 }
1470
1471 #ifdef __did_not_work
1472 static void
1473 sht3x_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1474 sysmon_envsys_lim_t *limits, uint32_t *props)
1475 {
1476 struct sht3x_sc *sc = sme->sme_cookie;
1477 uint16_t rawlimitshigh, rawlimitslow;
1478 uint16_t templimithigh, rhlimithigh,
1479 templimitlow, rhlimitlow;
1480 uint8_t templimithighmsb, templimithighlsb,
1481 templimitlowmsb, templimitlowlsb;
1482 uint8_t rhlimithighmsb, rhlimithighlsb,
1483 rhlimitlowmsb, rhlimitlowlsb;
1484 int error;
1485 uint8_t lbuf[3];
1486 uint8_t limitscrchigh, limitskcrchigh,
1487 limitscrclow, limitskcrclow;
1488
1489 *props = 0;
1490
1491 mutex_enter(&sc->sc_mutex);
1492 error = iic_acquire_bus(sc->sc_tag, 0);
1493 if (error) {
1494 DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
1495 device_xname(sc->sc_dev), error));
1496 goto out;
1497 }
1498
1499 error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3);
1500 if (error) {
1501 DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
1502 device_xname(sc->sc_dev), error));
1503 goto out;
1504 }
1505
1506 rawlimitshigh = (lbuf[0] << 8) | lbuf[1];
1507 limitskcrchigh = lbuf[2];
1508 limitscrchigh = sht3x_crc(&lbuf[0],2);
1509
1510 templimithigh = ((rawlimitshigh & 0x1FF) << 7);
1511 templimithighmsb = (uint8_t)(templimithigh >> 8);
1512 templimithighlsb = (uint8_t)(templimithigh & 0x00FF);
1513 DPRINTF(sc, 2, ("%s: Limits high intermediate temp: %04x %04x %02x %02x\n",
1514 device_xname(sc->sc_dev), rawlimitshigh, templimithigh, templimithighmsb,
1515 templimithighlsb));
1516
1517 rhlimithigh = (rawlimitshigh & 0xFE00);
1518 rhlimithighmsb = (uint8_t)(rhlimithigh >> 8);
1519 rhlimithighlsb = (uint8_t)(rhlimithigh & 0x00FF);
1520 DPRINTF(sc, 2, ("%s: Limits high intermediate rh: %04x %04x %02x %02x\n",
1521 device_xname(sc->sc_dev), rawlimitshigh, rhlimithigh, rhlimithighmsb,
1522 rhlimithighlsb));
1523
1524 DPRINTF(sc, 2, ("%s: Limit high raw: %02x%02x %02x %02x %02x\n",
1525 device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2],
1526 limitscrchigh, limitskcrchigh));
1527
1528 error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3);
1529 if (error) {
1530 DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
1531 device_xname(sc->sc_dev), error));
1532 goto out;
1533 }
1534
1535 rawlimitslow = (lbuf[0] << 8) | lbuf[1];
1536 limitskcrclow = lbuf[2];
1537 limitscrclow = sht3x_crc(&lbuf[0],2);
1538
1539 templimitlow = ((rawlimitslow & 0x1FF) << 7);
1540 templimitlowmsb = (uint8_t)(templimitlow >> 8);
1541 templimitlowlsb = (uint8_t)(templimitlow & 0x00FF);
1542 DPRINTF(sc, 2, ("%s: Limits low intermediate temp: %04x %04x %02x %02x\n",
1543 device_xname(sc->sc_dev), rawlimitslow, templimitlow, templimitlowmsb,
1544 templimitlowlsb));
1545
1546 rhlimitlow = (rawlimitslow & 0xFE00);
1547 rhlimitlowmsb = (uint8_t)(rhlimitlow >> 8);
1548 rhlimitlowlsb = (uint8_t)(rhlimitlow & 0x00FF);
1549 DPRINTF(sc, 2, ("%s: Limits low intermediate rh: %04x %04x %02x %02x\n",
1550 device_xname(sc->sc_dev), rawlimitslow, rhlimitlow, rhlimitlowmsb,
1551 rhlimitlowlsb));
1552
1553 DPRINTF(sc, 2, ("%s: Limit low raw: %02x%02x %02x %02x %02x\n",
1554 device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2],
1555 limitscrclow, limitskcrclow));
1556
1557
1558 switch (edata->sensor) {
1559 case SHT3X_TEMP_SENSOR:
1560 if (limitscrchigh == limitskcrchigh) {
1561 limits->sel_critmax = sht3x_compute_temp_from_raw(templimithighmsb, templimithighlsb);
1562 *props |= PROP_CRITMAX;
1563 }
1564 if (limitscrclow == limitskcrclow) {
1565 limits->sel_critmin = sht3x_compute_temp_from_raw(templimitlowmsb, templimitlowlsb);
1566 *props |= PROP_CRITMIN;
1567 }
1568 break;
1569 case SHT3X_HUMIDITY_SENSOR:
1570 if (limitscrchigh == limitskcrchigh) {
1571 limits->sel_critmax = sht3x_compute_rh_from_raw(rhlimithighmsb, rhlimithighlsb);
1572 *props |= PROP_CRITMAX;
1573 }
1574 if (limitscrclow == limitskcrclow) {
1575 limits->sel_critmin = sht3x_compute_rh_from_raw(rhlimitlowmsb, rhlimitlowlsb);
1576 *props |= PROP_CRITMIN;
1577 }
1578 break;
1579 default:
1580 break;
1581 }
1582
1583 if (*props != 0)
1584 *props |= PROP_DRIVER_LIMITS;
1585
1586 iic_release_bus(sc->sc_tag, 0);
1587 out:
1588 mutex_exit(&sc->sc_mutex);
1589 }
1590
1591 static void
1592 sht3x_set_alert_limits(void *aux, uint16_t high, uint16_t low, bool have_bus)
1593 {
1594 struct sht3x_sc *sc;
1595 sc = aux;
1596
1597 int error = 0;
1598 uint8_t hbuf[3];
1599 uint8_t lbuf[3];
1600
1601 if (! have_bus) {
1602 error = iic_acquire_bus(sc->sc_tag, 0);
1603 if (error) {
1604 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for setting alerts %d\n",
1605 device_xname(sc->sc_dev), error));
1606 goto out;
1607 }
1608 }
1609
1610 hbuf[0] = high >> 8;
1611 hbuf[1] = high & 0x00FF;
1612 hbuf[2] = sht3x_crc(&hbuf[0],2);
1613
1614 lbuf[0] = low >> 8;
1615 lbuf[1] = low & 0x00FF;
1616 lbuf[2] = sht3x_crc(&lbuf[0],2);
1617
1618 error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3);
1619 if (error) {
1620 DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n",
1621 device_xname(sc->sc_dev), error));
1622 goto out;
1623 }
1624 error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbuf, 3);
1625 if (error) {
1626 DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
1627 device_xname(sc->sc_dev), error));
1628 goto out;
1629 }
1630 error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3);
1631 if (error) {
1632 DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n",
1633 device_xname(sc->sc_dev), error));
1634 goto out;
1635 }
1636 error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbuf, 3);
1637 if (error) {
1638 DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
1639 device_xname(sc->sc_dev), error));
1640 }
1641
1642 out:
1643 if (! have_bus) {
1644 iic_release_bus(sc->sc_tag, 0);
1645 }
1646 }
1647
1648 static void
1649 sht3x_set_alert_limits2(void *aux, uint16_t high, uint16_t low,
1650 uint16_t highminusone, uint16_t lowplusone, bool have_bus)
1651 {
1652 struct sht3x_sc *sc;
1653 sc = aux;
1654
1655 int error = 0;
1656 uint8_t hbuf[3];
1657 uint8_t lbuf[3];
1658 uint8_t hbufminusone[3];
1659 uint8_t lbufplusone[3];
1660
1661 if (! have_bus) {
1662 error = iic_acquire_bus(sc->sc_tag, 0);
1663 if (error) {
1664 DPRINTF(sc, 2, ("%s: Could not acquire iic bus for setting alerts %d\n",
1665 device_xname(sc->sc_dev), error));
1666 goto out;
1667 }
1668 }
1669
1670 hbuf[0] = high >> 8;
1671 hbuf[1] = high & 0x00FF;
1672 hbuf[2] = sht3x_crc(&hbuf[0],2);
1673
1674 lbuf[0] = low >> 8;
1675 lbuf[1] = low & 0x00FF;
1676 lbuf[2] = sht3x_crc(&lbuf[0],2);
1677
1678 hbufminusone[0] = highminusone >> 8;
1679 hbufminusone[1] = highminusone & 0x00FF;
1680 hbufminusone[2] = sht3x_crc(&hbufminusone[0],2);
1681
1682 lbufplusone[0] = lowplusone >> 8;
1683 lbufplusone[1] = lowplusone & 0x00FF;
1684 lbufplusone[2] = sht3x_crc(&lbufplusone[0],2);
1685
1686 DPRINTF(sc, 2, ("%s: Physical SET HIGH %02x %02x %02x\n",
1687 device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2]));
1688 error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3);
1689 if (error) {
1690 DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n",
1691 device_xname(sc->sc_dev), error));
1692 goto out;
1693 }
1694
1695 uint16_t sbuf;
1696 int status_error;
1697 status_error = sht3x_get_status_register(sc, &sbuf, true);
1698 DPRINTF(sc, 2, ("%s: In SETTING, status register %04x -- %d\n",
1699 device_xname(sc->sc_dev), sbuf, status_error));
1700
1701 hbuf[0] = 0;
1702 hbuf[1] = 0;
1703 hbuf[2] = 0;
1704 error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, hbuf, 3);
1705 if (error) {
1706 DPRINTF(sc, 2, ("%s: Could not read high alert for SET %d\n",
1707 device_xname(sc->sc_dev), error));
1708 goto out;
1709 }
1710 DPRINTF(sc, 2, ("%s: Physical READBACK SET HIGH %02x %02x %02x\n",
1711 device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2]));
1712
1713 DPRINTF(sc, 2, ("%s: Physical CLEAR HIGH %02x %02x %02x\n",
1714 device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], hbufminusone[2]));
1715 error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbufminusone, 3);
1716 if (error) {
1717 DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
1718 device_xname(sc->sc_dev), error));
1719 goto out;
1720 }
1721 hbufminusone[0] = 0;
1722 hbufminusone[1] = 0;
1723 hbufminusone[2] = 0;
1724 error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, hbufminusone, 3);
1725 if (error) {
1726 DPRINTF(sc, 2, ("%s: Could not read high alert for CLEAR %d\n",
1727 device_xname(sc->sc_dev), error));
1728 goto out;
1729 }
1730 DPRINTF(sc, 2, ("%s: Physical READBACK CLEAR HIGH %02x %02x %02x\n",
1731 device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], hbufminusone[2]));
1732
1733 DPRINTF(sc, 2, ("%s: Physical SET LOW %02x %02x %02x\n",
1734 device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2]));
1735 error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3);
1736 if (error) {
1737 DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n",
1738 device_xname(sc->sc_dev), error));
1739 goto out;
1740 }
1741 DPRINTF(sc, 2, ("%s: Physical CLEAR LOW %02x %02x %02x\n",
1742 device_xname(sc->sc_dev), lbufplusone[0], lbufplusone[1], lbufplusone[2]));
1743 error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbufplusone, 3);
1744 if (error) {
1745 DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
1746 device_xname(sc->sc_dev), error));
1747 }
1748
1749 out:
1750 if (! have_bus) {
1751 iic_release_bus(sc->sc_tag, 0);
1752 }
1753 }
1754
1755 static void
1756 sht3x_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1757 sysmon_envsys_lim_t *limits, uint32_t *props)
1758 {
1759 struct sht3x_sc *sc = sme->sme_cookie;
1760 uint16_t rawlimitshigh, rawlimitslow;
1761 uint16_t rawlimitshighclear, rawlimitslowclear;
1762 uint16_t rawlimitshighminusone, rawlimitslowplusone;
1763 int error;
1764 uint8_t lbuf[3];
1765 uint8_t limitscrchigh, limitskcrchigh,
1766 limitscrclow, limitskcrclow;
1767 uint16_t limithigh, limitlow;
1768 uint16_t limithighminusone, limitlowplusone;
1769
1770 if (limits == NULL) {
1771 printf("XXX - Need to set back to default... limits is NULL\n");
1772 return;
1773 }
1774
1775 DPRINTF(sc, 2, ("%s: In set_limits - %d -- %d %d\n",
1776 device_xname(sc->sc_dev), edata->sensor,
1777 limits->sel_critmin, limits->sel_critmax));
1778
1779 mutex_enter(&sc->sc_mutex);
1780 error = iic_acquire_bus(sc->sc_tag, 0);
1781 if (error) {
1782 DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
1783 device_xname(sc->sc_dev), error));
1784 goto out;
1785 }
1786
1787 error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3);
1788 if (error) {
1789 DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
1790 device_xname(sc->sc_dev), error));
1791 goto out;
1792 }
1793
1794 rawlimitshigh = (lbuf[0] << 8) | lbuf[1];
1795 limitskcrchigh = lbuf[2];
1796 limitscrchigh = sht3x_crc(&lbuf[0],2);
1797
1798
1799 error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3);
1800 if (error) {
1801 DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
1802 device_xname(sc->sc_dev), error));
1803 goto out;
1804 }
1805
1806 rawlimitslow = (lbuf[0] << 8) | lbuf[1];
1807 limitskcrclow = lbuf[2];
1808 limitscrclow = sht3x_crc(&lbuf[0],2);
1809
1810 error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, lbuf, 3);
1811 if (error) {
1812 DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n",
1813 device_xname(sc->sc_dev), error));
1814 goto out;
1815 }
1816
1817 rawlimitshighclear = (lbuf[0] << 8) | lbuf[1];
1818
1819 error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_CLEAR, lbuf, 3);
1820 if (error) {
1821 DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n",
1822 device_xname(sc->sc_dev), error));
1823 goto out;
1824 }
1825
1826 rawlimitslowclear = (lbuf[0] << 8) | lbuf[1];
1827
1828 DPRINTF(sc, 2, ("%s: Set limits current raw limits %04x - %02x %02x ; %04x - %02x %02x ;; %04x %04x\n",
1829 device_xname(sc->sc_dev), rawlimitshigh, limitskcrchigh, limitscrchigh,
1830 rawlimitslow, limitskcrclow, limitscrclow, rawlimitshighclear, rawlimitslowclear));
1831
1832 switch (edata->sensor) {
1833 case SHT3X_TEMP_SENSOR:
1834 limithigh = sht3x_compute_raw_from_temp(limits->sel_critmax);
1835 limitlow = sht3x_compute_raw_from_temp(limits->sel_critmin);
1836 limithigh = limithigh >> 7;
1837 limithighminusone = limithigh - 1;
1838 limitlow = limitlow >> 7;
1839 limitlowplusone = limitlow + 1;
1840 rawlimitshigh = (rawlimitshigh & 0xFE00) | limithigh;
1841 rawlimitshighminusone = (rawlimitshigh & 0xFE00) | limithighminusone;
1842 rawlimitslow = (rawlimitslow & 0xFE00) | limitlow;
1843 rawlimitslowplusone = (rawlimitslow & 0xFE00) | limitlowplusone;
1844 DPRINTF(sc, 2, ("%s: Temp new raw limits high/low %04x %04x %04x %04x\n",
1845 device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow,
1846 rawlimitshighminusone, rawlimitslowplusone));
1847 sht3x_set_alert_limits2(sc, rawlimitshigh, rawlimitslow,
1848 rawlimitshighminusone, rawlimitslowplusone, true);
1849 break;
1850 case SHT3X_HUMIDITY_SENSOR:
1851 limithigh = sht3x_compute_raw_from_rh(limits->sel_critmax);
1852 limitlow = sht3x_compute_raw_from_rh(limits->sel_critmin);
1853 limithigh = limithigh & 0xFE00;
1854 limitlow = limitlow & 0xFE00;
1855 rawlimitshigh = (rawlimitshigh & 0x1FF) | limithigh;
1856 rawlimitslow = (rawlimitslow & 0x1FF) | limitlow;
1857 DPRINTF(sc, 2, ("%s: RH new raw limits high/low %04x %04x from %x %x\n",
1858 device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow, limithigh, limitlow));
1859 sht3x_set_alert_limits(sc, rawlimitshigh, rawlimitslow, true);
1860 break;
1861 default:
1862 break;
1863 }
1864
1865 iic_release_bus(sc->sc_tag, 0);
1866 out:
1867 mutex_exit(&sc->sc_mutex);
1868 }
1869 #endif
1870
1871 static int
1872 sht3xopen(dev_t dev, int flags, int fmt, struct lwp *l)
1873 {
1874 struct sht3x_sc *sc;
1875
1876 sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
1877 if (!sc)
1878 return (ENXIO);
1879
1880 if (sc->sc_opened)
1881 return (EBUSY);
1882
1883 mutex_enter(&sc->sc_mutex);
1884 sc->sc_opened = true;
1885
1886 sc->sc_wassingleshot = false;
1887 if (!sc->sc_isperiodic) {
1888 sc->sc_stopping = false;
1889 sc->sc_initperiodic = true;
1890 sc->sc_isperiodic = true;
1891 sc->sc_wassingleshot = true;
1892 sht3x_start_thread(sc);
1893 }
1894 mutex_exit(&sc->sc_mutex);
1895
1896 return (0);
1897 }
1898
1899 static int
1900 sht3xread(dev_t dev, struct uio *uio, int flags)
1901 {
1902 struct sht3x_sc *sc;
1903 struct sht3x_read_q *pp;
1904 int error,any;
1905
1906 sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
1907 if (!sc)
1908 return (ENXIO);
1909
1910 while (uio->uio_resid) {
1911 any = 0;
1912 error = 0;
1913 mutex_enter(&sc->sc_read_mutex);
1914
1915 while (any == 0) {
1916 pp = SIMPLEQ_FIRST(&sc->sc_read_queue);
1917 if (pp != NULL) {
1918 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
1919 any = 1;
1920 break;
1921 } else {
1922 error = cv_wait_sig(&sc->sc_condreadready,&sc->sc_read_mutex);
1923 if (sc->sc_dying)
1924 error = EIO;
1925 if (error == 0)
1926 continue;
1927 break;
1928 }
1929 }
1930
1931 if (any == 1 && error == 0) {
1932 mutex_exit(&sc->sc_read_mutex);
1933 pool_cache_put(sc->sc_readpool,pp);
1934
1935 DPRINTF(sc,2, ("%s: sending %02x%02x %02x -- %02x%02x %02x -- %x\n",device_xname(sc->sc_dev),pp->measurement[0],pp->measurement[1],pp->measurement[2],pp->measurement[3],pp->measurement[4],pp->measurement[5],mutex_owned(&sc->sc_read_mutex)));
1936 if ((error = uiomove(&pp->measurement[0], 6, uio)) != 0) {
1937 DPRINTF(sc,2, ("%s: send error %d\n",device_xname(sc->sc_dev),error));
1938 break;
1939 }
1940 } else {
1941 mutex_exit(&sc->sc_read_mutex);
1942 if (error) {
1943 break;
1944 }
1945 }
1946 }
1947
1948 DPRINTF(sc,2, ("%s: loop done: %d\n",device_xname(sc->sc_dev),error));
1949 if (sc->sc_dying) {
1950 DPRINTF(sc, 2, ("%s: Telling all we are almost dead\n",
1951 device_xname(sc->sc_dev)));
1952 mutex_enter(&sc->sc_dying_mutex);
1953 cv_signal(&sc->sc_cond_dying);
1954 mutex_exit(&sc->sc_dying_mutex);
1955 }
1956 return error;
1957 }
1958
1959 static int
1960 sht3xclose(dev_t dev, int flags, int fmt, struct lwp *l)
1961 {
1962 struct sht3x_sc *sc;
1963 struct sht3x_read_q *pp;
1964
1965 sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
1966
1967 if (sc->sc_wassingleshot) {
1968 sht3x_stop_thread(sc);
1969 sc->sc_stopping = false;
1970 sc->sc_initperiodic = false;
1971 sc->sc_isperiodic = false;
1972 }
1973
1974 mutex_enter(&sc->sc_mutex);
1975 /* Drain any read pools */
1976 while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
1977 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
1978 pool_cache_put(sc->sc_readpool,pp);
1979 }
1980
1981 /* Say that the device is now free */
1982 sc->sc_opened = false;
1983 mutex_exit(&sc->sc_mutex);
1984
1985 return(0);
1986 }
1987
1988 static int
1989 sht3x_detach(device_t self, int flags)
1990 {
1991 struct sht3x_sc *sc;
1992 struct sht3x_read_q *pp;
1993
1994 sc = device_private(self);
1995
1996 if (sc->sc_isperiodic) {
1997 sht3x_stop_thread(sc);
1998 }
1999
2000 mutex_enter(&sc->sc_mutex);
2001
2002 sc->sc_dying = true;
2003
2004 /* If this is true we are still open, destroy the condvar */
2005 if (sc->sc_opened) {
2006 mutex_enter(&sc->sc_dying_mutex);
2007 mutex_enter(&sc->sc_read_mutex);
2008 cv_signal(&sc->sc_condreadready);
2009 mutex_exit(&sc->sc_read_mutex);
2010 DPRINTF(sc, 2, ("%s: Will wait for anything to exit\n",
2011 device_xname(sc->sc_dev)));
2012 cv_timedwait_sig(&sc->sc_cond_dying,&sc->sc_dying_mutex,mstohz(5000));
2013 mutex_exit(&sc->sc_dying_mutex);
2014 cv_destroy(&sc->sc_condreadready);
2015 cv_destroy(&sc->sc_cond_dying);
2016 }
2017
2018 /* Drain any read pools */
2019 while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
2020 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
2021 pool_cache_put(sc->sc_readpool,pp);
2022 }
2023
2024 /* Destroy the pool cache now that nothing is using it */
2025 pool_cache_destroy(sc->sc_readpool);
2026
2027 /* Remove the sensors */
2028 if (sc->sc_sme != NULL) {
2029 sysmon_envsys_unregister(sc->sc_sme);
2030 sc->sc_sme = NULL;
2031 }
2032 mutex_exit(&sc->sc_mutex);
2033
2034 /* Remove the sysctl tree */
2035 sysctl_teardown(&sc->sc_sht3xlog);
2036
2037 /* Remove the mutex */
2038 mutex_destroy(&sc->sc_mutex);
2039 mutex_destroy(&sc->sc_threadmutex);
2040 mutex_destroy(&sc->sc_read_mutex);
2041 mutex_destroy(&sc->sc_dying_mutex);
2042
2043 /* Free the poolname string */
2044 if (sc->sc_readpoolname != NULL) {
2045 kmem_free(sc->sc_readpoolname,strlen(sc->sc_readpoolname) + 1);
2046 }
2047
2048 return 0;
2049 }
2050
2051 int
2052 sht3x_activate(device_t self, enum devact act)
2053 {
2054 struct sht3x_sc *sc = device_private(self);
2055
2056 switch (act) {
2057 case DVACT_DEACTIVATE:
2058 sc->sc_dying = true;
2059 return 0;
2060 default:
2061 return EOPNOTSUPP;
2062 }
2063 }
2064
2065 MODULE(MODULE_CLASS_DRIVER, sht3xtemp, "i2cexec,sysmon_envsys");
2066
2067 #ifdef _MODULE
2068 #include "ioconf.c"
2069 #endif
2070
2071 static int
2072 sht3xtemp_modcmd(modcmd_t cmd, void *opaque)
2073 {
2074 int error;
2075 #ifdef _MODULE
2076 int bmaj = -1, cmaj = -1;
2077 #endif
2078
2079 switch (cmd) {
2080 case MODULE_CMD_INIT:
2081 #ifdef _MODULE
2082 error = config_init_component(cfdriver_ioconf_sht3xtemp,
2083 cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
2084 if (error)
2085 aprint_error("%s: unable to init component\n",
2086 sht3xtemp_cd.cd_name);
2087
2088 error = devsw_attach("sht3xtemp", NULL, &bmaj,
2089 &sht3x_cdevsw, &cmaj);
2090 if (error) {
2091 aprint_error("%s: unable to attach devsw\n",
2092 sht3xtemp_cd.cd_name);
2093 config_fini_component(cfdriver_ioconf_sht3xtemp,
2094 cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
2095 }
2096 return error;
2097 #else
2098 return 0;
2099 #endif
2100 case MODULE_CMD_FINI:
2101 #ifdef _MODULE
2102 devsw_detach(NULL, &sht3x_cdevsw);
2103 return config_fini_component(cfdriver_ioconf_sht3xtemp,
2104 cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
2105 #else
2106 return 0;
2107 #endif
2108 default:
2109 return ENOTTY;
2110 }
2111 }
2112