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