|
|
- /* $OpenBSD: sensors.c,v 1.47 2013/10/04 14:28:16 phessler Exp $ */
-
- /*
- * Copyright (c) 2006 Henning Brauer <henning@openbsd.org>
- *
- * 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 MIND, 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/param.h>
- #include <sys/queue.h>
- #include <sys/sensors.h>
- #include <sys/sysctl.h>
- #include <sys/device.h>
- #include <sys/hotplug.h>
-
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-
- #include "ntpd.h"
-
- #define MAXDEVNAMLEN 16
- #define _PATH_DEV_HOTPLUG "/dev/hotplug"
-
- int sensor_probe(int, char *, struct sensor *);
- void sensor_add(int, char *);
- void sensor_remove(struct ntp_sensor *);
- void sensor_update(struct ntp_sensor *);
-
- void
- sensor_init(void)
- {
- TAILQ_INIT(&conf->ntp_sensors);
- }
-
- int
- sensor_scan(void)
- {
- int i, n, err;
- char d[MAXDEVNAMLEN];
- struct sensor s;
-
- n = 0;
- for (i = 0; ; i++)
- if ((err = sensor_probe(i, d, &s))) {
- if (err == 0)
- continue;
- if (err == -1) /* no further sensors */
- break;
- sensor_add(i, d);
- n++;
- }
-
- return n;
- }
-
- /*
- * 1 = time sensor!
- * 0 = sensor exists... but is not a time sensor
- * -1: no sensor here, and no further sensors after this
- */
- int
- sensor_probe(int devid, char *dxname, struct sensor *sensor)
- {
- int mib[5];
- size_t slen, sdlen;
- struct sensordev sensordev;
-
- mib[0] = CTL_HW;
- mib[1] = HW_SENSORS;
- mib[2] = devid;
- mib[3] = SENSOR_TIMEDELTA;
- mib[4] = 0;
-
- sdlen = sizeof(sensordev);
- if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
- if (errno == ENXIO)
- return (0);
- if (errno == ENOENT)
- return (-1);
- log_warn("sensor_probe sysctl");
- }
-
- if (sensordev.maxnumt[SENSOR_TIMEDELTA] == 0)
- return (0);
-
- strlcpy(dxname, sensordev.xname, MAXDEVNAMLEN);
-
- slen = sizeof(*sensor);
- if (sysctl(mib, 5, sensor, &slen, NULL, 0) == -1) {
- if (errno != ENOENT)
- log_warn("sensor_probe sysctl");
- return (0);
- }
-
- return (1);
- }
-
- void
- sensor_add(int sensordev, char *dxname)
- {
- struct ntp_sensor *s;
- struct ntp_conf_sensor *cs;
-
- /* check whether it is already there */
- TAILQ_FOREACH(s, &conf->ntp_sensors, entry)
- if (!strcmp(s->device, dxname))
- return;
-
- /* check whether it is requested in the config file */
- for (cs = TAILQ_FIRST(&conf->ntp_conf_sensors); cs != NULL &&
- strcmp(cs->device, dxname) && strcmp(cs->device, "*");
- cs = TAILQ_NEXT(cs, entry))
- ; /* nothing */
- if (cs == NULL)
- return;
-
- if ((s = calloc(1, sizeof(*s))) == NULL)
- fatal("sensor_add calloc");
-
- s->next = getmonotime();
- s->weight = cs->weight;
- s->correction = cs->correction;
- s->stratum = cs->stratum - 1;
- if ((s->device = strdup(dxname)) == NULL)
- fatal("sensor_add strdup");
- s->sensordevid = sensordev;
-
- if (cs->refstr == NULL)
- memcpy(&s->refid, SENSOR_DEFAULT_REFID, sizeof(s->refid));
- else {
- s->refid = 0;
- strncpy((char *)&s->refid, cs->refstr, sizeof(s->refid));
- }
-
- TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry);
-
- log_debug("sensor %s added (weight %d, correction %.6f, refstr %.4s, "
- "stratum %d)", s->device, s->weight, s->correction / 1e6,
- &s->refid, s->stratum);
- }
-
- void
- sensor_remove(struct ntp_sensor *s)
- {
- TAILQ_REMOVE(&conf->ntp_sensors, s, entry);
- free(s->device);
- free(s);
- }
-
- void
- sensor_query(struct ntp_sensor *s)
- {
- char dxname[MAXDEVNAMLEN];
- struct sensor sensor;
-
- if (conf->settime)
- s->next = getmonotime() + SENSOR_QUERY_INTERVAL_SETTIME;
- else
- s->next = getmonotime() + SENSOR_QUERY_INTERVAL;
-
- /* rcvd is walltime here, monotime in client.c. not used elsewhere */
- if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE)
- s->update.good = 0;
-
- if (!sensor_probe(s->sensordevid, dxname, &sensor)) {
- sensor_remove(s);
- return;
- }
-
- if (sensor.flags & SENSOR_FINVALID ||
- sensor.status != SENSOR_S_OK)
- return;
-
- if (strcmp(dxname, s->device)) {
- sensor_remove(s);
- return;
- }
-
- if (sensor.tv.tv_sec == s->last) /* already seen */
- return;
-
- s->last = sensor.tv.tv_sec;
- /*
- * TD = device time
- * TS = system time
- * sensor.value = TS - TD in ns
- * if value is positive, system time is ahead
- */
- s->offsets[s->shift].offset = (sensor.value / -1e9) - getoffset() +
- (s->correction / 1e6);
- s->offsets[s->shift].rcvd = sensor.tv.tv_sec;
- s->offsets[s->shift].good = 1;
-
- s->offsets[s->shift].status.send_refid = s->refid;
- /* stratum increased when sent out */
- s->offsets[s->shift].status.stratum = s->stratum;
- s->offsets[s->shift].status.rootdelay = 0;
- s->offsets[s->shift].status.rootdispersion = 0;
- s->offsets[s->shift].status.reftime = sensor.tv.tv_sec;
- s->offsets[s->shift].status.synced = 1;
-
- log_debug("sensor %s: offset %f", s->device,
- s->offsets[s->shift].offset);
-
- if (++s->shift >= SENSOR_OFFSETS) {
- s->shift = 0;
- sensor_update(s);
- }
-
- }
-
- void
- sensor_update(struct ntp_sensor *s)
- {
- struct ntp_offset **offsets;
- int i;
-
- if ((offsets = calloc(SENSOR_OFFSETS, sizeof(struct ntp_offset *))) ==
- NULL)
- fatal("calloc sensor_update");
-
- for (i = 0; i < SENSOR_OFFSETS; i++)
- offsets[i] = &s->offsets[i];
-
- qsort(offsets, SENSOR_OFFSETS, sizeof(struct ntp_offset *),
- offset_compare);
-
- i = SENSOR_OFFSETS / 2;
- memcpy(&s->update, offsets[i], sizeof(s->update));
- if (SENSOR_OFFSETS % 2 == 0) {
- s->update.offset =
- (offsets[i - 1]->offset + offsets[i]->offset) / 2;
- }
- free(offsets);
-
- log_debug("sensor update %s: offset %f", s->device, s->update.offset);
- priv_adjtime();
- }
-
- int
- sensor_hotplugfd(void)
- {
- #ifdef notyet
- int fd, flags;
-
- if ((fd = open(_PATH_DEV_HOTPLUG, O_RDONLY, 0)) == -1) {
- log_warn("open %s", _PATH_DEV_HOTPLUG);
- return (-1);
- }
-
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
- fatal("fcntl F_GETFL");
- flags |= O_NONBLOCK;
- if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
- fatal("fcntl F_SETFL");
-
- return (fd);
- #else
- return (-1);
- #endif
- }
-
- void
- sensor_hotplugevent(int fd)
- {
- struct hotplug_event he;
- ssize_t n;
-
- do {
- if ((n = read(fd, &he, sizeof(he))) == -1 &&
- errno != EINTR && errno != EAGAIN)
- fatal("sensor_hotplugevent read");
-
- if (n == sizeof(he))
- switch (he.he_type) {
- case HOTPLUG_DEVAT:
- if (he.he_devclass == DV_DULL &&
- !strcmp(he.he_devname, "sensordev"))
- sensor_scan();
- break;
- default: /* ignore */
- break;
- }
- else if (n > 0)
- fatal("sensor_hotplugevent: short read");
- } while (n > 0 || (n == -1 && errno == EINTR));
- }
|