summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Balmer <mbalmer@cvs.openbsd.org>2006-06-17 12:26:56 +0000
committerMarc Balmer <mbalmer@cvs.openbsd.org>2006-06-17 12:26:56 +0000
commit86949d29b2fee4476d959b00a51c3d5438a33a4d (patch)
tree88dc206519f16cb141be5c0cd2d119d0be766773
parent68e2bd83e79f2c63313ebf081d8aaf987675ad66 (diff)
udcf(4) no longer needs the file sys/dev/clock_subr.c to be compiled and linked
to the kernel, the two functions it used from this file are now included in the driver itself (like in nmea(4)). udcf(4) can now be enabled to the zaurus, too. in fact on all arches that have USB support.
-rw-r--r--sys/dev/usb/udcf.c146
1 files changed, 134 insertions, 12 deletions
diff --git a/sys/dev/usb/udcf.c b/sys/dev/usb/udcf.c
index 20ac0296f2a..5d8ea25df5f 100644
--- a/sys/dev/usb/udcf.c
+++ b/sys/dev/usb/udcf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udcf.c,v 1.12 2006/06/12 09:51:09 mbalmer Exp $ */
+/* $OpenBSD: udcf.c,v 1.13 2006/06/17 12:26:55 mbalmer Exp $ */
/*
* Copyright (c) 2006 Marc Balmer <mbalmer@openbsd.org>
@@ -29,7 +29,6 @@
#include <sys/time.h>
#include <sys/sensors.h>
-#include <dev/clock_subr.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -43,6 +42,18 @@ int udcfdebug = 0;
#endif
#define DPRINTF(x) DPRINTFN(0, x)
+/* Traditional POSIX base year */
+#define POSIX_BASE_YEAR 1970
+
+static inline int leapyear(int year);
+#define FEBRUARY 2
+#define days_in_year(a) (leapyear(a) ? 366 : 365)
+#define days_in_month(a) (month_days[(a) - 1])
+
+static const int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
#define UDCF_READ_REQ 0xc0
#define UDCF_READ_IDX 0x1f
@@ -113,6 +124,11 @@ void udcf_sl_probe(void *);
void udcf_it_probe(void *);
void udcf_ct_probe(void *);
+#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))
+static inline int leapyear(int year);
+int udcf_ymdhm_to_secs(int y, int mon, int d, int h, int m, time_t *secs);
+
+
USB_DECLARE_DRIVER(udcf);
USB_MATCH(udcf)
@@ -460,7 +476,7 @@ udcf_mg_probe(void *xsc)
{
struct udcf_softc *sc = xsc;
- struct clock_ymdhms ymdhm;
+ int year, month, day, hour, minute;
int minute_bits, hour_bits, day_bits;
int month_bits, year_bits, wday;
int p1, p2, p3;
@@ -529,18 +545,23 @@ udcf_mg_probe(void *xsc)
/* Decode valid time */
- ymdhm.dt_min = FROMBCD(minute_bits);
- ymdhm.dt_hour = FROMBCD(hour_bits);
- ymdhm.dt_day = FROMBCD(day_bits);
- ymdhm.dt_mon = FROMBCD(month_bits);
- ymdhm.dt_year = 2000 + FROMBCD(year_bits);
- ymdhm.dt_sec = 0;
+ minute = FROMBCD(minute_bits);
+ hour = FROMBCD(hour_bits);
+ day = FROMBCD(day_bits);
+ month = FROMBCD(month_bits);
+ year = 2000 + FROMBCD(year_bits);
- sc->sc_next = clock_ymdhms_to_secs(&ymdhm);
+ if (!udcf_ymdhm_to_secs(year, month, day,
+ hour, minute, &sc->sc_next)) {
- /* convert to coordinated universal time */
+ /* convert to UTC */
- sc->sc_next -= z1_bit ? 7200 : 3600;
+ sc->sc_next -= z1_bit ? 7200 : 3600;
+ } else {
+ sc->sc_sensor.status = SENSOR_S_WARN;
+ timeout_add(&sc->sc_it_to, t8);
+ sc->sc_sync = 1;
+ }
DPRINTF(("\n%02d.%02d.%04d %02d:%02d:00 %s",
ymdhm.dt_day, ymdhm.dt_mon + 1,
@@ -637,3 +658,104 @@ udcf_activate(device_ptr_t self, enum devact act)
}
return (0);
}
+
+/*
+ * the leapyear() and udcf_ymdhms_to_secs() functions to calculate the number
+ * of seconds since the epoch for a certain date are from sys/dev/clock_subr.c,
+ * the following copyright applies to these functions:
+ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This inline avoids some unnecessary modulo operations
+ * as compared with the usual macro:
+ * ( ((year % 4) == 0 &&
+ * (year % 100) != 0) ||
+ * ((year % 400) == 0) )
+ * It is otherwise equivalent.
+ */
+static inline int
+leapyear(int year)
+{
+ int rv = 0;
+
+ if ((year & 3) == 0) {
+ rv = 1;
+ if ((year % 100) == 0) {
+ rv = 0;
+ if ((year % 400) == 0)
+ rv = 1;
+ }
+ }
+ return (rv);
+}
+
+/* convert year, month, day, hour, minute to seconds since the epoch */
+int
+udcf_ymdhm_to_secs(int year, int month, int day, int hour, int minute,
+ time_t *secs)
+{
+ int i, days;
+ int leap;
+
+ if (month < 1 || month > 12)
+ return (-1);
+
+ days = days_in_month(month);
+ leap = leapyear(year);
+ if (month == FEBRUARY && leap)
+ days++;
+ if (day < 1 || day > days)
+ return (-1);
+
+ /*
+ * Compute days since start of time
+ * First from years, then from months.
+ */
+ days = 0;
+ for (i = POSIX_BASE_YEAR; i < year; i++)
+ days += days_in_year(i);
+ if (leap && month > FEBRUARY)
+ days++;
+
+ /* Months */
+ for (i = 1; i < month; i++)
+ days += days_in_month(i);
+ days += (day - 1);
+
+ /* convert to seconds. */
+ *secs = days * 86400L + hour * 3600L + minute * 60L;
+ return (0);
+}