| File: | dev/usb/uthum.c |
| Warning: | line 691, column 13 The left operand of '!=' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: uthum.c,v 1.39 2023/12/04 05:28:25 mglocker Exp $ */ | ||||
| 2 | |||||
| 3 | /* | ||||
| 4 | * Copyright (c) 2009, 2010 Yojiro UO <yuo@nui.org> | ||||
| 5 | * | ||||
| 6 | * Permission to use, copy, modify, and distribute this software for any | ||||
| 7 | * purpose with or without fee is hereby granted, provided that the above | ||||
| 8 | * copyright notice and this permission notice appear in all copies. | ||||
| 9 | * | ||||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES | ||||
| 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
| 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
| 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
| 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
| 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
| 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
| 17 | */ | ||||
| 18 | |||||
| 19 | /* Driver for HID based TEMPer series Temperature(/Humidity) sensors */ | ||||
| 20 | |||||
| 21 | #include <sys/param.h> | ||||
| 22 | #include <sys/systm.h> | ||||
| 23 | #include <sys/kernel.h> | ||||
| 24 | #include <sys/device.h> | ||||
| 25 | #include <sys/conf.h> | ||||
| 26 | #include <sys/sensors.h> | ||||
| 27 | |||||
| 28 | #include <dev/usb/usb.h> | ||||
| 29 | #include <dev/usb/usbhid.h> | ||||
| 30 | #include <dev/usb/usbdi.h> | ||||
| 31 | #include <dev/usb/usbdi_util.h> | ||||
| 32 | #include <dev/usb/usbdevs.h> | ||||
| 33 | #include <dev/usb/uhidev.h> | ||||
| 34 | |||||
| 35 | #ifdef UTHUM_DEBUG | ||||
| 36 | #define DPRINTF(x) do { printf x; } while (0) | ||||
| 37 | #else | ||||
| 38 | #define DPRINTF(x) | ||||
| 39 | #endif | ||||
| 40 | |||||
| 41 | /* Device types */ | ||||
| 42 | #define UTHUM_TYPE_TEMPERHUM0x535a 0x535a | ||||
| 43 | #define UTHUM_TYPE_TEMPERHUM_20x575a 0x575a /* alternative TEMPerHUM */ | ||||
| 44 | #define UTHUM_TYPE_TEMPER10x5758 0x5758 /* TEMPer1 and HID TEMPer */ | ||||
| 45 | #define UTHUM_TYPE_TEMPER20x5759 0x5759 | ||||
| 46 | #define UTHUM_TYPE_TEMPERNTC0x575b 0x575b | ||||
| 47 | #define UTHUM_TYPE_TEMPERHUM_30x5f5a 0x5f5a | ||||
| 48 | #define UTHUM_TYPE_UNKNOWN0xffff 0xffff | ||||
| 49 | |||||
| 50 | /* Common */ | ||||
| 51 | #define UTHUM_CAL_OFFSET0x14 0x14 | ||||
| 52 | #define UTHUM_MAX_SENSORS2 2 | ||||
| 53 | #define CMD_DEVTYPE0x52 0x52 | ||||
| 54 | #define DEVTYPE_EOF0x53 0x53 | ||||
| 55 | |||||
| 56 | /* query commands */ | ||||
| 57 | #define CMD_GETDATA_NTC0x41 0x41 /* TEMPerNTC NTC part */ | ||||
| 58 | #define CMD_RESET00x43 0x43 /* TEMPer, TEMPer[12], TEMPerNTC */ | ||||
| 59 | #define CMD_RESET10x44 0x44 /* TEMPer, TEMPer[12] */ | ||||
| 60 | #define CMD_GETDATA0x48 0x48 /* TEMPerHUM */ | ||||
| 61 | #define CMD_GETDATA_OUTER0x53 0x53 /* TEMPer, TEMPer[12], TEMPerNTC */ | ||||
| 62 | #define CMD_GETDATA_INNER0x54 0x54 /* TEMPer, TEMPer[12], TEMPerNTC */ | ||||
| 63 | #define CMD_GETDATA_EOF0x31 0x31 | ||||
| 64 | #define CMD_GETDATA_EOF20xaa 0xaa | ||||
| 65 | |||||
| 66 | /* temperntc mode */ | ||||
| 67 | #define TEMPERNTC_MODE_BASE0x61 0x61 /* 0x61 - 0x68 */ | ||||
| 68 | #define TEMPERNTC_MODE_MAX0x68 0x68 | ||||
| 69 | #define CMD_TEMPERNTC_MODE_DONE0x69 0x69 | ||||
| 70 | #define UTHUM_NTC_MIN_THRESHOLD0xb300 0xb300 | ||||
| 71 | #define UTHUM_NTC_MAX_THRESHOLD0xf200 0xf200 | ||||
| 72 | |||||
| 73 | /* sensor name */ | ||||
| 74 | #define UTHUM_TEMPER_INNER0 0 | ||||
| 75 | #define UTHUM_TEMPER_OUTER1 1 | ||||
| 76 | #define UTHUM_TEMPER_NTC1 1 | ||||
| 77 | #define UTHUM_TEMPERHUM_TEMP0 0 | ||||
| 78 | #define UTHUM_TEMPERHUM_HUM1 1 | ||||
| 79 | |||||
| 80 | enum uthum_sensor_type { | ||||
| 81 | UTHUM_SENSOR_UNKNOWN, | ||||
| 82 | UTHUM_SENSOR_SHT1X, | ||||
| 83 | UTHUM_SENSOR_DS75, | ||||
| 84 | UTHUM_SENSOR_NTC, | ||||
| 85 | UTHUM_SENSOR_MAXTYPES, | ||||
| 86 | }; | ||||
| 87 | |||||
| 88 | static const char * const uthum_sensor_type_s[UTHUM_SENSOR_MAXTYPES] = { | ||||
| 89 | "unknown", | ||||
| 90 | "sht1x", | ||||
| 91 | "ds75/12bit", | ||||
| 92 | "NTC" | ||||
| 93 | }; | ||||
| 94 | |||||
| 95 | static uint8_t cmd_issue[8] = | ||||
| 96 | { 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x02, 0x00 }; | ||||
| 97 | static uint8_t cmd_query[8] = | ||||
| 98 | { 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x01, 0x00 }; | ||||
| 99 | |||||
| 100 | struct uthum_sensor { | ||||
| 101 | struct ksensor sensor; | ||||
| 102 | int cal_offset; /* mC or m%RH */ | ||||
| 103 | int attached; | ||||
| 104 | enum uthum_sensor_type dev_type; | ||||
| 105 | int cur_state; /* for TEMPerNTC */ | ||||
| 106 | }; | ||||
| 107 | |||||
| 108 | struct uthum_softc { | ||||
| 109 | struct uhidev sc_hdev; | ||||
| 110 | struct usbd_device *sc_udev; | ||||
| 111 | int sc_device_type; | ||||
| 112 | int sc_num_sensors; | ||||
| 113 | |||||
| 114 | /* uhidev parameters */ | ||||
| 115 | size_t sc_flen; /* feature report length */ | ||||
| 116 | size_t sc_ilen; /* input report length */ | ||||
| 117 | size_t sc_olen; /* output report length */ | ||||
| 118 | |||||
| 119 | /* sensor framework */ | ||||
| 120 | struct uthum_sensor sc_sensor[UTHUM_MAX_SENSORS2]; | ||||
| 121 | struct ksensordev sc_sensordev; | ||||
| 122 | struct sensor_task *sc_sensortask; | ||||
| 123 | }; | ||||
| 124 | |||||
| 125 | const struct usb_devno uthum_devs[] = { | ||||
| 126 | /* XXX: various TEMPer variants are using same VID/PID */ | ||||
| 127 | { USB_VENDOR_TENX0x1130, USB_PRODUCT_TENX_TEMPER0x660c}, | ||||
| 128 | }; | ||||
| 129 | #define uthum_lookup(v, p)usbd_match_device((const struct usb_devno *)(uthum_devs), sizeof (uthum_devs) / sizeof ((uthum_devs)[0]), sizeof ((uthum_devs )[0]), (v), (p)) usb_lookup(uthum_devs, v, p)usbd_match_device((const struct usb_devno *)(uthum_devs), sizeof (uthum_devs) / sizeof ((uthum_devs)[0]), sizeof ((uthum_devs )[0]), (v), (p)) | ||||
| 130 | |||||
| 131 | int uthum_match(struct device *, void *, void *); | ||||
| 132 | void uthum_attach(struct device *, struct device *, void *); | ||||
| 133 | int uthum_detach(struct device *, int); | ||||
| 134 | |||||
| 135 | int uthum_issue_cmd(struct uthum_softc *, uint8_t, int); | ||||
| 136 | int uthum_read_data(struct uthum_softc *, uint8_t, uint8_t *, size_t, int); | ||||
| 137 | int uthum_check_device_info(struct uthum_softc *); | ||||
| 138 | void uthum_reset_device(struct uthum_softc *); | ||||
| 139 | void uthum_setup_sensors(struct uthum_softc *); | ||||
| 140 | |||||
| 141 | void uthum_intr(struct uhidev *, void *, u_int); | ||||
| 142 | void uthum_refresh(void *); | ||||
| 143 | void uthum_refresh_temper(struct uthum_softc *, int); | ||||
| 144 | void uthum_refresh_temperhum(struct uthum_softc *); | ||||
| 145 | void uthum_refresh_temperntc(struct uthum_softc *, int); | ||||
| 146 | |||||
| 147 | int uthum_ntc_getdata(struct uthum_softc *, int *); | ||||
| 148 | int uthum_ntc_tuning(struct uthum_softc *, int, int *); | ||||
| 149 | int64_t uthum_ntc_temp(int64_t, int); | ||||
| 150 | int uthum_sht1x_temp(uint8_t, uint8_t); | ||||
| 151 | int uthum_sht1x_rh(uint8_t, uint8_t, int); | ||||
| 152 | int uthum_ds75_temp(uint8_t, uint8_t); | ||||
| 153 | void uthum_print_sensorinfo(struct uthum_softc *, int); | ||||
| 154 | |||||
| 155 | struct cfdriver uthum_cd = { | ||||
| 156 | NULL((void *)0), "uthum", DV_DULL | ||||
| 157 | }; | ||||
| 158 | |||||
| 159 | const struct cfattach uthum_ca = { | ||||
| 160 | sizeof(struct uthum_softc), | ||||
| 161 | uthum_match, | ||||
| 162 | uthum_attach, | ||||
| 163 | uthum_detach | ||||
| 164 | }; | ||||
| 165 | |||||
| 166 | int | ||||
| 167 | uthum_match(struct device *parent, void *match, void *aux) | ||||
| 168 | { | ||||
| 169 | struct uhidev_attach_arg *uha = aux; | ||||
| 170 | |||||
| 171 | if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)((uha)->claimed != ((void *)0))) | ||||
| 172 | return (UMATCH_NONE0); | ||||
| 173 | |||||
| 174 | if (uthum_lookup(uha->uaa->vendor, uha->uaa->product)usbd_match_device((const struct usb_devno *)(uthum_devs), sizeof (uthum_devs) / sizeof ((uthum_devs)[0]), sizeof ((uthum_devs )[0]), (uha->uaa->vendor), (uha->uaa->product)) == NULL((void *)0)) | ||||
| 175 | return UMATCH_NONE0; | ||||
| 176 | |||||
| 177 | #if 0 /* attach only sensor part of HID as uthum* */ | ||||
| 178 | #define HUG_UNKNOWN_3 0x0003 | ||||
| 179 | void *desc; | ||||
| 180 | int size; | ||||
| 181 | uhidev_get_report_desc(uha->parent, &desc, &size); | ||||
| 182 | if (!hid_is_collection(desc, size, uha->reportid, | ||||
| 183 | HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_UNKNOWN_3)(((0x0001) << 16) | HUG_UNKNOWN_3))) | ||||
| 184 | return (UMATCH_NONE0); | ||||
| 185 | #undef HUG_UNKNOWN_3 | ||||
| 186 | #endif | ||||
| 187 | |||||
| 188 | return (UMATCH_VENDOR_PRODUCT13); | ||||
| 189 | } | ||||
| 190 | |||||
| 191 | void | ||||
| 192 | uthum_attach(struct device *parent, struct device *self, void *aux) | ||||
| 193 | { | ||||
| 194 | struct uthum_softc *sc = (struct uthum_softc *)self; | ||||
| 195 | struct usb_attach_arg *uaa = aux; | ||||
| 196 | struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; | ||||
| 197 | struct usbd_device *dev = uha->parent->sc_udev; | ||||
| 198 | int i, size, repid; | ||||
| 199 | void *desc; | ||||
| 200 | |||||
| 201 | sc->sc_udev = dev; | ||||
| 202 | sc->sc_hdev.sc_intr = uthum_intr; | ||||
| 203 | sc->sc_hdev.sc_parent = uha->parent; | ||||
| 204 | sc->sc_hdev.sc_report_id = uha->reportid; | ||||
| 205 | sc->sc_num_sensors = 0; | ||||
| 206 | |||||
| 207 | uhidev_get_report_desc(uha->parent, &desc, &size); | ||||
| 208 | repid = uha->reportid; | ||||
| 209 | sc->sc_ilen = hid_report_size(desc, size, hid_input, repid); | ||||
| 210 | sc->sc_olen = hid_report_size(desc, size, hid_output, repid); | ||||
| 211 | sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); | ||||
| 212 | |||||
| 213 | printf("\n"); | ||||
| 214 | |||||
| 215 | if (sc->sc_flen < 32) { | ||||
| 216 | /* not sensor interface, just attach */ | ||||
| 217 | return; | ||||
| 218 | } | ||||
| 219 | |||||
| 220 | /* maybe unsupported device */ | ||||
| 221 | if (uthum_check_device_info(sc) < 0) { | ||||
| 222 | DPRINTF(("uthum: unknown device\n")); | ||||
| 223 | return; | ||||
| 224 | }; | ||||
| 225 | |||||
| 226 | /* attach sensor */ | ||||
| 227 | strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname, | ||||
| 228 | sizeof(sc->sc_sensordev.xname)); | ||||
| 229 | uthum_setup_sensors(sc); | ||||
| 230 | |||||
| 231 | /* attach sensors */ | ||||
| 232 | for (i = 0; i < UTHUM_MAX_SENSORS2; i++) { | ||||
| 233 | if (sc->sc_sensor[i].dev_type == UTHUM_SENSOR_UNKNOWN) | ||||
| 234 | continue; | ||||
| 235 | uthum_print_sensorinfo(sc, i); | ||||
| 236 | sc->sc_sensor[i].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 237 | sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i].sensor); | ||||
| 238 | sc->sc_sensor[i].attached = 1; | ||||
| 239 | sc->sc_num_sensors++; | ||||
| 240 | } | ||||
| 241 | |||||
| 242 | if (sc->sc_num_sensors > 0) { | ||||
| 243 | /* 0.1Hz */ | ||||
| 244 | sc->sc_sensortask = sensor_task_register(sc, uthum_refresh, 6); | ||||
| 245 | if (sc->sc_sensortask == NULL((void *)0)) { | ||||
| 246 | printf(", unable to register update task\n"); | ||||
| 247 | return; | ||||
| 248 | } | ||||
| 249 | sensordev_install(&sc->sc_sensordev); | ||||
| 250 | } | ||||
| 251 | |||||
| 252 | DPRINTF(("uthum_attach: complete\n")); | ||||
| 253 | } | ||||
| 254 | |||||
| 255 | int | ||||
| 256 | uthum_detach(struct device *self, int flags) | ||||
| 257 | { | ||||
| 258 | struct uthum_softc *sc = (struct uthum_softc *)self; | ||||
| 259 | int i, rv = 0; | ||||
| 260 | |||||
| 261 | if (sc->sc_num_sensors > 0) { | ||||
| 262 | wakeup(&sc->sc_sensortask); | ||||
| 263 | sensordev_deinstall(&sc->sc_sensordev); | ||||
| 264 | for (i = 0; i < UTHUM_MAX_SENSORS2; i++) { | ||||
| 265 | if (sc->sc_sensor[i].attached) | ||||
| 266 | sensor_detach(&sc->sc_sensordev, | ||||
| 267 | &sc->sc_sensor[i].sensor); | ||||
| 268 | } | ||||
| 269 | if (sc->sc_sensortask != NULL((void *)0)) | ||||
| 270 | sensor_task_unregister(sc->sc_sensortask); | ||||
| 271 | } | ||||
| 272 | |||||
| 273 | uthum_reset_device(sc); | ||||
| 274 | |||||
| 275 | return (rv); | ||||
| 276 | } | ||||
| 277 | |||||
| 278 | void | ||||
| 279 | uthum_intr(struct uhidev *addr, void *ibuf, u_int len) | ||||
| 280 | { | ||||
| 281 | /* do nothing */ | ||||
| 282 | } | ||||
| 283 | |||||
| 284 | int | ||||
| 285 | uthum_issue_cmd(struct uthum_softc *sc, uint8_t target_cmd, int delay) | ||||
| 286 | { | ||||
| 287 | uint8_t cmdbuf[32]; | ||||
| 288 | int i, actlen, olen; | ||||
| 289 | |||||
| 290 | olen = MIN(sc->sc_olen, sizeof(cmdbuf))(((sc->sc_olen)<(sizeof(cmdbuf)))?(sc->sc_olen):(sizeof (cmdbuf))); | ||||
| 291 | |||||
| 292 | bzero(cmdbuf, sizeof(cmdbuf))__builtin_bzero((cmdbuf), (sizeof(cmdbuf))); | ||||
| 293 | memcpy(cmdbuf, cmd_issue, sizeof(cmd_issue))__builtin_memcpy((cmdbuf), (cmd_issue), (sizeof(cmd_issue))); | ||||
| 294 | actlen = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT0x02, | ||||
| 295 | sc->sc_hdev.sc_report_id, cmdbuf, olen); | ||||
| 296 | if (actlen != olen) | ||||
| 297 | return EIO5; | ||||
| 298 | |||||
| 299 | bzero(cmdbuf, sizeof(cmdbuf))__builtin_bzero((cmdbuf), (sizeof(cmdbuf))); | ||||
| 300 | cmdbuf[0] = target_cmd; | ||||
| 301 | actlen = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT0x02, | ||||
| 302 | sc->sc_hdev.sc_report_id, cmdbuf, olen); | ||||
| 303 | if (actlen != olen) | ||||
| 304 | return EIO5; | ||||
| 305 | |||||
| 306 | bzero(cmdbuf, sizeof(cmdbuf))__builtin_bzero((cmdbuf), (sizeof(cmdbuf))); | ||||
| 307 | for (i = 0; i < 7; i++) { | ||||
| 308 | actlen = uhidev_set_report(sc->sc_hdev.sc_parent, | ||||
| 309 | UHID_OUTPUT_REPORT0x02, sc->sc_hdev.sc_report_id, cmdbuf, olen); | ||||
| 310 | if (actlen != olen) | ||||
| 311 | return EIO5; | ||||
| 312 | } | ||||
| 313 | |||||
| 314 | /* wait if required */ | ||||
| 315 | if (delay > 0) | ||||
| 316 | tsleep_nsec(&sc->sc_sensortask, 0, "uthum", | ||||
| 317 | MSEC_TO_NSEC(delay)); | ||||
| 318 | |||||
| 319 | return 0; | ||||
| 320 | } | ||||
| 321 | |||||
| 322 | int | ||||
| 323 | uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf, | ||||
| 324 | size_t len, int delay) | ||||
| 325 | { | ||||
| 326 | uint8_t cmdbuf[32], report[256]; | ||||
| 327 | int olen, flen; | ||||
| 328 | |||||
| 329 | /* if return buffer is null, do nothing */ | ||||
| 330 | if ((buf
| ||||
| 331 | return 0; | ||||
| 332 | |||||
| 333 | if (uthum_issue_cmd(sc, target_cmd, 50)) | ||||
| 334 | return 0; | ||||
| 335 | |||||
| 336 | olen = MIN(sc->sc_olen, sizeof(cmdbuf))(((sc->sc_olen)<(sizeof(cmdbuf)))?(sc->sc_olen):(sizeof (cmdbuf))); | ||||
| 337 | |||||
| 338 | bzero(cmdbuf, sizeof(cmdbuf))__builtin_bzero((cmdbuf), (sizeof(cmdbuf))); | ||||
| 339 | memcpy(cmdbuf, cmd_query, sizeof(cmd_query))__builtin_memcpy((cmdbuf), (cmd_query), (sizeof(cmd_query))); | ||||
| 340 | if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT0x02, | ||||
| 341 | sc->sc_hdev.sc_report_id, cmdbuf, olen) != olen) | ||||
| 342 | return EIO5; | ||||
| 343 | |||||
| 344 | /* wait if required */ | ||||
| 345 | if (delay > 0) | ||||
| 346 | tsleep_nsec(&sc->sc_sensortask, 0, "uthum", | ||||
| 347 | MSEC_TO_NSEC(delay)); | ||||
| 348 | |||||
| 349 | /* get answer */ | ||||
| 350 | flen = MIN(sc->sc_flen, sizeof(report))(((sc->sc_flen)<(sizeof(report)))?(sc->sc_flen):(sizeof (report))); | ||||
| 351 | if (uhidev_get_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT0x03, | ||||
| 352 | sc->sc_hdev.sc_report_id, report, flen) != flen) | ||||
| 353 | return EIO5; | ||||
| 354 | memcpy(buf, report, len)__builtin_memcpy((buf), (report), (len)); | ||||
| 355 | return 0; | ||||
| 356 | } | ||||
| 357 | |||||
| 358 | int | ||||
| 359 | uthum_check_device_info(struct uthum_softc *sc) | ||||
| 360 | { | ||||
| 361 | struct uthum_dev_info { | ||||
| 362 | uint16_t dev_type; | ||||
| 363 | uint8_t cal[2][2]; /* calibration offsets */ | ||||
| 364 | uint8_t footer; | ||||
| 365 | uint8_t padding[25]; | ||||
| 366 | } dinfo; | ||||
| 367 | int val, dev_type; | ||||
| 368 | int retry = 3; | ||||
| 369 | |||||
| 370 | /* issue query to device */ | ||||
| 371 | while (retry) { | ||||
| 372 | if (uthum_read_data(sc, CMD_DEVTYPE0x52, (void *)&dinfo, | ||||
| 373 | sizeof(struct uthum_dev_info), 0) != 0) { | ||||
| 374 | DPRINTF(("uthum: device information query fail.\n")); | ||||
| 375 | retry--; | ||||
| 376 | continue; | ||||
| 377 | } | ||||
| 378 | if (dinfo.footer != DEVTYPE_EOF0x53) { | ||||
| 379 | /* it will be a bogus entry, retry. */ | ||||
| 380 | retry--; | ||||
| 381 | } else | ||||
| 382 | break; | ||||
| 383 | } | ||||
| 384 | |||||
| 385 | if (retry <= 0) | ||||
| 386 | return EIO5; | ||||
| 387 | |||||
| 388 | dev_type = betoh16(dinfo.dev_type)(__uint16_t)(__builtin_constant_p(dinfo.dev_type) ? (__uint16_t )(((__uint16_t)(dinfo.dev_type) & 0xffU) << 8 | ((__uint16_t )(dinfo.dev_type) & 0xff00U) >> 8) : __swap16md(dinfo .dev_type)); | ||||
| 389 | /* TEMPerHUM has 3 different device identifiers, unify them */ | ||||
| 390 | if (dev_type == UTHUM_TYPE_TEMPERHUM_20x575a || | ||||
| 391 | dev_type == UTHUM_TYPE_TEMPERHUM_30x5f5a) | ||||
| 392 | dev_type = UTHUM_TYPE_TEMPERHUM0x535a; | ||||
| 393 | |||||
| 394 | /* check device type and calibration offset*/ | ||||
| 395 | switch (dev_type) { | ||||
| 396 | case UTHUM_TYPE_TEMPER20x5759: | ||||
| 397 | case UTHUM_TYPE_TEMPERHUM0x535a: | ||||
| 398 | case UTHUM_TYPE_TEMPERNTC0x575b: | ||||
| 399 | val = (dinfo.cal[1][0] - UTHUM_CAL_OFFSET0x14) * 100; | ||||
| 400 | val += dinfo.cal[1][1] * 10; | ||||
| 401 | sc->sc_sensor[1].cal_offset = val; | ||||
| 402 | /* fall down, don't break */ | ||||
| 403 | case UTHUM_TYPE_TEMPER10x5758: | ||||
| 404 | val = (dinfo.cal[0][0] - UTHUM_CAL_OFFSET0x14) * 100; | ||||
| 405 | val += dinfo.cal[0][1] * 10; | ||||
| 406 | sc->sc_sensor[0].cal_offset = val; | ||||
| 407 | sc->sc_device_type = dev_type; | ||||
| 408 | break; | ||||
| 409 | default: | ||||
| 410 | sc->sc_device_type = UTHUM_TYPE_UNKNOWN0xffff; | ||||
| 411 | printf("uthum: unknown device (devtype = 0x%.2x)\n", | ||||
| 412 | dev_type); | ||||
| 413 | return EIO5; | ||||
| 414 | } | ||||
| 415 | |||||
| 416 | /* device specific init process */ | ||||
| 417 | switch (dev_type) { | ||||
| 418 | case UTHUM_TYPE_TEMPERHUM0x535a: | ||||
| 419 | sc->sc_sensor[UTHUM_TEMPER_NTC1].cur_state = 0; | ||||
| 420 | break; | ||||
| 421 | }; | ||||
| 422 | |||||
| 423 | uthum_reset_device(sc); | ||||
| 424 | |||||
| 425 | return 0; | ||||
| 426 | }; | ||||
| 427 | |||||
| 428 | void | ||||
| 429 | uthum_reset_device(struct uthum_softc *sc) | ||||
| 430 | { | ||||
| 431 | switch (sc->sc_device_type) { | ||||
| 432 | case UTHUM_TYPE_TEMPER10x5758: | ||||
| 433 | case UTHUM_TYPE_TEMPERNTC0x575b: | ||||
| 434 | uthum_issue_cmd(sc, CMD_RESET00x43, 200); | ||||
| 435 | break; | ||||
| 436 | case UTHUM_TYPE_TEMPER20x5759: | ||||
| 437 | uthum_issue_cmd(sc, CMD_RESET00x43, 200); | ||||
| 438 | uthum_issue_cmd(sc, CMD_RESET10x44, 200); | ||||
| 439 | break; | ||||
| 440 | } | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | void | ||||
| 444 | uthum_setup_sensors(struct uthum_softc *sc) | ||||
| 445 | { | ||||
| 446 | int i; | ||||
| 447 | |||||
| 448 | for (i = 0; i < UTHUM_MAX_SENSORS2; i++) | ||||
| 449 | sc->sc_sensor[i].dev_type = UTHUM_SENSOR_UNKNOWN; | ||||
| 450 | |||||
| 451 | switch (sc->sc_device_type) { | ||||
| 452 | case UTHUM_TYPE_TEMPER20x5759: /* 2 temperature sensors */ | ||||
| 453 | sc->sc_sensor[UTHUM_TEMPER_OUTER1].dev_type = | ||||
| 454 | UTHUM_SENSOR_DS75; | ||||
| 455 | sc->sc_sensor[UTHUM_TEMPER_OUTER1].sensor.type = | ||||
| 456 | SENSOR_TEMP; | ||||
| 457 | strlcpy(sc->sc_sensor[UTHUM_TEMPER_OUTER1].sensor.desc, | ||||
| 458 | "outer", | ||||
| 459 | sizeof(sc->sc_sensor[UTHUM_TEMPER_OUTER1].sensor.desc)); | ||||
| 460 | /* fall down */ | ||||
| 461 | case UTHUM_TYPE_TEMPER10x5758: /* 1 temperature sensor */ | ||||
| 462 | sc->sc_sensor[UTHUM_TEMPER_INNER0].dev_type = | ||||
| 463 | UTHUM_SENSOR_DS75; | ||||
| 464 | sc->sc_sensor[UTHUM_TEMPER_INNER0].sensor.type = | ||||
| 465 | SENSOR_TEMP; | ||||
| 466 | strlcpy(sc->sc_sensor[UTHUM_TEMPER_INNER0].sensor.desc, | ||||
| 467 | "inner", | ||||
| 468 | sizeof(sc->sc_sensor[UTHUM_TEMPER_INNER0].sensor.desc)); | ||||
| 469 | break; | ||||
| 470 | case UTHUM_TYPE_TEMPERHUM0x535a: | ||||
| 471 | /* 1 temperature sensor and 1 humidity sensor */ | ||||
| 472 | for (i = 0; i < 2; i++) | ||||
| 473 | sc->sc_sensor[i].dev_type = UTHUM_SENSOR_SHT1X; | ||||
| 474 | sc->sc_sensor[UTHUM_TEMPERHUM_TEMP0].sensor.type = SENSOR_TEMP; | ||||
| 475 | sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.type = | ||||
| 476 | SENSOR_HUMIDITY; | ||||
| 477 | strlcpy(sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.desc, | ||||
| 478 | "RH", | ||||
| 479 | sizeof(sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.desc)); | ||||
| 480 | break; | ||||
| 481 | case UTHUM_TYPE_TEMPERNTC0x575b: | ||||
| 482 | /* 2 temperature sensors */ | ||||
| 483 | for (i = 0; i < 2; i++) | ||||
| 484 | sc->sc_sensor[i].sensor.type = SENSOR_TEMP; | ||||
| 485 | sc->sc_sensor[UTHUM_TEMPER_INNER0].dev_type = | ||||
| 486 | UTHUM_SENSOR_DS75; | ||||
| 487 | sc->sc_sensor[UTHUM_TEMPER_NTC1].dev_type = | ||||
| 488 | UTHUM_SENSOR_NTC; | ||||
| 489 | strlcpy(sc->sc_sensor[UTHUM_TEMPER_INNER0].sensor.desc, | ||||
| 490 | "inner", | ||||
| 491 | sizeof(sc->sc_sensor[UTHUM_TEMPER_INNER0].sensor.desc)); | ||||
| 492 | strlcpy(sc->sc_sensor[UTHUM_TEMPER_NTC1].sensor.desc, | ||||
| 493 | "outer/ntc", | ||||
| 494 | sizeof(sc->sc_sensor[UTHUM_TEMPER_NTC1].sensor.desc)); | ||||
| 495 | |||||
| 496 | /* sensor state tuning */ | ||||
| 497 | for (i = 0; i < 4; i++) | ||||
| 498 | uthum_issue_cmd(sc, TEMPERNTC_MODE_BASE0x61, 50); | ||||
| 499 | sc->sc_sensor[UTHUM_TEMPER_NTC1].cur_state = TEMPERNTC_MODE_BASE0x61; | ||||
| 500 | if (uthum_ntc_tuning(sc, UTHUM_TEMPER_NTC1, NULL((void *)0))) | ||||
| 501 | DPRINTF(("uthum: NTC sensor tuning failed\n")); | ||||
| 502 | uthum_issue_cmd(sc, CMD_TEMPERNTC_MODE_DONE0x69, 100); | ||||
| 503 | break; | ||||
| 504 | default: | ||||
| 505 | /* do nothing */ | ||||
| 506 | break; | ||||
| 507 | } | ||||
| 508 | } | ||||
| 509 | |||||
| 510 | int | ||||
| 511 | uthum_ntc_getdata(struct uthum_softc *sc, int *val) | ||||
| 512 | { | ||||
| 513 | uint8_t buf[8]; | ||||
| 514 | |||||
| 515 | if (val == NULL((void *)0)) | ||||
| 516 | return EIO5; | ||||
| 517 | |||||
| 518 | /* get sensor value */ | ||||
| 519 | if (uthum_read_data(sc, CMD_GETDATA_NTC0x41, buf, sizeof(buf), 10) != 0) { | ||||
| 520 | DPRINTF(("uthum: data read fail\n")); | ||||
| 521 | return EIO5; | ||||
| 522 | } | ||||
| 523 | |||||
| 524 | /* check data integrity */ | ||||
| 525 | if (buf[2] != CMD_GETDATA_EOF20xaa) { | ||||
| 526 | DPRINTF(("uthum: broken ntc data 0x%.2x 0x%.2x 0x%.2x\n", | ||||
| 527 | buf[0], buf[1], buf[2])); | ||||
| 528 | return EIO5; | ||||
| 529 | } | ||||
| 530 | |||||
| 531 | *val = (buf[0] << 8) + buf[1]; | ||||
| 532 | return 0; | ||||
| 533 | } | ||||
| 534 | |||||
| 535 | int | ||||
| 536 | uthum_ntc_tuning(struct uthum_softc *sc, int sensor, int *val) | ||||
| 537 | { | ||||
| 538 | struct uthum_sensor *s; | ||||
| 539 | int done, state, ostate, curval; | ||||
| 540 | int retry = 3; | ||||
| 541 | |||||
| 542 | s = &sc->sc_sensor[sensor]; | ||||
| 543 | state = s->cur_state; | ||||
| 544 | |||||
| 545 | /* get current sensor value */ | ||||
| 546 | if (val == NULL((void *)0)) { | ||||
| 547 | while (retry) { | ||||
| 548 | if (uthum_ntc_getdata(sc, &curval)) { | ||||
| 549 | retry--; | ||||
| 550 | continue; | ||||
| 551 | } else | ||||
| 552 | break; | ||||
| 553 | } | ||||
| 554 | if (retry <= 0) | ||||
| 555 | return EIO5; | ||||
| 556 | } else { | ||||
| 557 | curval = *val; | ||||
| 558 | } | ||||
| 559 | |||||
| 560 | /* no state change is required */ | ||||
| 561 | if ((curval >= UTHUM_NTC_MIN_THRESHOLD0xb300) && | ||||
| 562 | (curval <= UTHUM_NTC_MAX_THRESHOLD0xf200)) { | ||||
| 563 | return 0; | ||||
| 564 | } | ||||
| 565 | |||||
| 566 | if (((curval < UTHUM_NTC_MIN_THRESHOLD0xb300) && | ||||
| 567 | (state == TEMPERNTC_MODE_MAX0x68)) || | ||||
| 568 | ((curval > UTHUM_NTC_MAX_THRESHOLD0xf200) && | ||||
| 569 | (state == TEMPERNTC_MODE_BASE0x61))) | ||||
| 570 | return 0; | ||||
| 571 | |||||
| 572 | DPRINTF(("uthum: ntc tuning start. cur state = 0x%.2x, val = 0x%.4x\n", | ||||
| 573 | state, curval)); | ||||
| 574 | |||||
| 575 | /* tuning loop */ | ||||
| 576 | ostate = state; | ||||
| 577 | done = 0; | ||||
| 578 | while (!done) { | ||||
| 579 | if (curval < UTHUM_NTC_MIN_THRESHOLD0xb300) { | ||||
| 580 | if (state == TEMPERNTC_MODE_MAX0x68) | ||||
| 581 | done++; | ||||
| 582 | else | ||||
| 583 | state++; | ||||
| 584 | } else if (curval > UTHUM_NTC_MAX_THRESHOLD0xf200) { | ||||
| 585 | if (state == TEMPERNTC_MODE_BASE0x61) | ||||
| 586 | done++; | ||||
| 587 | else | ||||
| 588 | state--; | ||||
| 589 | } else { | ||||
| 590 | uthum_ntc_getdata(sc, &curval); | ||||
| 591 | if ((curval >= UTHUM_NTC_MIN_THRESHOLD0xb300) && | ||||
| 592 | (curval <= UTHUM_NTC_MAX_THRESHOLD0xf200)) | ||||
| 593 | done++; | ||||
| 594 | } | ||||
| 595 | |||||
| 596 | /* update state */ | ||||
| 597 | if (state != ostate) { | ||||
| 598 | uthum_issue_cmd(sc, state, 50); | ||||
| 599 | uthum_issue_cmd(sc, state, 50); | ||||
| 600 | uthum_ntc_getdata(sc, &curval); | ||||
| 601 | } | ||||
| 602 | ostate = state; | ||||
| 603 | } | ||||
| 604 | |||||
| 605 | DPRINTF(("uthum: ntc tuning done. state change: 0x%.2x->0x%.2x\n", | ||||
| 606 | s->cur_state, state)); | ||||
| 607 | s->cur_state = state; | ||||
| 608 | if (val != NULL((void *)0)) | ||||
| 609 | *val = curval; | ||||
| 610 | |||||
| 611 | return 0; | ||||
| 612 | } | ||||
| 613 | |||||
| 614 | void | ||||
| 615 | uthum_refresh(void *arg) | ||||
| 616 | { | ||||
| 617 | struct uthum_softc *sc = arg; | ||||
| 618 | int i; | ||||
| 619 | |||||
| 620 | switch (sc->sc_device_type) { | ||||
| |||||
| 621 | case UTHUM_TYPE_TEMPER10x5758: | ||||
| 622 | case UTHUM_TYPE_TEMPER20x5759: | ||||
| 623 | case UTHUM_TYPE_TEMPERNTC0x575b: | ||||
| 624 | for (i = 0; i < sc->sc_num_sensors; i++) { | ||||
| 625 | if (sc->sc_sensor[i].dev_type == UTHUM_SENSOR_DS75) | ||||
| 626 | uthum_refresh_temper(sc, i); | ||||
| 627 | else if (sc->sc_sensor[i].dev_type == UTHUM_SENSOR_NTC) | ||||
| 628 | uthum_refresh_temperntc(sc, i); | ||||
| 629 | } | ||||
| 630 | break; | ||||
| 631 | case UTHUM_TYPE_TEMPERHUM0x535a: | ||||
| 632 | uthum_refresh_temperhum(sc); | ||||
| 633 | break; | ||||
| 634 | default: | ||||
| 635 | break; | ||||
| 636 | /* never reach */ | ||||
| 637 | } | ||||
| 638 | } | ||||
| 639 | |||||
| 640 | void | ||||
| 641 | uthum_refresh_temperhum(struct uthum_softc *sc) | ||||
| 642 | { | ||||
| 643 | uint8_t buf[8]; | ||||
| 644 | int temp, rh; | ||||
| 645 | |||||
| 646 | if (uthum_read_data(sc, CMD_GETDATA0x48, buf, sizeof(buf), 1000) != 0) { | ||||
| 647 | DPRINTF(("uthum: data read fail\n")); | ||||
| 648 | sc->sc_sensor[UTHUM_TEMPERHUM_TEMP0].sensor.flags | ||||
| 649 | |= SENSOR_FINVALID0x0001; | ||||
| 650 | sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.flags | ||||
| 651 | |= SENSOR_FINVALID0x0001; | ||||
| 652 | return; | ||||
| 653 | } | ||||
| 654 | |||||
| 655 | temp = uthum_sht1x_temp(buf[0], buf[1]); | ||||
| 656 | rh = uthum_sht1x_rh(buf[2], buf[3], temp); | ||||
| 657 | |||||
| 658 | /* apply calibration offsets */ | ||||
| 659 | temp += sc->sc_sensor[UTHUM_TEMPERHUM_TEMP0].cal_offset; | ||||
| 660 | rh += sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].cal_offset; | ||||
| 661 | |||||
| 662 | sc->sc_sensor[UTHUM_TEMPERHUM_TEMP0].sensor.value = | ||||
| 663 | (temp * 10000) + 273150000; | ||||
| 664 | sc->sc_sensor[UTHUM_TEMPERHUM_TEMP0].sensor.flags &= ~SENSOR_FINVALID0x0001; | ||||
| 665 | sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.value = rh; | ||||
| 666 | sc->sc_sensor[UTHUM_TEMPERHUM_HUM1].sensor.flags &= ~SENSOR_FINVALID0x0001; | ||||
| 667 | } | ||||
| 668 | |||||
| 669 | void | ||||
| 670 | uthum_refresh_temper(struct uthum_softc *sc, int sensor) | ||||
| 671 | { | ||||
| 672 | uint8_t buf[8]; | ||||
| 673 | uint8_t cmd; | ||||
| 674 | int temp; | ||||
| 675 | |||||
| 676 | if (sensor
| ||||
| 677 | cmd = CMD_GETDATA_INNER0x54; | ||||
| 678 | else if (sensor == UTHUM_TEMPER_OUTER1) | ||||
| 679 | cmd = CMD_GETDATA_OUTER0x53; | ||||
| 680 | else | ||||
| 681 | return; | ||||
| 682 | |||||
| 683 | /* get sensor value */ | ||||
| 684 | if (uthum_read_data(sc, cmd, buf, sizeof(buf), 1000) != 0) { | ||||
| 685 | DPRINTF(("uthum: data read fail\n")); | ||||
| 686 | sc->sc_sensor[sensor].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 687 | return; | ||||
| 688 | } | ||||
| 689 | |||||
| 690 | /* check integrity */ | ||||
| 691 | if (buf[2] != CMD_GETDATA_EOF0x31) { | ||||
| |||||
| 692 | DPRINTF(("uthum: broken ds75 data: 0x%.2x 0x%.2x 0x%.2x\n", | ||||
| 693 | buf[0], buf[1], buf[2])); | ||||
| 694 | sc->sc_sensor[sensor].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 695 | return; | ||||
| 696 | } | ||||
| 697 | temp = uthum_ds75_temp(buf[0], buf[1]); | ||||
| 698 | |||||
| 699 | /* apply calibration offset */ | ||||
| 700 | temp += sc->sc_sensor[sensor].cal_offset; | ||||
| 701 | |||||
| 702 | sc->sc_sensor[sensor].sensor.value = (temp * 10000) + 273150000; | ||||
| 703 | sc->sc_sensor[sensor].sensor.flags &= ~SENSOR_FINVALID0x0001; | ||||
| 704 | } | ||||
| 705 | |||||
| 706 | void | ||||
| 707 | uthum_refresh_temperntc(struct uthum_softc *sc, int sensor) | ||||
| 708 | { | ||||
| 709 | int val; | ||||
| 710 | int64_t temp; | ||||
| 711 | |||||
| 712 | /* get sensor data */ | ||||
| 713 | if (uthum_ntc_getdata(sc, &val)) { | ||||
| 714 | DPRINTF(("uthum: ntc data read fail\n")); | ||||
| 715 | sc->sc_sensor[sensor].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 716 | return; | ||||
| 717 | } | ||||
| 718 | |||||
| 719 | /* adjust sensor state */ | ||||
| 720 | if ((val < UTHUM_NTC_MIN_THRESHOLD0xb300) || | ||||
| 721 | (val > UTHUM_NTC_MAX_THRESHOLD0xf200)) { | ||||
| 722 | if (uthum_ntc_tuning(sc, UTHUM_TEMPER_NTC1, &val)) { | ||||
| 723 | DPRINTF(("uthum: NTC sensor tuning failed\n")); | ||||
| 724 | sc->sc_sensor[sensor].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 725 | return; | ||||
| 726 | } | ||||
| 727 | } | ||||
| 728 | |||||
| 729 | temp = uthum_ntc_temp(val, sc->sc_sensor[sensor].cur_state); | ||||
| 730 | if (temp == 0) { | ||||
| 731 | /* XXX: work around. */ | ||||
| 732 | sc->sc_sensor[sensor].sensor.flags |= SENSOR_FINVALID0x0001; | ||||
| 733 | } else { | ||||
| 734 | /* apply calibration offset */ | ||||
| 735 | temp += sc->sc_sensor[sensor].cal_offset * 10000; | ||||
| 736 | sc->sc_sensor[sensor].sensor.value = temp; | ||||
| 737 | sc->sc_sensor[sensor].sensor.flags &= ~SENSOR_FINVALID0x0001; | ||||
| 738 | } | ||||
| 739 | } | ||||
| 740 | |||||
| 741 | /* return C-degree * 100 value */ | ||||
| 742 | int | ||||
| 743 | uthum_ds75_temp(uint8_t msb, uint8_t lsb) | ||||
| 744 | { | ||||
| 745 | int val; | ||||
| 746 | |||||
| 747 | /* DS75: 12bit precision mode : 0.0625 degrees Celsius ticks */ | ||||
| 748 | |||||
| 749 | val = (msb << 8) | lsb; | ||||
| 750 | if (val >= 32768) | ||||
| 751 | val = val - 65536; | ||||
| 752 | val = (val * 100) >> 8; | ||||
| 753 | |||||
| 754 | return val; | ||||
| 755 | } | ||||
| 756 | |||||
| 757 | /* return C-degree * 100 value */ | ||||
| 758 | int | ||||
| 759 | uthum_sht1x_temp(uint8_t msb, uint8_t lsb) | ||||
| 760 | { | ||||
| 761 | int nticks; | ||||
| 762 | |||||
| 763 | /* sensor device VDD-bias value table | ||||
| 764 | * ---------------------------------------------- | ||||
| 765 | * VDD 2.5V 3.0V 3.5V 4.0V 5.0V | ||||
| 766 | * bias -3940 -3960 -3970 -3980 -4010 | ||||
| 767 | * ---------------------------------------------- | ||||
| 768 | * | ||||
| 769 | * as the VDD of the SHT10 on my TEMPerHUM is 3.43V +/- 0.05V, | ||||
| 770 | * bias -3970 will be best for that device. | ||||
| 771 | */ | ||||
| 772 | |||||
| 773 | nticks = (msb * 256 + lsb) & 0x3fff; | ||||
| 774 | return (nticks - 3970); | ||||
| 775 | } | ||||
| 776 | |||||
| 777 | /* return %RH * 1000 */ | ||||
| 778 | int | ||||
| 779 | uthum_sht1x_rh(uint8_t msb, uint8_t lsb, int temp) | ||||
| 780 | { | ||||
| 781 | int nticks, rh_l; | ||||
| 782 | |||||
| 783 | nticks = (msb * 256 + lsb) & 0x0fff; | ||||
| 784 | rh_l = (-40000 + 405 * nticks) - ((7 * nticks * nticks) / 250); | ||||
| 785 | |||||
| 786 | return ((temp - 2500) * (1 + (nticks >> 7)) + rh_l) / 10; | ||||
| 787 | } | ||||
| 788 | |||||
| 789 | /* return muK */ | ||||
| 790 | int64_t | ||||
| 791 | uthum_ntc_temp(int64_t val, int state) | ||||
| 792 | { | ||||
| 793 | int64_t temp = 0; | ||||
| 794 | |||||
| 795 | switch (state) { | ||||
| 796 | case TEMPERNTC_MODE_BASE0x61: /* 0x61 */ | ||||
| 797 | case TEMPERNTC_MODE_BASE0x61+1: /* 0x62 */ | ||||
| 798 | case TEMPERNTC_MODE_BASE0x61+2: /* 0x63 */ | ||||
| 799 | case TEMPERNTC_MODE_BASE0x61+3: /* 0x64 */ | ||||
| 800 | /* XXX, no data */ | ||||
| 801 | temp = -273150000; | ||||
| 802 | break; | ||||
| 803 | case TEMPERNTC_MODE_BASE0x61+4: /* 0x65 */ | ||||
| 804 | temp = ((val * val * 2977) / 100000) - (val * 4300) + 152450000; | ||||
| 805 | break; | ||||
| 806 | case TEMPERNTC_MODE_BASE0x61+5: /* 0x66 */ | ||||
| 807 | temp = ((val * val * 3887) / 100000) - (val * 5300) + 197590000; | ||||
| 808 | break; | ||||
| 809 | case TEMPERNTC_MODE_BASE0x61+6: /* 0x67 */ | ||||
| 810 | temp = ((val * val * 3495) / 100000) - (val * 5000) + 210590000; | ||||
| 811 | break; | ||||
| 812 | case TEMPERNTC_MODE_BASE0x61+7: /* 0x68 */ | ||||
| 813 | if (val < UTHUM_NTC_MIN_THRESHOLD0xb300) | ||||
| 814 | temp = (val * -1700) + 149630000; | ||||
| 815 | else | ||||
| 816 | temp = ((val * val * 3257) / 100000) - (val * 4900) + | ||||
| 817 | 230470000; | ||||
| 818 | break; | ||||
| 819 | default: | ||||
| 820 | DPRINTF(("NTC state error, unknown state 0x%.2x\n", state)); | ||||
| 821 | break; | ||||
| 822 | } | ||||
| 823 | |||||
| 824 | /* convert muC->muK value */ | ||||
| 825 | return temp + 273150000; | ||||
| 826 | } | ||||
| 827 | |||||
| 828 | void | ||||
| 829 | uthum_print_sensorinfo(struct uthum_softc *sc, int num) | ||||
| 830 | { | ||||
| 831 | struct uthum_sensor *s; | ||||
| 832 | s = &sc->sc_sensor[num]; | ||||
| 833 | |||||
| 834 | printf("%s: ", sc->sc_hdev.sc_dev.dv_xname); | ||||
| 835 | switch (s->sensor.type) { | ||||
| 836 | case SENSOR_TEMP: | ||||
| 837 | printf("type %s (temperature)", | ||||
| 838 | uthum_sensor_type_s[s->dev_type]); | ||||
| 839 | if (s->cal_offset) | ||||
| 840 | printf(", calibration offset %c%d.%d degC", | ||||
| 841 | (s->cal_offset < 0) ? '-' : '+', | ||||
| 842 | abs(s->cal_offset / 100), | ||||
| 843 | abs(s->cal_offset % 100)); | ||||
| 844 | break; | ||||
| 845 | case SENSOR_HUMIDITY: | ||||
| 846 | printf("type %s (humidity)", | ||||
| 847 | uthum_sensor_type_s[s->dev_type]); | ||||
| 848 | if (s->cal_offset) | ||||
| 849 | printf("calibration offset %c%d.%d %%RH", | ||||
| 850 | (s->cal_offset < 0) ? '-' : '+', | ||||
| 851 | abs(s->cal_offset / 100), | ||||
| 852 | abs(s->cal_offset % 100)); | ||||
| 853 | break; | ||||
| 854 | default: | ||||
| 855 | printf("unknown"); | ||||
| 856 | } | ||||
| 857 | printf("\n"); | ||||
| 858 | } |