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

1.1     ! misho       1: /*
        !             2:  * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
        !             3:  */
        !             4: 
        !             5: #ifdef HAVE_CONFIG_H
        !             6: # include <config.h>
        !             7: #endif
        !             8: 
        !             9: #if defined(REFCLOCK) && defined(CLOCK_LEITCH)
        !            10: 
        !            11: #include "ntpd.h"
        !            12: #include "ntp_io.h"
        !            13: #include "ntp_refclock.h"
        !            14: #include "ntp_unixtime.h"
        !            15: 
        !            16: #include <stdio.h>
        !            17: #include <ctype.h>
        !            18: 
        !            19: #ifdef STREAM
        !            20: #include <stropts.h>
        !            21: #if defined(LEITCHCLK)
        !            22: #include <sys/clkdefs.h>
        !            23: #endif /* LEITCHCLK */
        !            24: #endif /* STREAM */
        !            25: 
        !            26: #include "ntp_stdlib.h"
        !            27: 
        !            28: 
        !            29: /*
        !            30:  * Driver for Leitch CSD-5300 Master Clock System
        !            31:  *
        !            32:  * COMMANDS:
        !            33:  *     DATE:   D <CR>
        !            34:  *     TIME:   T <CR>
        !            35:  *     STATUS: S <CR>
        !            36:  *     LOOP:   L <CR>
        !            37:  *
        !            38:  * FORMAT:
        !            39:  *     DATE: YYMMDD<CR>
        !            40:  *     TIME: <CR>/HHMMSS <CR>/HHMMSS <CR>/HHMMSS <CR>/
        !            41:  *             second bondaried on the stop bit of the <CR>
        !            42:  *             second boundaries at '/' above.
        !            43:  *     STATUS: G (good), D (diag fail), T (time not provided) or
        !            44:  *             P (last phone update failed)
        !            45:  */
        !            46: #define PRECISION      (-20)   /* 1x10-8 */
        !            47: #define MAXUNITS 1             /* max number of LEITCH units */
        !            48: #define LEITCHREFID    "ATOM"  /* reference id */
        !            49: #define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
        !            50: #define LEITCH232 "/dev/leitch%d"      /* name of radio device */
        !            51: #define SPEED232 B300          /* uart speed (300 baud) */ 
        !            52: #ifdef DEBUG
        !            53: #define leitch_send(A,M) \
        !            54: if (debug) fprintf(stderr,"write leitch %s\n",M); \
        !            55: if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
        !            56:        if (debug) \
        !            57:            fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
        !            58:        else \
        !            59:            msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
        !            60: #else
        !            61: #define leitch_send(A,M) \
        !            62: if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
        !            63:        msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
        !            64: #endif
        !            65: 
        !            66: #define STATE_IDLE 0
        !            67: #define STATE_DATE 1
        !            68: #define STATE_TIME1 2
        !            69: #define STATE_TIME2 3
        !            70: #define STATE_TIME3 4
        !            71: 
        !            72: /*
        !            73:  * LEITCH unit control structure
        !            74:  */
        !            75: struct leitchunit {
        !            76:        struct peer *peer;
        !            77:        struct refclockio leitchio;
        !            78:        u_char unit;
        !            79:        short year;
        !            80:        short yearday;
        !            81:        short month;
        !            82:        short day;
        !            83:        short hour;
        !            84:        short second;
        !            85:        short minute;
        !            86:        short state;
        !            87:        u_short fudge1;
        !            88:        l_fp reftime1;
        !            89:        l_fp reftime2;
        !            90:        l_fp reftime3;
        !            91:        l_fp codetime1;
        !            92:        l_fp codetime2;
        !            93:        l_fp codetime3;
        !            94:        u_long yearstart;
        !            95: };
        !            96: 
        !            97: /*
        !            98:  * Function prototypes
        !            99:  */
        !           100: static void    leitch_init     (void);
        !           101: static int     leitch_start    (int, struct peer *);
        !           102: static void    leitch_shutdown (int, struct peer *);
        !           103: static void    leitch_poll     (int, struct peer *);
        !           104: static void    leitch_control  (int, struct refclockstat *, struct refclockstat *, struct peer *);
        !           105: #define        leitch_buginfo  noentry
        !           106: static void    leitch_receive  (struct recvbuf *);
        !           107: static void    leitch_process  (struct leitchunit *);
        !           108: #if 0
        !           109: static void    leitch_timeout  (struct peer *);
        !           110: #endif
        !           111: static int     leitch_get_date (struct recvbuf *, struct leitchunit *);
        !           112: static int     leitch_get_time (struct recvbuf *, struct leitchunit *, int);
        !           113: static int     days_per_year           (int);
        !           114: 
        !           115: static struct leitchunit leitchunits[MAXUNITS];
        !           116: static u_char unitinuse[MAXUNITS];
        !           117: static u_char stratumtouse[MAXUNITS];
        !           118: static u_int32 refid[MAXUNITS];
        !           119: 
        !           120: static char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        !           121: 
        !           122: /*
        !           123:  * Transfer vector
        !           124:  */
        !           125: struct refclock refclock_leitch = {
        !           126:        leitch_start, leitch_shutdown, leitch_poll,
        !           127:        leitch_control, leitch_init, leitch_buginfo, NOFLAGS
        !           128: };
        !           129: 
        !           130: /*
        !           131:  * leitch_init - initialize internal leitch driver data
        !           132:  */
        !           133: static void
        !           134: leitch_init(void)
        !           135: {
        !           136:        int i;
        !           137: 
        !           138:        memset((char*)leitchunits, 0, sizeof(leitchunits));
        !           139:        memset((char*)unitinuse, 0, sizeof(unitinuse));
        !           140:        for (i = 0; i < MAXUNITS; i++)
        !           141:            memcpy((char *)&refid[i], LEITCHREFID, 4);
        !           142: }
        !           143: 
        !           144: /*
        !           145:  * leitch_shutdown - shut down a LEITCH clock
        !           146:  */
        !           147: static void
        !           148: leitch_shutdown(
        !           149:        int unit,
        !           150:        struct peer *peer
        !           151:        )
        !           152: {
        !           153:        struct leitchunit *leitch;
        !           154: 
        !           155:        if (unit >= MAXUNITS) {
        !           156:                return;
        !           157:        }
        !           158:        leitch = &leitchunits[unit];
        !           159:        if (-1 != leitch->leitchio.fd)
        !           160:                io_closeclock(&leitch->leitchio);
        !           161: #ifdef DEBUG
        !           162:        if (debug)
        !           163:                fprintf(stderr, "leitch_shutdown()\n");
        !           164: #endif
        !           165: }
        !           166: 
        !           167: /*
        !           168:  * leitch_poll - called by the transmit procedure
        !           169:  */
        !           170: static void
        !           171: leitch_poll(
        !           172:        int unit,
        !           173:        struct peer *peer
        !           174:        )
        !           175: {
        !           176:        struct leitchunit *leitch;
        !           177: 
        !           178:        /* start the state machine rolling */
        !           179: 
        !           180: #ifdef DEBUG
        !           181:        if (debug)
        !           182:            fprintf(stderr, "leitch_poll()\n");
        !           183: #endif
        !           184:        if (unit >= MAXUNITS) {
        !           185:                /* XXXX syslog it */
        !           186:                return;
        !           187:        }
        !           188: 
        !           189:        leitch = &leitchunits[unit];
        !           190: 
        !           191:        if (leitch->state != STATE_IDLE) {
        !           192:                /* reset and wait for next poll */
        !           193:                /* XXXX syslog it */
        !           194:                leitch->state = STATE_IDLE;
        !           195:        } else {
        !           196:                leitch_send(leitch,"D\r");
        !           197:                leitch->state = STATE_DATE;
        !           198:        }
        !           199: }
        !           200: 
        !           201: static void
        !           202: leitch_control(
        !           203:        int unit,
        !           204:        struct refclockstat *in,
        !           205:        struct refclockstat *out,
        !           206:        struct peer *passed_peer
        !           207:        )
        !           208: {
        !           209:        if (unit >= MAXUNITS) {
        !           210:                msyslog(LOG_ERR,
        !           211:                        "leitch_control: unit %d invalid", unit);
        !           212:                return;
        !           213:        }
        !           214: 
        !           215:        if (in) {
        !           216:                if (in->haveflags & CLK_HAVEVAL1)
        !           217:                    stratumtouse[unit] = (u_char)(in->fudgeval1);
        !           218:                if (in->haveflags & CLK_HAVEVAL2)
        !           219:                    refid[unit] = in->fudgeval2;
        !           220:                if (unitinuse[unit]) {
        !           221:                        struct peer *peer;
        !           222: 
        !           223:                        peer = (&leitchunits[unit])->peer;
        !           224:                        peer->stratum = stratumtouse[unit];
        !           225:                        peer->refid = refid[unit];
        !           226:                }
        !           227:        }
        !           228: 
        !           229:        if (out) {
        !           230:                memset((char *)out, 0, sizeof (struct refclockstat));
        !           231:                out->type = REFCLK_ATOM_LEITCH;
        !           232:                out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
        !           233:                out->fudgeval1 = (int32)stratumtouse[unit];
        !           234:                out->fudgeval2 = refid[unit];
        !           235:                out->p_lastcode = "";
        !           236:                out->clockdesc = LEITCH_DESCRIPTION;
        !           237:        }
        !           238: }
        !           239: 
        !           240: /*
        !           241:  * leitch_start - open the LEITCH devices and initialize data for processing
        !           242:  */
        !           243: static int
        !           244: leitch_start(
        !           245:        int unit,
        !           246:        struct peer *peer
        !           247:        )
        !           248: {
        !           249:        struct leitchunit *leitch;
        !           250:        int fd232;
        !           251:        char leitchdev[20];
        !           252: 
        !           253:        /*
        !           254:         * Check configuration info.
        !           255:         */
        !           256:        if (unit >= MAXUNITS) {
        !           257:                msyslog(LOG_ERR, "leitch_start: unit %d invalid", unit);
        !           258:                return (0);
        !           259:        }
        !           260: 
        !           261:        if (unitinuse[unit]) {
        !           262:                msyslog(LOG_ERR, "leitch_start: unit %d in use", unit);
        !           263:                return (0);
        !           264:        }
        !           265: 
        !           266:        /*
        !           267:         * Open serial port.
        !           268:         */
        !           269:        snprintf(leitchdev, sizeof(leitchdev), LEITCH232, unit);
        !           270:        fd232 = open(leitchdev, O_RDWR, 0777);
        !           271:        if (fd232 == -1) {
        !           272:                msyslog(LOG_ERR,
        !           273:                        "leitch_start: open of %s: %m", leitchdev);
        !           274:                return (0);
        !           275:        }
        !           276: 
        !           277:        leitch = &leitchunits[unit];
        !           278:        memset(leitch, 0, sizeof(*leitch));
        !           279: 
        !           280: #if defined(HAVE_SYSV_TTYS)
        !           281:        /*
        !           282:         * System V serial line parameters (termio interface)
        !           283:         *
        !           284:         */
        !           285:        {       struct termio ttyb;
        !           286:        if (ioctl(fd232, TCGETA, &ttyb) < 0) {
        !           287:                msyslog(LOG_ERR,
        !           288:                        "leitch_start: ioctl(%s, TCGETA): %m", leitchdev);
        !           289:                goto screwed;
        !           290:        }
        !           291:        ttyb.c_iflag = IGNBRK|IGNPAR|ICRNL;
        !           292:        ttyb.c_oflag = 0;
        !           293:        ttyb.c_cflag = SPEED232|CS8|CLOCAL|CREAD;
        !           294:        ttyb.c_lflag = ICANON;
        !           295:        ttyb.c_cc[VERASE] = ttyb.c_cc[VKILL] = '\0';
        !           296:        if (ioctl(fd232, TCSETA, &ttyb) < 0) {
        !           297:                msyslog(LOG_ERR,
        !           298:                        "leitch_start: ioctl(%s, TCSETA): %m", leitchdev);
        !           299:                goto screwed;
        !           300:        }
        !           301:        }
        !           302: #endif /* HAVE_SYSV_TTYS */
        !           303: #if defined(HAVE_TERMIOS)
        !           304:        /*
        !           305:         * POSIX serial line parameters (termios interface)
        !           306:         *
        !           307:         * The LEITCHCLK option provides timestamping at the driver level. 
        !           308:         * It requires the tty_clk streams module.
        !           309:         */
        !           310:        {       struct termios ttyb, *ttyp;
        !           311: 
        !           312:        ttyp = &ttyb;
        !           313:        if (tcgetattr(fd232, ttyp) < 0) {
        !           314:                msyslog(LOG_ERR,
        !           315:                        "leitch_start: tcgetattr(%s): %m", leitchdev);
        !           316:                goto screwed;
        !           317:        }
        !           318:        ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
        !           319:        ttyp->c_oflag = 0;
        !           320:        ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
        !           321:        ttyp->c_lflag = ICANON;
        !           322:        ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
        !           323:        if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
        !           324:                msyslog(LOG_ERR,
        !           325:                        "leitch_start: tcsetattr(%s): %m", leitchdev);
        !           326:                goto screwed;
        !           327:        }
        !           328:        if (tcflush(fd232, TCIOFLUSH) < 0) {
        !           329:                msyslog(LOG_ERR,
        !           330:                        "leitch_start: tcflush(%s): %m", leitchdev);
        !           331:                goto screwed;
        !           332:        }
        !           333:        }
        !           334: #endif /* HAVE_TERMIOS */
        !           335: #ifdef STREAM
        !           336: #if defined(LEITCHCLK)
        !           337:        if (ioctl(fd232, I_PUSH, "clk") < 0)
        !           338:            msyslog(LOG_ERR,
        !           339:                    "leitch_start: ioctl(%s, I_PUSH, clk): %m", leitchdev);
        !           340:        if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
        !           341:            msyslog(LOG_ERR,
        !           342:                    "leitch_start: ioctl(%s, CLK_SETSTR): %m", leitchdev);
        !           343: #endif /* LEITCHCLK */
        !           344: #endif /* STREAM */
        !           345: #if defined(HAVE_BSD_TTYS)
        !           346:        /*
        !           347:         * 4.3bsd serial line parameters (sgttyb interface)
        !           348:         *
        !           349:         * The LEITCHCLK option provides timestamping at the driver level. 
        !           350:         * It requires the tty_clk line discipline and 4.3bsd or later.
        !           351:         */
        !           352:        {       struct sgttyb ttyb;
        !           353: #if defined(LEITCHCLK)
        !           354:        int ldisc = CLKLDISC;
        !           355: #endif /* LEITCHCLK */
        !           356: 
        !           357:        if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
        !           358:                msyslog(LOG_ERR,
        !           359:                        "leitch_start: ioctl(%s, TIOCGETP): %m", leitchdev);
        !           360:                goto screwed;
        !           361:        }
        !           362:        ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
        !           363: #if defined(LEITCHCLK)
        !           364:        ttyb.sg_erase = ttyb.sg_kill = '\r';
        !           365:        ttyb.sg_flags = RAW;
        !           366: #else
        !           367:        ttyb.sg_erase = ttyb.sg_kill = '\0';
        !           368:        ttyb.sg_flags = EVENP|ODDP|CRMOD;
        !           369: #endif /* LEITCHCLK */
        !           370:        if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
        !           371:                msyslog(LOG_ERR,
        !           372:                        "leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev);
        !           373:                goto screwed;
        !           374:        }
        !           375: #if defined(LEITCHCLK)
        !           376:        if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
        !           377:                msyslog(LOG_ERR,
        !           378:                        "leitch_start: ioctl(%s, TIOCSETD): %m",leitchdev);
        !           379:                goto screwed;
        !           380:        }
        !           381: #endif /* LEITCHCLK */
        !           382:        }
        !           383: #endif /* HAVE_BSD_TTYS */
        !           384: 
        !           385:        /*
        !           386:         * Set up the structures
        !           387:         */
        !           388:        leitch->peer = peer;
        !           389:        leitch->unit = unit;
        !           390:        leitch->state = STATE_IDLE;
        !           391:        leitch->fudge1 = 15;    /* 15ms */
        !           392: 
        !           393:        leitch->leitchio.clock_recv = leitch_receive;
        !           394:        leitch->leitchio.srcclock = (caddr_t) leitch;
        !           395:        leitch->leitchio.datalen = 0;
        !           396:        leitch->leitchio.fd = fd232;
        !           397:        if (!io_addclock(&leitch->leitchio)) {
        !           398:                leitch->leitchio.fd = -1;
        !           399:                goto screwed;
        !           400:        }
        !           401: 
        !           402:        /*
        !           403:         * All done.  Initialize a few random peer variables, then
        !           404:         * return success.
        !           405:         */
        !           406:        peer->precision = PRECISION;
        !           407:        peer->stratum = stratumtouse[unit];
        !           408:        peer->refid = refid[unit];
        !           409:        unitinuse[unit] = 1;
        !           410:        return(1);
        !           411: 
        !           412:        /*
        !           413:         * Something broke; abandon ship.
        !           414:         */
        !           415:     screwed:
        !           416:        close(fd232);
        !           417:        return(0);
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * leitch_receive - receive data from the serial interface on a leitch
        !           422:  * clock
        !           423:  */
        !           424: static void
        !           425: leitch_receive(
        !           426:        struct recvbuf *rbufp
        !           427:        )
        !           428: {
        !           429:        struct leitchunit *leitch = (struct leitchunit *)rbufp->recv_srcclock;
        !           430: 
        !           431: #ifdef DEBUG
        !           432:        if (debug)
        !           433:            fprintf(stderr, "leitch_recieve(%*.*s)\n", 
        !           434:                    rbufp->recv_length, rbufp->recv_length,
        !           435:                    rbufp->recv_buffer);
        !           436: #endif
        !           437:        if (rbufp->recv_length != 7)
        !           438:            return; /* The date is return with a trailing newline,
        !           439:                       discard it. */
        !           440: 
        !           441:        switch (leitch->state) {
        !           442:            case STATE_IDLE:    /* unexpected, discard and resync */
        !           443:                return;
        !           444:            case STATE_DATE:
        !           445:                if (!leitch_get_date(rbufp,leitch)) {
        !           446:                        leitch->state = STATE_IDLE;
        !           447:                        break;
        !           448:                }
        !           449:                leitch_send(leitch,"T\r");
        !           450: #ifdef DEBUG
        !           451:                if (debug)
        !           452:                    fprintf(stderr, "%u\n",leitch->yearday);
        !           453: #endif
        !           454:                leitch->state = STATE_TIME1;
        !           455:                break;
        !           456:            case STATE_TIME1:
        !           457:                if (!leitch_get_time(rbufp,leitch,1)) {
        !           458:                }
        !           459:                if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
        !           460:                               leitch->second, 1, rbufp->recv_time.l_ui,
        !           461:                               &leitch->yearstart, &leitch->reftime1.l_ui)) {
        !           462:                        leitch->state = STATE_IDLE;
        !           463:                        break;
        !           464:                }
        !           465:                leitch->reftime1.l_uf = 0;
        !           466: #ifdef DEBUG
        !           467:                if (debug)
        !           468:                    fprintf(stderr, "%lu\n", (u_long)leitch->reftime1.l_ui);
        !           469: #endif
        !           470:                MSUTOTSF(leitch->fudge1, leitch->reftime1.l_uf);
        !           471:                leitch->codetime1 = rbufp->recv_time;
        !           472:                leitch->state = STATE_TIME2;
        !           473:                break;
        !           474:            case STATE_TIME2:
        !           475:                if (!leitch_get_time(rbufp,leitch,2)) {
        !           476:                }
        !           477:                if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
        !           478:                               leitch->second, 1, rbufp->recv_time.l_ui,
        !           479:                               &leitch->yearstart, &leitch->reftime2.l_ui)) {
        !           480:                        leitch->state = STATE_IDLE;
        !           481:                        break;
        !           482:                }
        !           483: #ifdef DEBUG
        !           484:                if (debug)
        !           485:                    fprintf(stderr, "%lu\n", (u_long)leitch->reftime2.l_ui);
        !           486: #endif
        !           487:                MSUTOTSF(leitch->fudge1, leitch->reftime2.l_uf);
        !           488:                leitch->codetime2 = rbufp->recv_time;
        !           489:                leitch->state = STATE_TIME3;
        !           490:                break;
        !           491:            case STATE_TIME3:
        !           492:                if (!leitch_get_time(rbufp,leitch,3)) {
        !           493:                }
        !           494:                if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
        !           495:                               leitch->second, GMT, rbufp->recv_time.l_ui,
        !           496:                               &leitch->yearstart, &leitch->reftime3.l_ui)) {
        !           497:                        leitch->state = STATE_IDLE;
        !           498:                        break;
        !           499:                }
        !           500: #ifdef DEBUG
        !           501:                if (debug)
        !           502:                    fprintf(stderr, "%lu\n", (u_long)leitch->reftime3.l_ui);
        !           503: #endif
        !           504:                MSUTOTSF(leitch->fudge1, leitch->reftime3.l_uf);
        !           505:                leitch->codetime3 = rbufp->recv_time;
        !           506:                leitch_process(leitch);
        !           507:                leitch->state = STATE_IDLE;
        !           508:                break;
        !           509:            default:
        !           510:                msyslog(LOG_ERR,
        !           511:                        "leitech_receive: invalid state %d unit %d",
        !           512:                        leitch->state, leitch->unit);
        !           513:        }
        !           514: }
        !           515: 
        !           516: /*
        !           517:  * leitch_process - process a pile of samples from the clock
        !           518:  *
        !           519:  * This routine uses a three-stage median filter to calculate offset and
        !           520:  * dispersion. reduce jitter. The dispersion is calculated as the span
        !           521:  * of the filter (max - min), unless the quality character (format 2) is
        !           522:  * non-blank, in which case the dispersion is calculated on the basis of
        !           523:  * the inherent tolerance of the internal radio oscillator, which is
        !           524:  * +-2e-5 according to the radio specifications.
        !           525:  */
        !           526: static void
        !           527: leitch_process(
        !           528:        struct leitchunit *leitch
        !           529:        )
        !           530: {
        !           531:        l_fp off;
        !           532:        l_fp tmp_fp;
        !           533:       /*double doffset;*/
        !           534: 
        !           535:        off = leitch->reftime1;
        !           536:        L_SUB(&off,&leitch->codetime1);
        !           537:        tmp_fp = leitch->reftime2;
        !           538:        L_SUB(&tmp_fp,&leitch->codetime2);
        !           539:        if (L_ISGEQ(&off,&tmp_fp))
        !           540:            off = tmp_fp;
        !           541:        tmp_fp = leitch->reftime3;
        !           542:        L_SUB(&tmp_fp,&leitch->codetime3);
        !           543: 
        !           544:        if (L_ISGEQ(&off,&tmp_fp))
        !           545:            off = tmp_fp;
        !           546:       /*LFPTOD(&off, doffset);*/
        !           547:        refclock_receive(leitch->peer);
        !           548: }
        !           549: 
        !           550: /*
        !           551:  * days_per_year
        !           552:  */
        !           553: static int
        !           554: days_per_year(
        !           555:        int year
        !           556:        )
        !           557: {
        !           558:        if (year%4) {   /* not a potential leap year */
        !           559:                return (365);
        !           560:        } else {
        !           561:                if (year % 100) {       /* is a leap year */
        !           562:                        return (366);
        !           563:                } else {        
        !           564:                        if (year % 400) {
        !           565:                                return (365);
        !           566:                        } else {
        !           567:                                return (366);
        !           568:                        }
        !           569:                }
        !           570:        }
        !           571: }
        !           572: 
        !           573: static int
        !           574: leitch_get_date(
        !           575:        struct recvbuf *rbufp,
        !           576:        struct leitchunit *leitch
        !           577:        )
        !           578: {
        !           579:        int i;
        !           580: 
        !           581:        if (rbufp->recv_length < 6)
        !           582:            return(0);
        !           583: #undef  BAD    /* confict: defined as (-1) in AIX sys/param.h */
        !           584: #define BAD(A) (rbufp->recv_buffer[A] < '0') || (rbufp->recv_buffer[A] > '9')
        !           585:        if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
        !           586:            return(0);
        !           587: #define ATOB(A) ((rbufp->recv_buffer[A])-'0')
        !           588:        leitch->year = ATOB(0)*10 + ATOB(1);
        !           589:        leitch->month = ATOB(2)*10 + ATOB(3);
        !           590:        leitch->day = ATOB(4)*10 + ATOB(5);
        !           591: 
        !           592:        /* sanity checks */
        !           593:        if (leitch->month > 12)
        !           594:            return(0);
        !           595:        if (leitch->day > days_in_month[leitch->month-1])
        !           596:            return(0);
        !           597: 
        !           598:        /* calculate yearday */
        !           599:        i = 0;
        !           600:        leitch->yearday = leitch->day;
        !           601: 
        !           602:        while ( i < (leitch->month-1) )
        !           603:            leitch->yearday += days_in_month[i++];
        !           604: 
        !           605:        if ((days_per_year((leitch->year>90?1900:2000)+leitch->year)==365) && 
        !           606:            leitch->month > 2)
        !           607:            leitch->yearday--;
        !           608: 
        !           609:        return(1);
        !           610: }
        !           611: 
        !           612: /*
        !           613:  * leitch_get_time
        !           614:  */
        !           615: static int
        !           616: leitch_get_time(
        !           617:        struct recvbuf *rbufp,
        !           618:        struct leitchunit *leitch,
        !           619:        int which
        !           620:        )
        !           621: {
        !           622:        if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
        !           623:            return(0);
        !           624:        leitch->hour = ATOB(0)*10 +ATOB(1);
        !           625:        leitch->minute = ATOB(2)*10 +ATOB(3);
        !           626:        leitch->second = ATOB(4)*10 +ATOB(5);
        !           627: 
        !           628:        if ((leitch->hour > 23) || (leitch->minute > 60) ||
        !           629:            (leitch->second > 60))
        !           630:            return(0);
        !           631:        return(1);
        !           632: }
        !           633: 
        !           634: #else
        !           635: int refclock_leitch_bs;
        !           636: #endif /* REFCLOCK */

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