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