Annotation of embedaddon/ntp/ntpd/refclock_pcf.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * refclock_pcf - clock driver for the Conrad parallel port radio clock
        !             3:  */
        !             4: 
        !             5: #ifdef HAVE_CONFIG_H
        !             6: # include <config.h>
        !             7: #endif
        !             8: 
        !             9: #if defined(REFCLOCK) && defined(CLOCK_PCF)
        !            10: 
        !            11: #include "ntpd.h"
        !            12: #include "ntp_io.h"
        !            13: #include "ntp_refclock.h"
        !            14: #include "ntp_calendar.h"
        !            15: #include "ntp_stdlib.h"
        !            16: 
        !            17: /*
        !            18:  * This driver supports the parallel port radio clock sold by Conrad
        !            19:  * Electronic under order numbers 967602 and 642002.
        !            20:  *
        !            21:  * It requires that the local timezone be CET/CEST and that the pcfclock
        !            22:  * device driver be installed.  A device driver for Linux is available at
        !            23:  * http://home.pages.de/~voegele/pcf.html.  Information about a FreeBSD
        !            24:  * driver is available at http://schumann.cx/pcfclock/.
        !            25:  */
        !            26: 
        !            27: /*
        !            28:  * Interface definitions
        !            29:  */
        !            30: #define        DEVICE          "/dev/pcfclocks/%d"
        !            31: #define        OLDDEVICE       "/dev/pcfclock%d"
        !            32: #define        PRECISION       (-1)    /* precision assumed (about 0.5 s) */
        !            33: #define REFID          "PCF"
        !            34: #define DESCRIPTION    "Conrad parallel port radio clock"
        !            35: 
        !            36: #define LENPCF         18      /* timecode length */
        !            37: 
        !            38: /*
        !            39:  * Function prototypes
        !            40:  */
        !            41: static int     pcf_start               (int, struct peer *);
        !            42: static void    pcf_shutdown            (int, struct peer *);
        !            43: static void    pcf_poll                (int, struct peer *);
        !            44: 
        !            45: /*
        !            46:  * Transfer vector
        !            47:  */
        !            48: struct  refclock refclock_pcf = {
        !            49:        pcf_start,              /* start up driver */
        !            50:        pcf_shutdown,           /* shut down driver */
        !            51:        pcf_poll,               /* transmit poll message */
        !            52:        noentry,                /* not used */
        !            53:        noentry,                /* initialize driver (not used) */
        !            54:        noentry,                /* not used */
        !            55:        NOFLAGS                 /* not used */
        !            56: };
        !            57: 
        !            58: 
        !            59: /*
        !            60:  * pcf_start - open the device and initialize data for processing
        !            61:  */
        !            62: static int
        !            63: pcf_start(
        !            64:        int unit,
        !            65:        struct peer *peer
        !            66:        )
        !            67: {
        !            68:        struct refclockproc *pp;
        !            69:        int fd;
        !            70:        char device[128];
        !            71: 
        !            72:        /*
        !            73:         * Open device file for reading.
        !            74:         */
        !            75:        snprintf(device, sizeof(device), DEVICE, unit);
        !            76:        fd = open(device, O_RDONLY);
        !            77:        if (fd == -1) {
        !            78:                snprintf(device, sizeof(device), OLDDEVICE, unit);
        !            79:                fd = open(device, O_RDONLY);
        !            80:        }
        !            81: #ifdef DEBUG
        !            82:        if (debug)
        !            83:                printf ("starting PCF with device %s\n",device);
        !            84: #endif
        !            85:        if (fd == -1) {
        !            86:                return (0);
        !            87:        }
        !            88:        
        !            89:        pp = peer->procptr;
        !            90:        pp->io.clock_recv = noentry;
        !            91:        pp->io.srcclock = (caddr_t)peer;
        !            92:        pp->io.datalen = 0;
        !            93:        pp->io.fd = fd;
        !            94:        
        !            95:        /*
        !            96:         * Initialize miscellaneous variables
        !            97:         */
        !            98:        peer->precision = PRECISION;
        !            99:        pp->clockdesc = DESCRIPTION;
        !           100:        /* one transmission takes 172.5 milliseconds since the radio clock
        !           101:           transmits 69 bits with a period of 2.5 milliseconds per bit */
        !           102:        pp->fudgetime1 = 0.1725;
        !           103:        memcpy((char *)&pp->refid, REFID, 4);
        !           104: 
        !           105:        return (1);
        !           106: }
        !           107: 
        !           108: 
        !           109: /*
        !           110:  * pcf_shutdown - shut down the clock
        !           111:  */
        !           112: static void
        !           113: pcf_shutdown(
        !           114:        int unit,
        !           115:        struct peer *peer
        !           116:        )
        !           117: {
        !           118:        struct refclockproc *pp;
        !           119:        
        !           120:        pp = peer->procptr;
        !           121:        (void)close(pp->io.fd);
        !           122: }
        !           123: 
        !           124: 
        !           125: /*
        !           126:  * pcf_poll - called by the transmit procedure
        !           127:  */
        !           128: static void
        !           129: pcf_poll(
        !           130:        int unit,
        !           131:        struct peer *peer
        !           132:        )
        !           133: {
        !           134:        struct refclockproc *pp;
        !           135:        char buf[LENPCF];
        !           136:        struct tm tm, *tp;
        !           137:        time_t t;
        !           138:        
        !           139:        pp = peer->procptr;
        !           140: 
        !           141:        buf[0] = 0;
        !           142:        if (read(pp->io.fd, buf, sizeof(buf)) < sizeof(buf) || buf[0] != 9) {
        !           143:                refclock_report(peer, CEVNT_FAULT);
        !           144:                return;
        !           145:        }
        !           146: 
        !           147:        memset(&tm, 0, sizeof(tm));
        !           148: 
        !           149:        tm.tm_mday = buf[11] * 10 + buf[10];
        !           150:        tm.tm_mon = buf[13] * 10 + buf[12] - 1;
        !           151:        tm.tm_year = buf[15] * 10 + buf[14];
        !           152:        tm.tm_hour = buf[7] * 10 + buf[6];
        !           153:        tm.tm_min = buf[5] * 10 + buf[4];
        !           154:        tm.tm_sec = buf[3] * 10 + buf[2];
        !           155:        tm.tm_isdst = (buf[8] & 1) ? 1 : (buf[8] & 2) ? 0 : -1;
        !           156: 
        !           157:        /*
        !           158:         * Y2K convert the 2-digit year
        !           159:         */
        !           160:        if (tm.tm_year < 99)
        !           161:                tm.tm_year += 100;
        !           162:        
        !           163:        t = mktime(&tm);
        !           164:        if (t == (time_t) -1) {
        !           165:                refclock_report(peer, CEVNT_BADTIME);
        !           166:                return;
        !           167:        }
        !           168: 
        !           169: #if defined(__GLIBC__) && defined(_BSD_SOURCE)
        !           170:        if ((tm.tm_isdst > 0 && tm.tm_gmtoff != 7200)
        !           171:            || (tm.tm_isdst == 0 && tm.tm_gmtoff != 3600)
        !           172:            || tm.tm_isdst < 0) {
        !           173: #ifdef DEBUG
        !           174:                if (debug)
        !           175:                        printf ("local time zone not set to CET/CEST\n");
        !           176: #endif
        !           177:                refclock_report(peer, CEVNT_BADTIME);
        !           178:                return;
        !           179:        }
        !           180: #endif
        !           181: 
        !           182:        pp->lencode = strftime(pp->a_lastcode, BMAX, "%Y %m %d %H %M %S", &tm);
        !           183: 
        !           184: #if defined(_REENTRANT) || defined(_THREAD_SAFE)
        !           185:        tp = gmtime_r(&t, &tm);
        !           186: #else
        !           187:        tp = gmtime(&t);
        !           188: #endif
        !           189:        if (!tp) {
        !           190:                refclock_report(peer, CEVNT_FAULT);
        !           191:                return;
        !           192:        }
        !           193: 
        !           194:        get_systime(&pp->lastrec);
        !           195:        pp->polls++;
        !           196:        pp->year = tp->tm_year + 1900;
        !           197:        pp->day = tp->tm_yday + 1;
        !           198:        pp->hour = tp->tm_hour;
        !           199:        pp->minute = tp->tm_min;
        !           200:        pp->second = tp->tm_sec;
        !           201:        pp->nsec = buf[16] * 31250000;
        !           202:        if (buf[17] & 1)
        !           203:                pp->nsec += 500000000;
        !           204: 
        !           205: #ifdef DEBUG
        !           206:        if (debug)
        !           207:                printf ("pcf%d: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
        !           208:                        unit, pp->year, tp->tm_mon + 1, tp->tm_mday, pp->hour,
        !           209:                        pp->minute, pp->second);
        !           210: #endif
        !           211: 
        !           212:        if (!refclock_process(pp)) {
        !           213:                refclock_report(peer, CEVNT_BADTIME);
        !           214:                return;
        !           215:        }
        !           216:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
        !           217:        if ((buf[1] & 1) && !(pp->sloppyclockflag & CLK_FLAG2))
        !           218:                pp->leap = LEAP_NOTINSYNC;
        !           219:        else
        !           220:                pp->leap = LEAP_NOWARNING;
        !           221:        pp->lastref = pp->lastrec;
        !           222:        refclock_receive(peer);
        !           223: }
        !           224: #else
        !           225: int refclock_pcf_bs;
        !           226: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>