LCOV - code coverage report
Current view: top level - dev/onewire - owtemp.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 63 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: owtemp.c,v 1.16 2014/09/14 14:17:25 jsg Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006, 2009 Alexander Yurchenko <grange@openbsd.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 DISCLAIMS 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             : /*
      20             :  * 1-Wire temperature family type device driver.
      21             :  */
      22             : 
      23             : #include <sys/param.h>
      24             : #include <sys/systm.h>
      25             : #include <sys/device.h>
      26             : #include <sys/kernel.h>
      27             : #include <sys/rwlock.h>
      28             : #include <sys/sensors.h>
      29             : 
      30             : #include <dev/onewire/onewiredevs.h>
      31             : #include <dev/onewire/onewirereg.h>
      32             : #include <dev/onewire/onewirevar.h>
      33             : 
      34             : /* Commands */
      35             : #define DS1920_CMD_CONVERT              0x44
      36             : #define DS1920_CMD_READ_SCRATCHPAD      0xbe
      37             : 
      38             : /* Scratchpad layout */
      39             : #define DS1920_SP_TEMP_LSB              0
      40             : #define DS1920_SP_TEMP_MSB              1
      41             : #define DS1920_SP_TH                    2
      42             : #define DS1920_SP_TL                    3
      43             : #define DS18B20_SP_CONFIG               4
      44             : #define DS1920_SP_COUNT_REMAIN          6
      45             : #define DS1920_SP_COUNT_PERC            7
      46             : #define DS1920_SP_CRC                   8
      47             : 
      48             : struct owtemp_softc {
      49             :         struct device           sc_dev;
      50             : 
      51             :         void *                  sc_onewire;
      52             :         u_int64_t               sc_rom;
      53             : 
      54             :         struct ksensor          sc_sensor;
      55             :         struct ksensordev       sc_sensordev;
      56             :         struct sensor_task      *sc_sensortask;
      57             :         struct rwlock           sc_lock;
      58             : };
      59             : 
      60             : int     owtemp_match(struct device *, void *, void *);
      61             : void    owtemp_attach(struct device *, struct device *, void *);
      62             : int     owtemp_detach(struct device *, int);
      63             : int     owtemp_activate(struct device *, int);
      64             : 
      65             : void    owtemp_update(void *);
      66             : 
      67             : struct cfattach owtemp_ca = {
      68             :         sizeof(struct owtemp_softc),
      69             :         owtemp_match,
      70             :         owtemp_attach,
      71             :         owtemp_detach,
      72             :         owtemp_activate
      73             : };
      74             : 
      75             : struct cfdriver owtemp_cd = {
      76             :         NULL, "owtemp", DV_DULL
      77             : };
      78             : 
      79             : static const struct onewire_matchfam owtemp_fams[] = {
      80             :         { ONEWIRE_FAMILY_DS1920 },
      81             :         { ONEWIRE_FAMILY_DS18B20 },
      82             :         { ONEWIRE_FAMILY_DS1822 }
      83             : };
      84             : 
      85             : int
      86           0 : owtemp_match(struct device *parent, void *match, void *aux)
      87             : {
      88           0 :         return (onewire_matchbyfam(aux, owtemp_fams, nitems(owtemp_fams)));
      89             : }
      90             : 
      91             : void
      92           0 : owtemp_attach(struct device *parent, struct device *self, void *aux)
      93             : {
      94           0 :         struct owtemp_softc *sc = (struct owtemp_softc *)self;
      95           0 :         struct onewire_attach_args *oa = aux;
      96             : 
      97           0 :         sc->sc_onewire = oa->oa_onewire;
      98           0 :         sc->sc_rom = oa->oa_rom;
      99             : 
     100             :         /* Initialize sensor */
     101           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     102             :             sizeof(sc->sc_sensordev.xname));
     103           0 :         sc->sc_sensor.type = SENSOR_TEMP;
     104           0 :         snprintf(sc->sc_sensor.desc, sizeof(sc->sc_sensor.desc), "sn %012llx",
     105           0 :             ONEWIRE_ROM_SN(oa->oa_rom));
     106             : 
     107           0 :         sc->sc_sensortask = sensor_task_register(sc, owtemp_update, 5);
     108           0 :         if (sc->sc_sensortask == NULL) {
     109           0 :                 printf(": unable to register update task\n");
     110           0 :                 return;
     111             :         }
     112           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
     113           0 :         sensordev_install(&sc->sc_sensordev);
     114             : 
     115           0 :         rw_init(&sc->sc_lock, sc->sc_dev.dv_xname);
     116           0 :         printf("\n");
     117           0 : }
     118             : 
     119             : int
     120           0 : owtemp_detach(struct device *self, int flags)
     121             : {
     122           0 :         struct owtemp_softc *sc = (struct owtemp_softc *)self;
     123             : 
     124           0 :         rw_enter_write(&sc->sc_lock);
     125           0 :         sensordev_deinstall(&sc->sc_sensordev);
     126           0 :         if (sc->sc_sensortask != NULL)
     127           0 :                 sensor_task_unregister(sc->sc_sensortask);
     128           0 :         rw_exit_write(&sc->sc_lock);
     129             : 
     130           0 :         return (0);
     131             : }
     132             : 
     133             : int
     134           0 : owtemp_activate(struct device *self, int act)
     135             : {
     136           0 :         return (0);
     137             : }
     138             : 
     139             : void
     140           0 : owtemp_update(void *arg)
     141             : {
     142           0 :         struct owtemp_softc *sc = arg;
     143           0 :         u_int8_t data[9];
     144             :         int16_t temp;
     145             :         int count_perc, count_remain, val;
     146             : 
     147           0 :         rw_enter_write(&sc->sc_lock);
     148           0 :         onewire_lock(sc->sc_onewire, 0);
     149           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     150             :                 goto done;
     151           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     152             : 
     153             :         /*
     154             :          * Start temperature conversion. The conversion takes up to 750ms.
     155             :          * After sending the command, the data line must be held high for
     156             :          * at least 750ms to provide power during the conversion process.
     157             :          * As such, no other activity may take place on the 1-Wire bus for
     158             :          * at least this period.
     159             :          */
     160           0 :         onewire_write_byte(sc->sc_onewire, DS1920_CMD_CONVERT);
     161           0 :         tsleep(sc, PRIBIO, "owtemp", hz);
     162             : 
     163           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     164             :                 goto done;
     165           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     166             : 
     167             :         /*
     168             :          * The result of the temperature measurement is placed in the
     169             :          * first two bytes of the scratchpad.
     170             :          */
     171           0 :         onewire_write_byte(sc->sc_onewire, DS1920_CMD_READ_SCRATCHPAD);
     172           0 :         onewire_read_block(sc->sc_onewire, data, 9);
     173           0 :         if (onewire_crc(data, 8) == data[DS1920_SP_CRC]) {
     174           0 :                 temp = data[DS1920_SP_TEMP_MSB] << 8 |
     175           0 :                     data[DS1920_SP_TEMP_LSB];
     176           0 :                 if (ONEWIRE_ROM_FAMILY(sc->sc_rom) == ONEWIRE_FAMILY_DS18B20 ||
     177           0 :                     ONEWIRE_ROM_FAMILY(sc->sc_rom) == ONEWIRE_FAMILY_DS1822) {
     178             :                         /*
     179             :                          * DS18B20 decoding
     180             :                          * default 12 bit 0.0625 C resolution
     181             :                          */
     182           0 :                         val = temp * (1000000 / 16);
     183           0 :                 } else {
     184             :                         /* DS1920 decoding */
     185           0 :                         count_perc = data[DS1920_SP_COUNT_PERC];
     186           0 :                         count_remain = data[DS1920_SP_COUNT_REMAIN];
     187             : 
     188           0 :                         if (count_perc != 0) {
     189             :                                 /* High resolution algorithm */
     190           0 :                                 temp &= ~0x0001;
     191           0 :                                 val = temp * 500000 - 250000 +
     192           0 :                                     ((count_perc - count_remain) * 1000000) /
     193             :                                     count_perc;
     194           0 :                         } else {
     195           0 :                                 val = temp * 500000;
     196             :                         }
     197             :                 }
     198           0 :                 sc->sc_sensor.value = 273150000 + val;
     199           0 :         }
     200             : 
     201             : done:
     202           0 :         onewire_unlock(sc->sc_onewire);
     203           0 :         rw_exit_write(&sc->sc_lock);
     204           0 : }

Generated by: LCOV version 1.13