Annotation of embedaddon/ntp/ntpd/refclock_pcf.c, revision 1.1.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>