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