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