Module Name: src
Committed By: brad
Date: Sun Oct 3 17:27:02 UTC 2021
Modified Files:
src/distrib/sets/lists/man: mi
src/distrib/sets/lists/modules: mi
src/share/man/man4: Makefile
src/sys/dev/i2c: files.i2c
src/sys/modules: Makefile
Added Files:
src/share/man/man4: sht4xtemp.4
src/sys/dev/i2c: sht4x.c sht4xreg.h sht4xvar.h
src/sys/modules/sht4xtemp: Makefile sht4xtemp.ioconf
Log Message:
A driver for the Sensirion SHT40/SHT41/SHT45 temperature and humidity
sensor. An example of this chip is:
https://www.adafruit.com/product/4885
This is a lower cost chip that provides higher then usual precision
according to the data sheet. This driver supports all of the published
functions that the chip has.
To generate a diff of this commit:
cvs rdiff -u -r1.1725 -r1.1726 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.146 -r1.147 src/distrib/sets/lists/modules/mi
cvs rdiff -u -r1.715 -r1.716 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/sht4xtemp.4
cvs rdiff -u -r1.116 -r1.117 src/sys/dev/i2c/files.i2c
cvs rdiff -u -r0 -r1.1 src/sys/dev/i2c/sht4x.c src/sys/dev/i2c/sht4xreg.h \
src/sys/dev/i2c/sht4xvar.h
cvs rdiff -u -r1.256 -r1.257 src/sys/modules/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/modules/sht4xtemp/Makefile \
src/sys/modules/sht4xtemp/sht4xtemp.ioconf
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1725 src/distrib/sets/lists/man/mi:1.1726
--- src/distrib/sets/lists/man/mi:1.1725 Sun Aug 1 21:56:26 2021
+++ src/distrib/sets/lists/man/mi Sun Oct 3 17:27:02 2021
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1725 2021/08/01 21:56:26 andvar Exp $
+# $NetBSD: mi,v 1.1726 2021/10/03 17:27:02 brad Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -1723,6 +1723,7 @@
./usr/share/man/cat4/shb.0 man-sys-catman .cat
./usr/share/man/cat4/shmif.0 man-sys-catman .cat
./usr/share/man/cat4/shpcic.0 man-sys-catman .cat
+./usr/share/man/cat4/sht4xtemp.0 man-sys-catman .cat
./usr/share/man/cat4/si.0 man-sys-catman .cat
./usr/share/man/cat4/si70xxtemp.0 man-sys-catman .cat
./usr/share/man/cat4/siisata.0 man-sys-catman .cat
@@ -4896,6 +4897,7 @@
./usr/share/man/html4/shb.html man-sys-htmlman html
./usr/share/man/html4/shmif.html man-sys-htmlman html
./usr/share/man/html4/shpcic.html man-sys-htmlman html
+./usr/share/man/html4/sht4xtemp.html man-sys-htmlman html
./usr/share/man/html4/si.html man-sys-htmlman html
./usr/share/man/html4/si70xxtemp.html man-sys-htmlman html
./usr/share/man/html4/siisata.html man-sys-htmlman html
@@ -7975,6 +7977,7 @@
./usr/share/man/man4/shb.4 man-sys-man .man
./usr/share/man/man4/shmif.4 man-sys-man .man
./usr/share/man/man4/shpcic.4 man-sys-man .man
+./usr/share/man/man4/sht4xtemp.4 man-sys-man .man
./usr/share/man/man4/si.4 man-sys-man .man
./usr/share/man/man4/si70xxtemp.4 man-sys-man .man
./usr/share/man/man4/siisata.4 man-sys-man .man
Index: src/distrib/sets/lists/modules/mi
diff -u src/distrib/sets/lists/modules/mi:1.146 src/distrib/sets/lists/modules/mi:1.147
--- src/distrib/sets/lists/modules/mi:1.146 Sat Sep 11 16:10:37 2021
+++ src/distrib/sets/lists/modules/mi Sun Oct 3 17:27:02 2021
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.146 2021/09/11 16:10:37 pgoyette Exp $
+# $NetBSD: mi,v 1.147 2021/10/03 17:27:02 brad Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -397,6 +397,8 @@
./@MODULEDIR@/securelevel/securelevel.kmod modules-base-kernel kmod
./@MODULEDIR@/sequencer modules-base-kernel kmod
./@MODULEDIR@/sequencer/sequencer.kmod modules-base-kernel kmod
+./@MODULEDIR@/sht4xtemp modules-base-kernel kmod
+./@MODULEDIR@/sht4xtemp/sht4xtemp.kmod modules-base-kernel kmod
./@MODULEDIR@/si70xxtemp modules-base-kernel kmod
./@MODULEDIR@/si70xxtemp/si70xxtemp.kmod modules-base-kernel kmod
./@MODULEDIR@/skipjack modules-base-kernel kmod
Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.715 src/share/man/man4/Makefile:1.716
--- src/share/man/man4/Makefile:1.715 Sun Aug 1 21:56:27 2021
+++ src/share/man/man4/Makefile Sun Oct 3 17:27:02 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.715 2021/08/01 21:56:27 andvar Exp $
+# $NetBSD: Makefile,v 1.716 2021/10/03 17:27:02 brad Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -56,7 +56,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 a
rnd.4 route.4 rs5c372rtc.4 rtk.4 rtsx.4 rtw.4 rtwn.4 rum.4 run.4 \
s390rtc.4 satalink.4 sbus.4 schide.4 \
scsi.4 sctp.4 sd.4 se.4 seeprom.4 sem.4 \
- ses.4 sf.4 sfb.4 sgsmix.4 shb.4 shmif.4 shpcic.4 si70xxtemp.4 \
+ ses.4 sf.4 sfb.4 sgsmix.4 shb.4 shmif.4 shpcic.4 sht4xtemp.4 si70xxtemp.4 \
siisata.4 siop.4 sip.4 siside.4 sk.4 sl.4 slide.4 \
sm.4 smscphy.4 smsh.4 sn.4 sony.4 spc.4 speaker.4 spif.4 sqphy.4 \
srt.4 ss.4 \
Index: src/sys/dev/i2c/files.i2c
diff -u src/sys/dev/i2c/files.i2c:1.116 src/sys/dev/i2c/files.i2c:1.117
--- src/sys/dev/i2c/files.i2c:1.116 Tue Jul 27 20:23:41 2021
+++ src/sys/dev/i2c/files.i2c Sun Oct 3 17:27:02 2021
@@ -1,4 +1,4 @@
-# $NetBSD: files.i2c,v 1.116 2021/07/27 20:23:41 macallan Exp $
+# $NetBSD: files.i2c,v 1.117 2021/10/03 17:27:02 brad Exp $
obsolete defflag opt_i2cbus.h I2C_SCAN
define i2cbus { }
@@ -395,6 +395,11 @@ device cwfg: sysmon_envsys
attach cwfg at iic
file dev/i2c/cwfg.c cwfg
+# Sensirion SHT40/SHT41/SHT45 Temperature and Humidity sensor
+device sht4xtemp
+attach sht4xtemp at iic
+file dev/i2c/sht4x.c sht4xtemp
+
# Philips PCA955x GPIO
device pcagpio: leds
attach pcagpio at iic
Index: src/sys/modules/Makefile
diff -u src/sys/modules/Makefile:1.256 src/sys/modules/Makefile:1.257
--- src/sys/modules/Makefile:1.256 Sat Sep 25 17:55:37 2021
+++ src/sys/modules/Makefile Sun Oct 3 17:27:02 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.256 2021/09/25 17:55:37 maya Exp $
+# $NetBSD: Makefile,v 1.257 2021/10/03 17:27:02 brad Exp $
.include <bsd.own.mk>
@@ -69,6 +69,7 @@ SUBDIR+= hfs
SUBDIR+= hythygtemp
SUBDIR+= si70xxtemp
SUBDIR+= am2315temp
+SUBDIR+= sht4xtemp
SUBDIR+= i2cexec
SUBDIR+= i2c_bitbang
SUBDIR+= if_agr
Added files:
Index: src/share/man/man4/sht4xtemp.4
diff -u /dev/null src/share/man/man4/sht4xtemp.4:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/share/man/man4/sht4xtemp.4 Sun Oct 3 17:27:02 2021
@@ -0,0 +1,93 @@
+.\" $NetBSD: sht4xtemp.4,v 1.1 2021/10/03 17:27:02 brad Exp $
+.\"
+.\" Copyright (c) 2021 Brad Spencer <[email protected]>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd September 28th, 2021
+.Dt SHT4XTEMP 4
+.Os
+.Sh NAME
+.Nm sht4xtemp
+.Nd Driver for Sensirion SHT40/SHT41/SHT45 sensor chip via I2C bus
+.Sh SYNOPSIS
+.Cd "sht4xtemp* at iic? addr 0x44"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides measurements from the SHT40/SHT41/SHT45 humidity/temperature
+sensors via the
+.Xr envsys 4
+framework.
+The
+.Nm
+.Ar addr
+argument selects the address at the
+.Xr iic 4
+bus.
+The resolution, heater controls and crc validity can be changed through
+.Xr sysctl 8
+nodes.
+.Sh SYSCTL VARIABLES
+The following
+.Xr sysctl 3
+variables are provided:
+.Bl -tag -width indent
+.It hw.sht4xtemp0.resolutions
+Lists the resolutions supported by the driver and chip.
+.It hw.sht4xtemp0.resolution
+Set the resolution, or number of bits, used for %RH and temperature.
+Use one of the strings listed in hw.sht4xtemp.resolutions.
+.It hw.sht4xtemp0.ignorecrc
+If set, the crc calculation for %RH and temperature will be ignored.
+.It hw.sht4xtemp0.heateron
+Turn the heater on and off. Please note that the heater is turned on right
+before the measurement and runs for a pulse width of time. Then the measurement
+is taken and the heater is turned off. There is no way to keep the heater running
+with this chip.
+.It hw.sht4xtemp0.heaterstrength
+From 1 to 3, the amount of energy put into the heater.
+The higher the number, the more power used.
+.It hw.sht4xtemp0.heaterpulses
+Lists the valid heater pulses supported by the driver and chip.
+.It hw.sht4xtemp0.heaterpulse
+Set the heater pulse length. Use one of the strings listed in
+hw.sht4xtemp.heaterpulses
+.It hw.sht4xtemp0.debug
+If the driver is compiled with
+.Dv SI70XX_DEBUG ,
+this node will appear and can be used to set the debugging level.
+.It hw.sht4xtemp0.readattempts
+To read %RH or temperature the chip requires that the command be sent,
+then a delay must be observed before a read can be done to get the values
+back. The delays are documented in the datasheet for the chip.
+The driver will attempt to read back the values readattempts number of
+times.
+The default is 10 which should be more than enough for most purposes.
+.El
+.Sh SEE ALSO
+.Xr envsys 4 ,
+.Xr iic 4 ,
+.Xr envstat 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Nx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Brad Spencer Aq Mt [email protected] .
Index: src/sys/dev/i2c/sht4x.c
diff -u /dev/null src/sys/dev/i2c/sht4x.c:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/sys/dev/i2c/sht4x.c Sun Oct 3 17:27:02 2021
@@ -0,0 +1,886 @@
+/* $NetBSD: sht4x.c,v 1.1 2021/10/03 17:27:02 brad Exp $ */
+
+/*
+ * Copyright (c) 2021 Brad Spencer <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sht4x.c,v 1.1 2021/10/03 17:27:02 brad Exp $");
+
+/*
+ Driver for the Sensirion SHT40/SHT41/SHT45
+*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/sht4xreg.h>
+#include <dev/i2c/sht4xvar.h>
+
+
+static uint8_t sht4x_crc(uint8_t *, size_t);
+static int sht4x_poke(i2c_tag_t, i2c_addr_t, bool);
+static int sht4x_match(device_t, cfdata_t, void *);
+static void sht4x_attach(device_t, device_t, void *);
+static int sht4x_detach(device_t, int);
+static void sht4x_refresh(struct sysmon_envsys *, envsys_data_t *);
+static int sht4x_verify_sysctl(SYSCTLFN_ARGS);
+static int sht4x_verify_sysctl_resolution(SYSCTLFN_ARGS);
+static int sht4x_verify_sysctl_heateron(SYSCTLFN_ARGS);
+static int sht4x_verify_sysctl_heatervalue(SYSCTLFN_ARGS);
+static int sht4x_verify_sysctl_heaterpulse(SYSCTLFN_ARGS);
+
+#define SHT4X_DEBUG
+#ifdef SHT4X_DEBUG
+#define DPRINTF(s, l, x) \
+ do { \
+ if (l <= s->sc_sht4xdebug) \
+ printf x; \
+ } while (/*CONSTCOND*/0)
+#else
+#define DPRINTF(s, l, x)
+#endif
+
+CFATTACH_DECL_NEW(sht4xtemp, sizeof(struct sht4x_sc),
+ sht4x_match, sht4x_attach, sht4x_detach, NULL);
+
+static struct sht4x_sensor sht4x_sensors[] = {
+ {
+ .desc = "humidity",
+ .type = ENVSYS_SRELHUMIDITY,
+ },
+ {
+ .desc = "temperature",
+ .type = ENVSYS_STEMP,
+ }
+};
+
+/* The typical delays are documented in the datasheet for the chip.
+ There is no need to be very accurate with these, just rough estimates
+ will work fine.
+*/
+
+static struct sht4x_timing sht4x_timings[] = {
+ {
+ .cmd = SHT4X_READ_SERIAL,
+ .typicaldelay = 5000,
+ },
+ {
+ .cmd = SHT4X_SOFT_RESET,
+ .typicaldelay = 1000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION,
+ .typicaldelay = 8000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_MEDIUM_PRECISION,
+ .typicaldelay = 4000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_LOW_PRECISION,
+ .typicaldelay = 2000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_1_S,
+ .typicaldelay = 1000000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_1_S,
+ .typicaldelay = 1000000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_1_S,
+ .typicaldelay = 1000000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_TENTH_S,
+ .typicaldelay = 100000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_TENTH_S,
+ .typicaldelay = 100000,
+ },
+ {
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_TENTH_S,
+ .typicaldelay = 100000,
+ }
+};
+
+/* Used when the heater is not on to find the command to use for the
+ * measurement.
+ */
+
+static struct sht4x_resolution sht4x_resolutions[] = {
+ {
+ .text = "high",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION,
+ },
+ {
+ .text = "medium",
+ .cmd = SHT4X_MEASURE_MEDIUM_PRECISION,
+ },
+ {
+ .text = "low",
+ .cmd = SHT4X_MEASURE_LOW_PRECISION,
+ }
+};
+
+static const char sht4x_resolution_names[] =
+ "high, medium, low";
+
+static struct sht4x_heaterpulse sht4x_heaterpulses[] = {
+ {
+ .length = "short",
+ },
+ {
+ .length = "long",
+ }
+};
+
+/* This is consulted when the heater is on for which command is to be
+ used for the measurement.
+*/
+
+static struct sht4x_heateron_command sht4x_heateron_commands[] = {
+ {
+ .heatervalue = 1,
+ .pulselength = "short",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_TENTH_S,
+ },
+ {
+ .heatervalue = 2,
+ .pulselength = "short",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_TENTH_S,
+ },
+ {
+ .heatervalue = 3,
+ .pulselength = "short",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_TENTH_S,
+ },
+ {
+ .heatervalue = 1,
+ .pulselength = "long",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_1_S,
+ },
+ {
+ .heatervalue = 2,
+ .pulselength = "long",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_1_S,
+ },
+ {
+ .heatervalue = 3,
+ .pulselength = "long",
+ .cmd = SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_1_S,
+ }
+};
+
+static const char sht4x_heaterpulse_names[] =
+ "short, long";
+
+int
+sht4x_verify_sysctl(SYSCTLFN_ARGS)
+{
+ int error, t;
+ struct sysctlnode node;
+
+ node = *rnode;
+ t = *(int *)rnode->sysctl_data;
+ node.sysctl_data = &t;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ if (t < 0)
+ return EINVAL;
+
+ *(int *)rnode->sysctl_data = t;
+
+ return 0;
+}
+
+/* None of the heater and resolutions sysctls change anything on the chip in
+ real time. The values set are used to send different commands depending on
+ how they are set up.
+
+ What this implies is that the chip could be reset and the driver would not care.
+
+*/
+
+int
+sht4x_verify_sysctl_resolution(SYSCTLFN_ARGS)
+{
+ char buf[SHT4X_RES_NAME];
+ struct sht4x_sc *sc;
+ struct sysctlnode node;
+ int error = 0;
+ size_t i;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ (void) memcpy(buf, sc->sc_resolution, SHT4X_RES_NAME);
+ node.sysctl_data = buf;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ for (i = 0; i < __arraycount(sht4x_resolutions); i++) {
+ if (strncmp(node.sysctl_data, sht4x_resolutions[i].text,
+ SHT4X_RES_NAME) == 0) {
+ break;
+ }
+ }
+
+ if (i == __arraycount(sht4x_resolutions))
+ return EINVAL;
+ (void) memcpy(sc->sc_resolution, node.sysctl_data, SHT4X_RES_NAME);
+
+ return error;
+}
+
+int
+sht4x_verify_sysctl_heateron(SYSCTLFN_ARGS)
+{
+ int error;
+ bool t;
+ struct sht4x_sc *sc;
+ struct sysctlnode node;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ t = sc->sc_heateron;
+ node.sysctl_data = &t;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ sc->sc_heateron = t;
+
+ return error;
+}
+
+int
+sht4x_verify_sysctl_heatervalue(SYSCTLFN_ARGS)
+{
+ int error = 0, t;
+ struct sht4x_sc *sc;
+ struct sysctlnode node;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ t = sc->sc_heaterval;
+ node.sysctl_data = &t;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return (error);
+
+ if (t < 1 || t > 3)
+ return (EINVAL);
+
+ sc->sc_heaterval = t;
+
+ return error;
+}
+
+int
+sht4x_verify_sysctl_heaterpulse(SYSCTLFN_ARGS)
+{
+ char buf[SHT4X_PULSE_NAME];
+ struct sht4x_sc *sc;
+ struct sysctlnode node;
+ int error = 0;
+ size_t i;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ (void) memcpy(buf, sc->sc_heaterpulse, SHT4X_PULSE_NAME);
+ node.sysctl_data = buf;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ for (i = 0; i < __arraycount(sht4x_heaterpulses); i++) {
+ if (strncmp(node.sysctl_data, sht4x_heaterpulses[i].length,
+ SHT4X_RES_NAME) == 0) {
+ break;
+ }
+ }
+
+ if (i == __arraycount(sht4x_heaterpulses))
+ return EINVAL;
+ (void) memcpy(sc->sc_heaterpulse, node.sysctl_data, SHT4X_PULSE_NAME);
+
+ return error;
+}
+
+static int
+sht4x_cmddelay(uint8_t cmd)
+{
+ int r = -1;
+
+ for(int i = 0;i < __arraycount(sht4x_timings);i++) {
+ if (cmd == sht4x_timings[i].cmd) {
+ r = sht4x_timings[i].typicaldelay;
+ break;
+ }
+ }
+
+ if (r == -1) {
+ panic("Bad command look up in cmd delay: cmd: %d\n",cmd);
+ }
+
+ return r;
+}
+
+static int
+sht4x_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t *cmd,
+ uint8_t clen, uint8_t *buf, size_t blen, int readattempts)
+{
+ int error;
+ int cmddelay;
+
+ error = iic_exec(tag,I2C_OP_WRITE_WITH_STOP,addr,cmd,clen,NULL,0,0);
+
+ /* Every command returns something except for the soft reset
+ which returns nothing. This chip is also nice in that pretty
+ much every command that returns something does it in the same way.
+ */
+ if (error == 0 && cmd[0] != SHT4X_SOFT_RESET) {
+ cmddelay = sht4x_cmddelay(cmd[0]);
+ delay(cmddelay);
+
+ for (int aint = 0; aint < readattempts; aint++) {
+ error = iic_exec(tag,I2C_OP_READ_WITH_STOP,addr,NULL,0,buf,blen,0);
+ if (error == 0)
+ break;
+ delay(1000);
+ }
+ }
+
+ return error;
+}
+
+static int
+sht4x_cmdr(struct sht4x_sc *sc, uint8_t cmd, uint8_t *buf, size_t blen)
+{
+ return sht4x_cmd(sc->sc_tag, sc->sc_addr, &cmd, 1, buf, blen, sc->sc_readattempts);
+}
+
+static uint8_t
+sht4x_crc(uint8_t * data, size_t size)
+{
+ uint8_t crc = 0xFF;
+
+ for (size_t i = 0; i < size; i++) {
+ crc ^= data[i];
+ for (size_t j = 8; j > 0; j--) {
+ if (crc & 0x80)
+ crc = (crc << 1) ^ 0x131;
+ else
+ crc <<= 1;
+ }
+ }
+ return crc;
+}
+
+static int
+sht4x_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug)
+{
+ uint8_t reg = SHT4X_READ_SERIAL;
+ uint8_t buf[6];
+ int error;
+
+ error = sht4x_cmd(tag, addr, ®, 1, buf, 6, 10);
+ if (matchdebug) {
+ printf("poke X 1: %d\n", error);
+ }
+ return error;
+}
+
+static int
+sht4x_sysctl_init(struct sht4x_sc *sc)
+{
+ int error;
+ const struct sysctlnode *cnode;
+ int sysctlroot_num;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ 0, CTLTYPE_NODE, device_xname(sc->sc_dev),
+ SYSCTL_DESCR("sht4x controls"), NULL, 0, NULL, 0, CTL_HW,
+ CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ sysctlroot_num = cnode->sysctl_num;
+
+#ifdef SHT4X_DEBUG
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
+ SYSCTL_DESCR("Debug level"), sht4x_verify_sysctl, 0,
+ &sc->sc_sht4xdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
+ CTL_EOL)) != 0)
+ return error;
+
+#endif
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts",
+ SYSCTL_DESCR("The number of times to attempt to read the values"),
+ sht4x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW,
+ sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READONLY, CTLTYPE_STRING, "resolutions",
+ SYSCTL_DESCR("Valid resolutions"), 0, 0,
+ __UNCONST(sht4x_resolution_names),
+ sizeof(sht4x_resolution_names) + 1,
+ CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_STRING, "resolution",
+ SYSCTL_DESCR("Resolution of RH and Temp"),
+ sht4x_verify_sysctl_resolution, 0, (void *) sc,
+ SHT4X_RES_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc",
+ SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc,
+ 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron",
+ SYSCTL_DESCR("Heater on"), sht4x_verify_sysctl_heateron, 0,
+ (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_INT, "heaterstrength",
+ SYSCTL_DESCR("Heater strength 1 to 3"),
+ sht4x_verify_sysctl_heatervalue, 0, (void *)sc, 0, CTL_HW,
+ sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READONLY, CTLTYPE_STRING, "heaterpulses",
+ SYSCTL_DESCR("Valid heater pulse lengths"), 0, 0,
+ __UNCONST(sht4x_heaterpulse_names),
+ sizeof(sht4x_heaterpulse_names) + 1,
+ CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+
+ if ((error = sysctl_createv(&sc->sc_sht4xlog, 0, NULL, &cnode,
+ CTLFLAG_READWRITE, CTLTYPE_STRING, "heaterpulse",
+ SYSCTL_DESCR("Heater pulse length"),
+ sht4x_verify_sysctl_heaterpulse, 0, (void *) sc,
+ SHT4X_RES_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
+ return error;
+ return 0;
+}
+
+static int
+sht4x_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct i2c_attach_args *ia = aux;
+ int error, match_result;
+ const bool matchdebug = false;
+
+ if (iic_use_direct_match(ia, match, NULL, &match_result))
+ return match_result;
+
+ /* indirect config - check for configured address */
+ if (ia->ia_addr != SHT4X_TYPICAL_ADDR)
+ return 0;
+
+ /*
+ * Check to see if something is really at this i2c address. This will
+ * keep phantom devices from appearing
+ */
+ if (iic_acquire_bus(ia->ia_tag, 0) != 0) {
+ if (matchdebug)
+ printf("in match acquire bus failed\n");
+ return 0;
+ }
+
+ error = sht4x_poke(ia->ia_tag, ia->ia_addr, matchdebug);
+ iic_release_bus(ia->ia_tag, 0);
+
+ return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0;
+}
+
+static void
+sht4x_attach(device_t parent, device_t self, void *aux)
+{
+ struct sht4x_sc *sc;
+ struct i2c_attach_args *ia;
+ int error, i;
+ int ecount = 0;
+ uint8_t buf[6];
+ uint8_t sncrcpt1, sncrcpt2;
+
+ ia = aux;
+ sc = device_private(self);
+
+ sc->sc_dev = self;
+ sc->sc_tag = ia->ia_tag;
+ sc->sc_addr = ia->ia_addr;
+ sc->sc_sht4xdebug = 0;
+ strlcpy(sc->sc_resolution,"high",SHT4X_RES_NAME);
+ sc->sc_readattempts = 10;
+ sc->sc_ignorecrc = false;
+ sc->sc_heateron = false;
+ sc->sc_heaterval = 1;
+ strlcpy(sc->sc_heaterpulse,"short",SHT4X_PULSE_NAME);
+ sc->sc_sme = NULL;
+
+ aprint_normal("\n");
+
+ mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
+ sc->sc_numsensors = __arraycount(sht4x_sensors);
+
+ if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
+ aprint_error_dev(self,
+ "Unable to create sysmon structure\n");
+ sc->sc_sme = NULL;
+ return;
+ }
+ if ((error = sht4x_sysctl_init(sc)) != 0) {
+ aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error);
+ goto out;
+ }
+
+ error = iic_acquire_bus(sc->sc_tag, 0);
+ if (error) {
+ aprint_error_dev(self, "Could not acquire iic bus: %d\n",
+ error);
+ goto out;
+ }
+
+ error = sht4x_cmdr(sc, SHT4X_SOFT_RESET, NULL, 0);
+ if (error != 0)
+ aprint_error_dev(self, "Reset failed: %d\n", error);
+
+ delay(1000); /* 1 ms max */
+
+ error = sht4x_cmdr(sc, SHT4X_READ_SERIAL, buf, 6);
+ if (error) {
+ aprint_error_dev(self, "Failed to read serial number: %d\n",
+ error);
+ ecount++;
+ }
+
+ sncrcpt1 = sht4x_crc(&buf[0],2);
+ sncrcpt2 = sht4x_crc(&buf[3],2);
+
+ DPRINTF(sc, 2, ("%s: read serial number values: %02x%02x - %02x, %02x%02x - %02x ; %02x %02x\n",
+ device_xname(sc->sc_dev), buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], sncrcpt1, sncrcpt2));
+
+ iic_release_bus(sc->sc_tag, 0);
+ if (error != 0) {
+ aprint_error_dev(self, "Unable to setup device\n");
+ goto out;
+ }
+
+ for (i = 0; i < sc->sc_numsensors; i++) {
+ strlcpy(sc->sc_sensors[i].desc, sht4x_sensors[i].desc,
+ sizeof(sc->sc_sensors[i].desc));
+
+ sc->sc_sensors[i].units = sht4x_sensors[i].type;
+ sc->sc_sensors[i].state = ENVSYS_SINVALID;
+
+ DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i,
+ sc->sc_sensors[i].desc));
+
+ error = sysmon_envsys_sensor_attach(sc->sc_sme,
+ &sc->sc_sensors[i]);
+ if (error) {
+ aprint_error_dev(self,
+ "Unable to attach sensor %d: %d\n", i, error);
+ goto out;
+ }
+ }
+
+ sc->sc_sme->sme_name = device_xname(sc->sc_dev);
+ sc->sc_sme->sme_cookie = sc;
+ sc->sc_sme->sme_refresh = sht4x_refresh;
+
+ DPRINTF(sc, 2, ("sht4x_attach: registering with envsys\n"));
+
+ if (sysmon_envsys_register(sc->sc_sme)) {
+ aprint_error_dev(self,
+ "unable to register with sysmon\n");
+ sysmon_envsys_destroy(sc->sc_sme);
+ sc->sc_sme = NULL;
+ return;
+ }
+
+ /* There is no documented way to ask the chip what version it is. This
+ is likely fine as the only apparent difference is in how precise the
+ measurements will be. The actual conversation with the chip is
+ identical no matter which one you are talking to.
+ */
+
+ aprint_normal_dev(self, "Sensirion SHT40/SHT41/SHT45, "
+ "Serial number: %02x%02x%02x%02x%s",
+ buf[0], buf[1], buf[3], buf[4],
+ (sncrcpt1 == buf[2] && sncrcpt2 == buf[5]) ? "\n" : " (bad crc)\n");
+ return;
+out:
+ sysmon_envsys_destroy(sc->sc_sme);
+ sc->sc_sme = NULL;
+}
+
+/* If you use the heater on this chip, there is no documented choice but to use
+ the highest precision. If the heater is not in use one may select different
+ precisions or repeatability for the measurement.
+
+ Further, if the heater is used, it will only be active during the measurement.
+ The use of the heater will add delay to the measurement as chip will not
+ return anything until the heater pulse time is over.
+*/
+
+static uint8_t
+sht4x_compute_measure_command(char *resolution, bool heateron,
+ int heatervalue, char *heaterpulse)
+{
+ int i;
+ uint8_t r;
+
+ if (heateron == false) {
+ for (i = 0; i < __arraycount(sht4x_resolutions); i++) {
+ if (strncmp(resolution, sht4x_resolutions[i].text,
+ SHT4X_RES_NAME) == 0) {
+ r = sht4x_resolutions[i].cmd;
+ break;
+ }
+ }
+
+ if (i == __arraycount(sht4x_resolutions))
+ panic("Heater off could not find command for resolution: %s\n",resolution);
+ } else {
+ for (i = 0; i < __arraycount(sht4x_heateron_commands); i++) {
+ if (heatervalue == sht4x_heateron_commands[i].heatervalue &&
+ strncmp(heaterpulse, sht4x_heateron_commands[i].pulselength,
+ SHT4X_PULSE_NAME) == 0) {
+ r = sht4x_heateron_commands[i].cmd;
+ break;
+ }
+ }
+
+ if (i == __arraycount(sht4x_heateron_commands))
+ panic("Heater on could not find command for heatervalue, heaterpulse: %d %s\n",
+ heatervalue,heaterpulse);
+ }
+
+ return r;
+}
+
+static void
+sht4x_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
+{
+ struct sht4x_sc *sc;
+ sc = sme->sme_cookie;
+ int error;
+ uint8_t rawdata[6];
+ uint8_t measurement_command;
+ edata->state = ENVSYS_SINVALID;
+
+ mutex_enter(&sc->sc_mutex);
+ error = iic_acquire_bus(sc->sc_tag, 0);
+ if (error) {
+ DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
+ device_xname(sc->sc_dev), error));
+ goto out;
+ }
+
+ /*
+ The documented conversion calculations for the raw values are as follows:
+
+ %RH = (-6 + 125 * rawvalue / 65535)
+
+ T in Celsius = (-45 + 175 * rawvalue / 65535)
+
+ It follows then:
+
+ T in Kelvin = (229.15 + 175 * rawvalue / 65535)
+
+ given the relationship between Celsius and Kelvin.
+
+ What follows reorders the calculation a bit and scales it up to avoid
+ the use of any floating point. All that would really have to happen
+ is a scale up to 10^6 for the sysenv framework, which wants
+ temperature in micro-kelvin and percent relative humidity scaled up
+ 10^6, but since this conversion uses 64 bits due to intermediate
+ values that are bigger than 32 bits the conversion first scales up to
+ 10^9 and the scales back down by 10^3 at the end. This preserves some
+ precision in the conversion that would otherwise be lost.
+ */
+
+ measurement_command = sht4x_compute_measure_command(sc->sc_resolution,
+ sc->sc_heateron, sc->sc_heaterval, sc->sc_heaterpulse);
+ DPRINTF(sc, 2, ("%s: Measurement command: %02x\n",
+ device_xname(sc->sc_dev), measurement_command));
+
+ /* This chip is pretty nice in that all commands are the same length and
+ return the same result. What is not so nice is that you can not ask
+ for temperature and humidity independently.
+
+ The result will be 16 bits of raw temperature and a CRC byte followed
+ by 16 bits of humidity followed by a CRC byte.
+ */
+
+ error = sht4x_cmdr(sc,measurement_command,rawdata,6);
+
+ if (error == 0) {
+ DPRINTF(sc, 2, ("%s: Raw data: %02x%02x %02x - %02x%02x %02x\n",
+ device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2],
+ rawdata[3], rawdata[4], rawdata[5]));
+
+
+ uint8_t *svalptr;
+ uint64_t svalue;
+ int64_t v1;
+ uint64_t v2;
+ uint64_t d1 = 65535;
+ uint64_t mul1;
+ uint64_t mul2;
+ uint64_t div1 = 10000;
+ uint64_t q;
+
+ switch (edata->sensor) {
+ case SHT4X_TEMP_SENSOR:
+ svalptr = &rawdata[0];
+ v1 = 22915; /* this is scaled up already from 229.15 */
+ v2 = 175;
+ mul1 = 10000000000;
+ mul2 = 100000000;
+ break;
+ case SHT4X_HUMIDITY_SENSOR:
+ svalptr = &rawdata[3];
+ v1 = -6;
+ v2 = 125;
+ mul1 = 10000000000;
+ mul2 = 10000000000;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ if (error == 0) {
+ uint8_t testcrc;
+
+ /* Fake out the CRC check if being asked to ignore CRC */
+ if (sc->sc_ignorecrc) {
+ testcrc = *(svalptr + 2);
+ } else {
+ testcrc = sht4x_crc(svalptr,2);
+ }
+
+ if (*(svalptr + 2) == testcrc) {
+ svalue = *svalptr << 8 | *(svalptr + 1);
+ DPRINTF(sc, 2, ("%s: Raw sensor 16 bit: %#jx\n",
+ device_xname(sc->sc_dev), (uintmax_t)svalue));
+
+ /* Scale up */
+ svalue = svalue * mul1;
+ v1 = v1 * mul2;
+ /* Perform the conversion */
+ q = ((v2 * (svalue / d1)) + v1) / div1;
+
+ DPRINTF(sc, 2, ("%s: Computed sensor: %#jx\n",
+ device_xname(sc->sc_dev), (uintmax_t)q));
+ /* The results will fit in 32 bits, so nothing will be lost */
+ edata->value_cur = (uint32_t) q;
+ edata->state = ENVSYS_SVALID;
+ } else {
+ error = EINVAL;
+ }
+ }
+ }
+
+ if (error) {
+ DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d\n",
+ device_xname(sc->sc_dev), error));
+ }
+
+ iic_release_bus(sc->sc_tag, 0);
+out:
+ mutex_exit(&sc->sc_mutex);
+}
+
+static int
+sht4x_detach(device_t self, int flags)
+{
+ struct sht4x_sc *sc;
+
+ sc = device_private(self);
+
+ mutex_enter(&sc->sc_mutex);
+
+ /* Remove the sensors */
+ if (sc->sc_sme != NULL) {
+ sysmon_envsys_unregister(sc->sc_sme);
+ sc->sc_sme = NULL;
+ }
+ mutex_exit(&sc->sc_mutex);
+
+ /* Remove the sysctl tree */
+ sysctl_teardown(&sc->sc_sht4xlog);
+
+ /* Remove the mutex */
+ mutex_destroy(&sc->sc_mutex);
+
+ return 0;
+}
+
+MODULE(MODULE_CLASS_DRIVER, sht4xtemp, "i2cexec,sysmon_envsys");
+
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
+
+static int
+sht4xtemp_modcmd(modcmd_t cmd, void *opaque)
+{
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+#ifdef _MODULE
+ return config_init_component(cfdriver_ioconf_sht4xtemp,
+ cfattach_ioconf_sht4xtemp, cfdata_ioconf_sht4xtemp);
+#else
+ return 0;
+#endif
+ case MODULE_CMD_FINI:
+#ifdef _MODULE
+ return config_fini_component(cfdriver_ioconf_sht4xtemp,
+ cfattach_ioconf_sht4xtemp, cfdata_ioconf_sht4xtemp);
+#else
+ return 0;
+#endif
+ default:
+ return ENOTTY;
+ }
+}
Index: src/sys/dev/i2c/sht4xreg.h
diff -u /dev/null src/sys/dev/i2c/sht4xreg.h:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/sys/dev/i2c/sht4xreg.h Sun Oct 3 17:27:02 2021
@@ -0,0 +1,44 @@
+/* $NetBSD: sht4xreg.h,v 1.1 2021/10/03 17:27:02 brad Exp $ */
+
+/*
+ * Copyright (c) 2021 Brad Spencer <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_I2C_SHT4XREG_H_
+#define _DEV_I2C_SHT4XREG_H_
+
+#define SHT4X_TYPICAL_ADDR 0x44
+
+#define SHT4X_READ_SERIAL 0x89
+#define SHT4X_SOFT_RESET 0x94
+
+/* If you do not use the heater, you can take measurements at a couple
+ of different percisions */
+#define SHT4X_MEASURE_HIGH_PRECISION 0xFD
+#define SHT4X_MEASURE_MEDIUM_PRECISION 0xF6
+#define SHT4X_MEASURE_LOW_PRECISION 0xE0
+
+/* The SHT4X chip only support the heater when reading with the
+ highest percision and then only when the measurement is happening.
+ You can have the heater on for 1 second or 1 tenth of a second.
+ After the measurement the heater will switch itself off */
+#define SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_1_S 0x39
+#define SHT4X_MEASURE_HIGH_PRECISION_HIGH_HEAT_TENTH_S 0x32
+#define SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_1_S 0x2F
+#define SHT4X_MEASURE_HIGH_PRECISION_MEDIUM_HEAT_TENTH_S 0x24
+#define SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_1_S 0x1E
+#define SHT4X_MEASURE_HIGH_PRECISION_LOW_HEAT_TENTH_S 0x15
+
+#endif
Index: src/sys/dev/i2c/sht4xvar.h
diff -u /dev/null src/sys/dev/i2c/sht4xvar.h:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/sys/dev/i2c/sht4xvar.h Sun Oct 3 17:27:02 2021
@@ -0,0 +1,72 @@
+/* $NetBSD: sht4xvar.h,v 1.1 2021/10/03 17:27:02 brad Exp $ */
+
+/*
+ * Copyright (c) 2021 Brad Spencer <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_I2C_SHT4XVAR_H_
+#define _DEV_I2C_SHT4XVAR_H_
+
+#define SHT4X_NUM_SENSORS 2
+#define SHT4X_HUMIDITY_SENSOR 0
+#define SHT4X_TEMP_SENSOR 1
+
+#define SHT4X_RES_NAME 7
+#define SHT4X_PULSE_NAME 6
+
+struct sht4x_sc {
+ int sc_sht4xdebug;
+ device_t sc_dev;
+ i2c_tag_t sc_tag;
+ i2c_addr_t sc_addr;
+ kmutex_t sc_mutex;
+ int sc_numsensors;
+ struct sysmon_envsys *sc_sme;
+ struct sysctllog *sc_sht4xlog;
+ envsys_data_t sc_sensors[SHT4X_NUM_SENSORS];
+ bool sc_ignorecrc;
+ char sc_resolution[SHT4X_RES_NAME];
+ int sc_readattempts;
+ bool sc_heateron;
+ int sc_heaterval;
+ char sc_heaterpulse[SHT4X_PULSE_NAME];
+};
+
+struct sht4x_sensor {
+ const char *desc;
+ enum envsys_units type;
+};
+
+struct sht4x_timing {
+ uint8_t cmd;
+ int typicaldelay;
+};
+
+struct sht4x_resolution {
+ const char *text;
+ uint8_t cmd;
+};
+
+struct sht4x_heaterpulse {
+ const char *length;
+};
+
+struct sht4x_heateron_command {
+ int heatervalue;
+ const char *pulselength;
+ uint8_t cmd;
+};
+
+#endif
Index: src/sys/modules/sht4xtemp/Makefile
diff -u /dev/null src/sys/modules/sht4xtemp/Makefile:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/sys/modules/sht4xtemp/Makefile Sun Oct 3 17:27:02 2021
@@ -0,0 +1,11 @@
+.include "../Makefile.inc"
+
+.PATH: ${S}/dev/i2c
+
+KMOD= sht4xtemp
+IOCONF= sht4xtemp.ioconf
+SRCS= sht4x.c
+
+WARNS= 3
+
+.include <bsd.kmodule.mk>
Index: src/sys/modules/sht4xtemp/sht4xtemp.ioconf
diff -u /dev/null src/sys/modules/sht4xtemp/sht4xtemp.ioconf:1.1
--- /dev/null Sun Oct 3 17:27:03 2021
+++ src/sys/modules/sht4xtemp/sht4xtemp.ioconf Sun Oct 3 17:27:02 2021
@@ -0,0 +1,7 @@
+ioconf sht4xtemp
+
+include "conf/files"
+
+pseudo-root iic*
+
+sht4xtemp* at iic? addr 0x44