Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

219 lines
4.8 KiB

/* $OpenBSD: sensors.c,v 1.19 2006/06/02 21:17:01 henning 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ntpd.h"
#define SENSORS_MAX 255
#define _PATH_DEV_HOTPLUG "/dev/hotplug"
void sensor_probe(int);
void sensor_add(struct sensor *);
void sensor_remove(struct ntp_sensor *);
struct ntpd_conf *conf;
void
sensor_init(struct ntpd_conf *c)
{
conf = c;
TAILQ_INIT(&conf->ntp_sensors);
}
void
sensor_scan(void)
{
int i;
for (i = 0; i < SENSORS_MAX; i++)
sensor_probe(i);
}
void
sensor_probe(int id)
{
int mib[3];
size_t len;
struct sensor sensor;
mib[0] = CTL_HW;
mib[1] = HW_SENSORS;
mib[2] = id;
len = sizeof(sensor);
if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) {
if (errno != ENOENT)
log_warn("sensor_probe sysctl");
return;
}
if (sensor.type == SENSOR_TIMEDELTA)
sensor_add(&sensor);
}
void
sensor_add(struct sensor *sensor)
{
struct ntp_sensor *s;
struct ntp_conf_sensor *cs;
/* check wether it is already there */
TAILQ_FOREACH(s, &conf->ntp_sensors, entry)
if (!strcmp(s->device, sensor->device))
return;
/* check wether it is requested in the config file */
for (cs = TAILQ_FIRST(&conf->ntp_conf_sensors); cs != NULL &&
strcmp(cs->device, sensor->device) && 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 = time(NULL);
s->weight = cs->weight;
if ((s->device = strdup(sensor->device)) == NULL)
fatal("sensor_add strdup");
s->sensorid = sensor->num;
TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry);
log_debug("sensor %s added", s->device);
}
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)
{
struct sensor sensor;
u_int32_t refid;
int mib[3];
size_t len;
s->next = time(NULL) + SENSOR_QUERY_INTERVAL;
if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE)
s->update.good = 0;
mib[0] = CTL_HW;
mib[1] = HW_SENSORS;
mib[2] = s->sensorid;
len = sizeof(sensor);
if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) {
if (errno == ENOENT)
sensor_remove(s);
else
log_warn("sensor_query sysctl");
return;
}
if (sensor.flags & SENSOR_FINVALID ||
sensor.status != SENSOR_S_OK)
return;
if (sensor.type != SENSOR_TIMEDELTA ||
strcmp(sensor.device, s->device)) {
sensor_remove(s);
return;
}
if (sensor.tv.tv_sec == s->update.rcvd) /* already seen */
return;
memcpy(&refid, "HARD", sizeof(refid));
s->update.status.refid = htonl(refid);
s->update.offset = 0 - (float)sensor.value / 1000000000.0;
s->update.status.stratum = 0; /* increased when sent out */
s->update.status.rootdelay = 0;
s->update.status.rootdispersion = 0;
s->update.status.reftime = sensor.tv.tv_sec;
s->update.rcvd = sensor.tv.tv_sec;
s->update.good = 1;
log_debug("sensor %s: offset %f", s->device, s->update.offset);
}
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("fnctl F_GETFL");
flags |= O_NONBLOCK;
if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
fatal("fnctl 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, "sensor"))
sensor_scan();
break;
default: /* ignore */
break;
}
else if (n > 0)
fatal("sensor_hotplugevent: short read");
} while (n > 0 || (n == -1 && errno == EINTR));
}