Annotation of embedaddon/ntp/ntpd/refclock_hopfser.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *
                      3:  * refclock_hopfser.c
                      4:  * - clock driver for hopf serial boards (GPS or DCF77)
                      5:  *
                      6:  * Date: 30.03.2000 Revision: 01.10
                      7:  *
                      8:  * latest source and further information can be found at:
                      9:  * http://www.ATLSoft.de/ntp
                     10:  *
                     11:  */
                     12: 
                     13: #ifdef HAVE_CONFIG_H
                     14: # include "config.h"
                     15: #endif
                     16: 
                     17: #if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
                     18: 
                     19: #include "ntpd.h"
                     20: #include "ntp_io.h"
                     21: #include "ntp_control.h"
                     22: #include "ntp_refclock.h"
                     23: #include "ntp_unixtime.h"
                     24: #include "ntp_stdlib.h"
                     25: 
                     26: #if defined HAVE_SYS_MODEM_H
                     27: # include <sys/modem.h>
                     28: # ifndef __QNXNTO__
                     29: #  define TIOCMSET MCSETA
                     30: #  define TIOCMGET MCGETA
                     31: #  define TIOCM_RTS MRTS
                     32: # endif
                     33: #endif
                     34: 
                     35: #ifdef HAVE_TERMIOS_H
                     36: # ifdef TERMIOS_NEEDS__SVID3
                     37: #  define _SVID3
                     38: # endif
                     39: # include <termios.h>
                     40: # ifdef TERMIOS_NEEDS__SVID3
                     41: #  undef _SVID3
                     42: # endif
                     43: #endif
                     44: 
                     45: #ifdef HAVE_SYS_IOCTL_H
                     46: # include <sys/ioctl.h>
                     47: #endif
                     48: 
                     49: #ifdef SYS_WINNT
                     50: extern int async_write(int, const void *, unsigned int);
                     51: #undef write
                     52: #define write(fd, data, octets)        async_write(fd, data, octets)
                     53: #endif
                     54: 
                     55: /*
                     56:  * clock definitions
                     57:  */
                     58: #define        DESCRIPTION     "hopf Elektronik serial clock" /* Long name */
                     59: #define        PRECISION       (-10)   /* precision assumed (about 1 ms) */
                     60: #define        REFID           "hopf\0"        /* reference ID */
                     61: /*
                     62:  * I/O definitions
                     63:  */
                     64: #define        DEVICE          "/dev/hopfclock%d"      /* device name and unit */
                     65: #define        SPEED232        B9600                   /* uart speed (9600 baud) */
                     66: 
                     67: 
                     68: #define STX 0x02
                     69: #define ETX 0x03
                     70: #define CR  0x0c
                     71: #define LF  0x0a
                     72: 
                     73: /* parse states */
                     74: #define REC_QUEUE_EMPTY       0
                     75: #define REC_QUEUE_FULL        1
                     76: 
                     77: #define        HOPF_OPMODE     0x0C    /* operation mode mask */
                     78: #define HOPF_INVALID   0x00    /* no time code available */
                     79: #define HOPF_INTERNAL  0x04    /* internal clock */
                     80: #define HOPF_RADIO     0x08    /* radio clock */
                     81: #define HOPF_RADIOHP   0x0C    /* high precision radio clock */
                     82: 
                     83: /*
                     84:  * hopfclock unit control structure.
                     85:  */
                     86: struct hopfclock_unit {
                     87:        l_fp    laststamp;      /* last receive timestamp */
                     88:        short   unit;           /* NTP refclock unit number */
                     89:        u_long  polled;         /* flag to detect noreplies */
                     90:        char    leap_status;    /* leap second flag */
                     91:        int     rpt_next;
                     92: };
                     93: 
                     94: /*
                     95:  * Function prototypes
                     96:  */
                     97: 
                     98: static int     hopfserial_start        (int, struct peer *);
                     99: static void    hopfserial_shutdown     (int, struct peer *);
                    100: static void    hopfserial_receive      (struct recvbuf *);
                    101: static void    hopfserial_poll         (int, struct peer *);
                    102: /* static  void hopfserial_io          (struct recvbuf *); */
                    103: /*
                    104:  * Transfer vector
                    105:  */
                    106: struct refclock refclock_hopfser = {
                    107:        hopfserial_start,       /* start up driver */
                    108:        hopfserial_shutdown,    /* shut down driver */
                    109:        hopfserial_poll,        /* transmit poll message */
                    110:        noentry,                /* not used  */
                    111:        noentry,                /* initialize driver (not used) */
                    112:        noentry,                /* not used */
                    113:        NOFLAGS                 /* not used */
                    114: };
                    115: 
                    116: /*
                    117:  * hopfserial_start - open the devices and initialize data for processing
                    118:  */
                    119: static int
                    120: hopfserial_start (
                    121:        int unit,
                    122:        struct peer *peer
                    123:        )
                    124: {
                    125:        register struct hopfclock_unit *up;
                    126:        struct refclockproc *pp;
                    127:        int fd;
                    128:        char gpsdev[20];
                    129: 
                    130:        snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
                    131: 
                    132:        /* LDISC_STD, LDISC_RAW
                    133:         * Open serial port. Use CLK line discipline, if available.
                    134:         */
                    135:        fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
                    136:        if (fd <= 0) {
                    137: #ifdef DEBUG
                    138:                printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
                    139: #endif
                    140:                return 0;
                    141:        }
                    142: 
                    143:        msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
                    144:                gpsdev);
                    145: 
                    146:        /*
                    147:         * Allocate and initialize unit structure
                    148:         */
                    149:        up = emalloc(sizeof(*up));
                    150:        memset(up, 0, sizeof(*up));
                    151:        pp = peer->procptr;
                    152:        pp->unitptr = (caddr_t)up;
                    153:        pp->io.clock_recv = hopfserial_receive;
                    154:        pp->io.srcclock = (caddr_t)peer;
                    155:        pp->io.datalen = 0;
                    156:        pp->io.fd = fd;
                    157:        if (!io_addclock(&pp->io)) {
                    158: #ifdef DEBUG
                    159:                printf("hopfSerialClock(%d) io_addclock\n", unit);
                    160: #endif
                    161:                close(fd);
                    162:                pp->io.fd = -1;
                    163:                free(up);
                    164:                pp->unitptr = NULL;
                    165:                return (0);
                    166:        }
                    167: 
                    168:        /*
                    169:         * Initialize miscellaneous variables
                    170:         */
                    171:        pp->clockdesc = DESCRIPTION;
                    172:        peer->precision = PRECISION;
                    173:        peer->burst = NSTAGE;
                    174:        memcpy((char *)&pp->refid, REFID, 4);
                    175: 
                    176:        up->leap_status = 0;
                    177:        up->unit = (short) unit;
                    178: 
                    179:        return (1);
                    180: }
                    181: 
                    182: 
                    183: /*
                    184:  * hopfserial_shutdown - shut down the clock
                    185:  */
                    186: static void
                    187: hopfserial_shutdown (
                    188:        int unit,
                    189:        struct peer *peer
                    190:        )
                    191: {
                    192:        register struct hopfclock_unit *up;
                    193:        struct refclockproc *pp;
                    194: 
                    195:        pp = peer->procptr;
                    196:        up = (struct hopfclock_unit *)pp->unitptr;
                    197: 
                    198:        if (-1 != pp->io.fd)
                    199:                io_closeclock(&pp->io);
                    200:        if (NULL != up)
                    201:                free(up);
                    202: }
                    203: 
                    204: 
                    205: 
                    206: /*
                    207:  * hopfserial_receive - receive data from the serial interface
                    208:  */
                    209: 
                    210: static void
                    211: hopfserial_receive (
                    212:        struct recvbuf *rbufp
                    213:        )
                    214: {
                    215:        struct hopfclock_unit *up;
                    216:        struct refclockproc *pp;
                    217:        struct peer *peer;
                    218: 
                    219:        int             synch;  /* synchhronization indicator */
                    220:        int             DoW;    /* Dow */
                    221: 
                    222:        int     day, month;     /* ddd conversion */
                    223: 
                    224:        /*
                    225:         * Initialize pointers and read the timecode and timestamp.
                    226:         */
                    227:        peer = (struct peer *)rbufp->recv_srcclock;
                    228:        pp = peer->procptr;
                    229:        up = (struct hopfclock_unit *)pp->unitptr;
                    230: 
                    231:        if (up->rpt_next == 0 )
                    232:                return;
                    233: 
                    234: 
                    235:        up->rpt_next = 0; /* wait until next poll interval occur */
                    236: 
                    237:        pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
                    238: 
                    239:        if (pp->lencode  == 0)
                    240:                return;
                    241: 
                    242:        sscanf(pp->a_lastcode,
                    243: #if 1
                    244:               "%1x%1x%2d%2d%2d%2d%2d%2d",   /* ...cr,lf */
                    245: #else
                    246:               "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
                    247: #endif
                    248:               &synch,
                    249:               &DoW,
                    250:               &pp->hour,
                    251:               &pp->minute,
                    252:               &pp->second,
                    253:               &day,
                    254:               &month,
                    255:               &pp->year);
                    256: 
                    257: 
                    258:        /*
                    259:          Validate received values at least enough to prevent internal
                    260:          array-bounds problems, etc.
                    261:        */
                    262:        if((pp->hour < 0) || (pp->hour > 23) ||
                    263:           (pp->minute < 0) || (pp->minute > 59) ||
                    264:           (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
                    265:           (day < 1) || (day > 31) ||
                    266:           (month < 1) || (month > 12) ||
                    267:           (pp->year < 0) || (pp->year > 99)) {
                    268:                /* Data out of range. */
                    269:                refclock_report(peer, CEVNT_BADREPLY);
                    270:                return;
                    271:        }
                    272:        /*
                    273:          some preparations
                    274:        */
                    275:        pp->day    = ymd2yd(pp->year,month,day);
                    276:        pp->leap=0;
                    277: 
                    278:        /* Year-2000 check! */
                    279:        /* wrap 2-digit date into 4-digit */
                    280: 
                    281:        if(pp->year < YEAR_PIVOT) { pp->year += 100; }          /* < 98 */
                    282:        pp->year += 1900;
                    283: 
                    284:        /* preparation for timecode ntpq rl command ! */
                    285: 
                    286: #if 0
                    287:        snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
                    288:                 "STATUS: %1X%1X, DATE: %02d.%02d.%04d  TIME: %02d:%02d:%02d",
                    289:                 synch,
                    290:                 DoW,
                    291:                 day,
                    292:                 month,
                    293:                 pp->year,
                    294:                 pp->hour,
                    295:                 pp->minute,
                    296:                 pp->second);
                    297: 
                    298:        pp->lencode = strlen(pp->a_lastcode);
                    299:        if ((synch && 0xc) == 0 ){  /* time ok? */
                    300:                refclock_report(peer, CEVNT_BADTIME);
                    301:                pp->leap = LEAP_NOTINSYNC;
                    302:                return;
                    303:        }
                    304: #endif
                    305:        /*
                    306:         * If clock has no valid status then report error and exit
                    307:         */
                    308:        if ((synch & HOPF_OPMODE) == HOPF_INVALID ){  /* time ok? */
                    309:                refclock_report(peer, CEVNT_BADTIME);
                    310:                pp->leap = LEAP_NOTINSYNC;
                    311:                return;
                    312:        }
                    313: 
                    314:        /*
                    315:         * Test if time is running on internal quarz
                    316:         * if CLK_FLAG1 is set, sychronize even if no radio operation
                    317:         */
                    318: 
                    319:        if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
                    320:                if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
                    321:                        refclock_report(peer, CEVNT_BADTIME);
                    322:                        pp->leap = LEAP_NOTINSYNC;
                    323:                        return;
                    324:                }
                    325:        }
                    326: 
                    327: 
                    328:        if (!refclock_process(pp)) {
                    329:                refclock_report(peer, CEVNT_BADTIME);
                    330:                return;
                    331:        }
                    332:        pp->lastref = pp->lastrec;
                    333:        refclock_receive(peer);
                    334: 
                    335: #if 0
                    336:        msyslog(LOG_ERR, " D:%x  D:%d D:%d",synch,pp->minute,pp->second);
                    337: #endif
                    338: 
                    339:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
                    340: 
                    341:        return;
                    342: }
                    343: 
                    344: 
                    345: /*
                    346:  * hopfserial_poll - called by the transmit procedure
                    347:  *
                    348:  */
                    349: static void
                    350: hopfserial_poll (
                    351:        int unit,
                    352:        struct peer *peer
                    353:        )
                    354: {
                    355:        register struct hopfclock_unit *up;
                    356:        struct refclockproc *pp;
                    357:        pp = peer->procptr;
                    358: 
                    359:        up = (struct hopfclock_unit *)pp->unitptr;
                    360: 
                    361:        pp->polls++;
                    362:        up->rpt_next = 1;
                    363: 
                    364: #if 0
                    365:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
                    366: #endif
                    367: 
                    368:        return;
                    369: }
                    370: 
                    371: #else
                    372: int refclock_hopfser_bs;
                    373: #endif /* REFCLOCK */

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