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