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

1.1       misho       1: /*
                      2:  * refclock_hpgps - clock driver for HP 58503A GPS receiver
                      3:  */
                      4: 
                      5: #ifdef HAVE_CONFIG_H
                      6: # include <config.h>
                      7: #endif
                      8: 
                      9: #if defined(REFCLOCK) && defined(CLOCK_HPGPS)
                     10: 
                     11: #include "ntpd.h"
                     12: #include "ntp_io.h"
                     13: #include "ntp_refclock.h"
                     14: #include "ntp_stdlib.h"
                     15: 
                     16: #include <stdio.h>
                     17: #include <ctype.h>
                     18: 
                     19: /* Version 0.1 April  1, 1995  
                     20:  *         0.2 April 25, 1995
                     21:  *             tolerant of missing timecode response prompt and sends
                     22:  *             clear status if prompt indicates error;
                     23:  *             can use either local time or UTC from receiver;
                     24:  *             can get receiver status screen via flag4
                     25:  *
                     26:  * WARNING!: This driver is UNDER CONSTRUCTION
                     27:  * Everything in here should be treated with suspicion.
                     28:  * If it looks wrong, it probably is.
                     29:  *
                     30:  * Comments and/or questions to: Dave Vitanye
                     31:  *                               Hewlett Packard Company
                     32:  *                               dave@scd.hp.com
                     33:  *                               (408) 553-2856
                     34:  *
                     35:  * Thanks to the author of the PST driver, which was the starting point for
                     36:  * this one.
                     37:  *
                     38:  * This driver supports the HP 58503A Time and Frequency Reference Receiver.
                     39:  * This receiver uses HP SmartClock (TM) to implement an Enhanced GPS receiver.
                     40:  * The receiver accuracy when locked to GPS in normal operation is better
                     41:  * than 1 usec. The accuracy when operating in holdover is typically better
                     42:  * than 10 usec. per day.
                     43:  *
                     44:  * The same driver also handles the HP Z3801A which is available surplus
                     45:  * from the cell phone industry.  It's popular with hams.
                     46:  * It needs a different line setup: 19200 baud, 7 data bits, odd parity
                     47:  * That is selected by adding "mode 1" to the server line in ntp.conf
                     48:  * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005
                     49:  *
                     50:  *
                     51:  * The receiver should be operated with factory default settings.
                     52:  * Initial driver operation: expects the receiver to be already locked
                     53:  * to GPS, configured and able to output timecode format 2 messages.
                     54:  *
                     55:  * The driver uses the poll sequence :PTIME:TCODE? to get a response from
                     56:  * the receiver. The receiver responds with a timecode string of ASCII
                     57:  * printing characters, followed by a <cr><lf>, followed by a prompt string
                     58:  * issued by the receiver, in the following format:
                     59:  * T#yyyymmddhhmmssMFLRVcc<cr><lf>scpi > 
                     60:  *
                     61:  * The driver processes the response at the <cr> and <lf>, so what the
                     62:  * driver sees is the prompt from the previous poll, followed by this
                     63:  * timecode. The prompt from the current poll is (usually) left unread until
                     64:  * the next poll. So (except on the very first poll) the driver sees this:
                     65:  *
                     66:  * scpi > T#yyyymmddhhmmssMFLRVcc<cr><lf>
                     67:  *
                     68:  * The T is the on-time character, at 980 msec. before the next 1PPS edge.
                     69:  * The # is the timecode format type. We look for format 2.
                     70:  * Without any of the CLK or PPS stuff, then, the receiver buffer timestamp
                     71:  * at the <cr> is 24 characters later, which is about 25 msec. at 9600 bps,
                     72:  * so the first approximation for fudge time1 is nominally -0.955 seconds.
                     73:  * This number probably needs adjusting for each machine / OS type, so far:
                     74:  *  -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05
                     75:  *  -0.953175 on an HP 9000 Model 370    HP-UX 9.10 
                     76:  *
                     77:  * This receiver also provides a 1PPS signal, but I haven't figured out
                     78:  * how to deal with any of the CLK or PPS stuff yet. Stay tuned.
                     79:  *
                     80:  */
                     81: 
                     82: /*
                     83:  * Fudge Factors
                     84:  *
                     85:  * Fudge time1 is used to accomodate the timecode serial interface adjustment.
                     86:  * Fudge flag4 can be set to request a receiver status screen summary, which
                     87:  * is recorded in the clockstats file.
                     88:  */
                     89: 
                     90: /*
                     91:  * Interface definitions
                     92:  */
                     93: #define        DEVICE          "/dev/hpgps%d" /* device name and unit */
                     94: #define        SPEED232        B9600   /* uart speed (9600 baud) */
                     95: #define        SPEED232Z       B19200  /* uart speed (19200 baud) */
                     96: #define        PRECISION       (-10)   /* precision assumed (about 1 ms) */
                     97: #define        REFID           "GPS\0" /*  reference ID */
                     98: #define        DESCRIPTION     "HP 58503A GPS Time and Frequency Reference Receiver" 
                     99: 
                    100: #define SMAX            23*80+1 /* for :SYSTEM:PRINT? status screen response */
                    101: 
                    102: #define MTZONE          2       /* number of fields in timezone reply */
                    103: #define MTCODET2        12      /* number of fields in timecode format T2 */
                    104: #define NTCODET2        21      /* number of chars to checksum in format T2 */
                    105: 
                    106: /*
                    107:  * Tables to compute the day of year from yyyymmdd timecode.
                    108:  * Viva la leap.
                    109:  */
                    110: static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    111: static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    112: 
                    113: /*
                    114:  * Unit control structure
                    115:  */
                    116: struct hpgpsunit {
                    117:        int     pollcnt;        /* poll message counter */
                    118:        int     tzhour;         /* timezone offset, hours */
                    119:        int     tzminute;       /* timezone offset, minutes */
                    120:        int     linecnt;        /* set for expected multiple line responses */
                    121:        char    *lastptr;       /* pointer to receiver response data */
                    122:        char    statscrn[SMAX]; /* receiver status screen buffer */
                    123: };
                    124: 
                    125: /*
                    126:  * Function prototypes
                    127:  */
                    128: static int     hpgps_start     (int, struct peer *);
                    129: static void    hpgps_shutdown  (int, struct peer *);
                    130: static void    hpgps_receive   (struct recvbuf *);
                    131: static void    hpgps_poll      (int, struct peer *);
                    132: 
                    133: /*
                    134:  * Transfer vector
                    135:  */
                    136: struct refclock refclock_hpgps = {
                    137:        hpgps_start,            /* start up driver */
                    138:        hpgps_shutdown,         /* shut down driver */
                    139:        hpgps_poll,             /* transmit poll message */
                    140:        noentry,                /* not used (old hpgps_control) */
                    141:        noentry,                /* initialize driver */
                    142:        noentry,                /* not used (old hpgps_buginfo) */
                    143:        NOFLAGS                 /* not used */
                    144: };
                    145: 
                    146: 
                    147: /*
                    148:  * hpgps_start - open the devices and initialize data for processing
                    149:  */
                    150: static int
                    151: hpgps_start(
                    152:        int unit,
                    153:        struct peer *peer
                    154:        )
                    155: {
                    156:        register struct hpgpsunit *up;
                    157:        struct refclockproc *pp;
                    158:        int fd;
                    159:        char device[20];
                    160: 
                    161:        /*
                    162:         * Open serial port. Use CLK line discipline, if available.
                    163:         * Default is HP 58503A, mode arg selects HP Z3801A
                    164:         */
                    165:        snprintf(device, sizeof(device), DEVICE, unit);
                    166:        /* mode parameter to server config line shares ttl slot */
                    167:        if ((peer->ttl == 1)) {
                    168:                if (!(fd = refclock_open(device, SPEED232Z,
                    169:                                LDISC_CLK | LDISC_7O1)))
                    170:                        return (0);
                    171:        } else {
                    172:                if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
                    173:                        return (0);
                    174:        }
                    175:        /*
                    176:         * Allocate and initialize unit structure
                    177:         */
                    178:        up = emalloc(sizeof(*up));
                    179:        memset(up, 0, sizeof(*up));
                    180:        pp = peer->procptr;
                    181:        pp->io.clock_recv = hpgps_receive;
                    182:        pp->io.srcclock = (caddr_t)peer;
                    183:        pp->io.datalen = 0;
                    184:        pp->io.fd = fd;
                    185:        if (!io_addclock(&pp->io)) {
                    186:                close(fd);
                    187:                pp->io.fd = -1;
                    188:                free(up);
                    189:                return (0);
                    190:        }
                    191:        pp->unitptr = (caddr_t)up;
                    192: 
                    193:        /*
                    194:         * Initialize miscellaneous variables
                    195:         */
                    196:        peer->precision = PRECISION;
                    197:        pp->clockdesc = DESCRIPTION;
                    198:        memcpy((char *)&pp->refid, REFID, 4);
                    199:        up->tzhour = 0;
                    200:        up->tzminute = 0;
                    201: 
                    202:        *up->statscrn = '\0';
                    203:        up->lastptr = up->statscrn;
                    204:        up->pollcnt = 2;
                    205: 
                    206:        /*
                    207:         * Get the identifier string, which is logged but otherwise ignored,
                    208:         * and get the local timezone information
                    209:         */
                    210:        up->linecnt = 1;
                    211:        if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)
                    212:            refclock_report(peer, CEVNT_FAULT);
                    213: 
                    214:        return (1);
                    215: }
                    216: 
                    217: 
                    218: /*
                    219:  * hpgps_shutdown - shut down the clock
                    220:  */
                    221: static void
                    222: hpgps_shutdown(
                    223:        int unit,
                    224:        struct peer *peer
                    225:        )
                    226: {
                    227:        register struct hpgpsunit *up;
                    228:        struct refclockproc *pp;
                    229: 
                    230:        pp = peer->procptr;
                    231:        up = (struct hpgpsunit *)pp->unitptr;
                    232:        if (-1 != pp->io.fd)
                    233:                io_closeclock(&pp->io);
                    234:        if (NULL != up)
                    235:                free(up);
                    236: }
                    237: 
                    238: 
                    239: /*
                    240:  * hpgps_receive - receive data from the serial interface
                    241:  */
                    242: static void
                    243: hpgps_receive(
                    244:        struct recvbuf *rbufp
                    245:        )
                    246: {
                    247:        register struct hpgpsunit *up;
                    248:        struct refclockproc *pp;
                    249:        struct peer *peer;
                    250:        l_fp trtmp;
                    251:        char tcodechar1;        /* identifies timecode format */
                    252:        char tcodechar2;        /* identifies timecode format */
                    253:        char timequal;          /* time figure of merit: 0-9 */
                    254:        char freqqual;          /* frequency figure of merit: 0-3 */
                    255:        char leapchar;          /* leapsecond: + or 0 or - */
                    256:        char servchar;          /* request for service: 0 = no, 1 = yes */
                    257:        char syncchar;          /* time info is invalid: 0 = no, 1 = yes */
                    258:        short expectedsm;       /* expected timecode byte checksum */
                    259:        short tcodechksm;       /* computed timecode byte checksum */
                    260:        int i,m,n;
                    261:        int month, day, lastday;
                    262:        char *tcp;              /* timecode pointer (skips over the prompt) */
                    263:        char prompt[BMAX];      /* prompt in response from receiver */
                    264: 
                    265:        /*
                    266:         * Initialize pointers and read the receiver response
                    267:         */
                    268:        peer = (struct peer *)rbufp->recv_srcclock;
                    269:        pp = peer->procptr;
                    270:        up = (struct hpgpsunit *)pp->unitptr;
                    271:        *pp->a_lastcode = '\0';
                    272:        pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
                    273: 
                    274: #ifdef DEBUG
                    275:        if (debug)
                    276:            printf("hpgps: lencode: %d timecode:%s\n",
                    277:                   pp->lencode, pp->a_lastcode);
                    278: #endif
                    279: 
                    280:        /*
                    281:         * If there's no characters in the reply, we can quit now
                    282:         */
                    283:        if (pp->lencode == 0)
                    284:            return;
                    285: 
                    286:        /*
                    287:         * If linecnt is greater than zero, we are getting information only,
                    288:         * such as the receiver identification string or the receiver status
                    289:         * screen, so put the receiver response at the end of the status
                    290:         * screen buffer. When we have the last line, write the buffer to
                    291:         * the clockstats file and return without further processing.
                    292:         *
                    293:         * If linecnt is zero, we are expecting either the timezone
                    294:         * or a timecode. At this point, also write the response
                    295:         * to the clockstats file, and go on to process the prompt (if any),
                    296:         * timezone, or timecode and timestamp.
                    297:         */
                    298: 
                    299: 
                    300:        if (up->linecnt-- > 0) {
                    301:                if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) {
                    302:                        *up->lastptr++ = '\n';
                    303:                        (void)strcpy(up->lastptr, pp->a_lastcode);
                    304:                        up->lastptr += pp->lencode;
                    305:                }
                    306:                if (up->linecnt == 0) 
                    307:                    record_clock_stats(&peer->srcadr, up->statscrn);
                    308:                
                    309:                return;
                    310:        }
                    311: 
                    312:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
                    313:        pp->lastrec = trtmp;
                    314:             
                    315:        up->lastptr = up->statscrn;
                    316:        *up->lastptr = '\0';
                    317:        up->pollcnt = 2;
                    318: 
                    319:        /*
                    320:         * We get down to business: get a prompt if one is there, issue
                    321:         * a clear status command if it contains an error indication.
                    322:         * Next, check for either the timezone reply or the timecode reply
                    323:         * and decode it.  If we don't recognize the reply, or don't get the
                    324:         * proper number of decoded fields, or get an out of range timezone,
                    325:         * or if the timecode checksum is bad, then we declare bad format
                    326:         * and exit.
                    327:         *
                    328:         * Timezone format (including nominal prompt):
                    329:         * scpi > -H,-M<cr><lf>
                    330:         *
                    331:         * Timecode format (including nominal prompt):
                    332:         * scpi > T2yyyymmddhhmmssMFLRVcc<cr><lf>
                    333:         *
                    334:         */
                    335: 
                    336:        (void)strcpy(prompt,pp->a_lastcode);
                    337:        tcp = strrchr(pp->a_lastcode,'>');
                    338:        if (tcp == NULL)
                    339:            tcp = pp->a_lastcode; 
                    340:        else
                    341:            tcp++;
                    342:        prompt[tcp - pp->a_lastcode] = '\0';
                    343:        while ((*tcp == ' ') || (*tcp == '\t')) tcp++;
                    344: 
                    345:        /*
                    346:         * deal with an error indication in the prompt here
                    347:         */
                    348:        if (strrchr(prompt,'E') > strrchr(prompt,'s')){
                    349: #ifdef DEBUG
                    350:                if (debug)
                    351:                    printf("hpgps: error indicated in prompt: %s\n", prompt);
                    352: #endif
                    353:                if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
                    354:                    refclock_report(peer, CEVNT_FAULT);
                    355:        }
                    356: 
                    357:        /*
                    358:         * make sure we got a timezone or timecode format and 
                    359:         * then process accordingly
                    360:         */
                    361:        m = sscanf(tcp,"%c%c", &tcodechar1, &tcodechar2);
                    362: 
                    363:        if (m != 2){
                    364: #ifdef DEBUG
                    365:                if (debug)
                    366:                    printf("hpgps: no format indicator\n");
                    367: #endif
                    368:                refclock_report(peer, CEVNT_BADREPLY);
                    369:                return;
                    370:        }
                    371: 
                    372:        switch (tcodechar1) {
                    373: 
                    374:            case '+':
                    375:            case '-':
                    376:                m = sscanf(tcp,"%d,%d", &up->tzhour, &up->tzminute);
                    377:                if (m != MTZONE) {
                    378: #ifdef DEBUG
                    379:                        if (debug)
                    380:                            printf("hpgps: only %d fields recognized in timezone\n", m);
                    381: #endif
                    382:                        refclock_report(peer, CEVNT_BADREPLY);
                    383:                        return;
                    384:                }
                    385:                if ((up->tzhour < -12) || (up->tzhour > 13) || 
                    386:                    (up->tzminute < -59) || (up->tzminute > 59)){
                    387: #ifdef DEBUG
                    388:                        if (debug)
                    389:                            printf("hpgps: timezone %d, %d out of range\n",
                    390:                                   up->tzhour, up->tzminute);
                    391: #endif
                    392:                        refclock_report(peer, CEVNT_BADREPLY);
                    393:                        return;
                    394:                }
                    395:                return;
                    396: 
                    397:            case 'T':
                    398:                break;
                    399: 
                    400:            default:
                    401: #ifdef DEBUG
                    402:                if (debug)
                    403:                    printf("hpgps: unrecognized reply format %c%c\n",
                    404:                           tcodechar1, tcodechar2);
                    405: #endif
                    406:                refclock_report(peer, CEVNT_BADREPLY);
                    407:                return;
                    408:        } /* end of tcodechar1 switch */
                    409: 
                    410: 
                    411:        switch (tcodechar2) {
                    412: 
                    413:            case '2':
                    414:                m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx",
                    415:                           &pp->year, &month, &day, &pp->hour, &pp->minute, &pp->second,
                    416:                           &timequal, &freqqual, &leapchar, &servchar, &syncchar,
                    417:                           &expectedsm);
                    418:                n = NTCODET2;
                    419: 
                    420:                if (m != MTCODET2){
                    421: #ifdef DEBUG
                    422:                        if (debug)
                    423:                            printf("hpgps: only %d fields recognized in timecode\n", m);
                    424: #endif
                    425:                        refclock_report(peer, CEVNT_BADREPLY);
                    426:                        return;
                    427:                }
                    428:                break;
                    429: 
                    430:            default:
                    431: #ifdef DEBUG
                    432:                if (debug)
                    433:                    printf("hpgps: unrecognized timecode format %c%c\n",
                    434:                           tcodechar1, tcodechar2);
                    435: #endif
                    436:                refclock_report(peer, CEVNT_BADREPLY);
                    437:                return;
                    438:        } /* end of tcodechar2 format switch */
                    439:            
                    440:        /* 
                    441:         * Compute and verify the checksum.
                    442:         * Characters are summed starting at tcodechar1, ending at just
                    443:         * before the expected checksum.  Bail out if incorrect.
                    444:         */
                    445:        tcodechksm = 0;
                    446:        while (n-- > 0) tcodechksm += *tcp++;
                    447:        tcodechksm &= 0x00ff;
                    448: 
                    449:        if (tcodechksm != expectedsm) {
                    450: #ifdef DEBUG
                    451:                if (debug)
                    452:                    printf("hpgps: checksum %2hX doesn't match %2hX expected\n",
                    453:                           tcodechksm, expectedsm);
                    454: #endif
                    455:                refclock_report(peer, CEVNT_BADREPLY);
                    456:                return;
                    457:        }
                    458: 
                    459:        /* 
                    460:         * Compute the day of year from the yyyymmdd format.
                    461:         */
                    462:        if (month < 1 || month > 12 || day < 1) {
                    463:                refclock_report(peer, CEVNT_BADTIME);
                    464:                return;
                    465:        }
                    466: 
                    467:        if ( ! isleap_4(pp->year) ) {                           /* Y2KFixes */
                    468:                /* not a leap year */
                    469:                if (day > day1tab[month - 1]) {
                    470:                        refclock_report(peer, CEVNT_BADTIME);
                    471:                        return;
                    472:                }
                    473:                for (i = 0; i < month - 1; i++) day += day1tab[i];
                    474:                lastday = 365;
                    475:        } else {
                    476:                /* a leap year */
                    477:                if (day > day2tab[month - 1]) {
                    478:                        refclock_report(peer, CEVNT_BADTIME);
                    479:                        return;
                    480:                }
                    481:                for (i = 0; i < month - 1; i++) day += day2tab[i];
                    482:                lastday = 366;
                    483:        }
                    484: 
                    485:        /*
                    486:         * Deal with the timezone offset here. The receiver timecode is in
                    487:         * local time = UTC + :PTIME:TZONE, so SUBTRACT the timezone values.
                    488:         * For example, Pacific Standard Time is -8 hours , 0 minutes.
                    489:         * Deal with the underflows and overflows.
                    490:         */
                    491:        pp->minute -= up->tzminute;
                    492:        pp->hour -= up->tzhour;
                    493: 
                    494:        if (pp->minute < 0) {
                    495:                pp->minute += 60;
                    496:                pp->hour--;
                    497:        }
                    498:        if (pp->minute > 59) {
                    499:                pp->minute -= 60;
                    500:                pp->hour++;
                    501:        }
                    502:        if (pp->hour < 0)  {
                    503:                pp->hour += 24;
                    504:                day--;
                    505:                if (day < 1) {
                    506:                        pp->year--;
                    507:                        if ( isleap_4(pp->year) )               /* Y2KFixes */
                    508:                            day = 366;
                    509:                        else
                    510:                            day = 365;
                    511:                }
                    512:        }
                    513: 
                    514:        if (pp->hour > 23) {
                    515:                pp->hour -= 24;
                    516:                day++;
                    517:                if (day > lastday) {
                    518:                        pp->year++;
                    519:                        day = 1;
                    520:                }
                    521:        }
                    522: 
                    523:        pp->day = day;
                    524: 
                    525:        /*
                    526:         * Decode the MFLRV indicators.
                    527:         * NEED TO FIGURE OUT how to deal with the request for service,
                    528:         * time quality, and frequency quality indicators some day. 
                    529:         */
                    530:        if (syncchar != '0') {
                    531:                pp->leap = LEAP_NOTINSYNC;
                    532:        }
                    533:        else {
                    534:                pp->leap = LEAP_NOWARNING;
                    535:                switch (leapchar) {
                    536: 
                    537:                    case '0':
                    538:                        break;
                    539:                      
                    540:                    /* See http://bugs.ntp.org/1090
                    541:                     * Ignore leap announcements unless June or December.
                    542:                     * Better would be to use :GPSTime? to find the month,
                    543:                     * but that seems too likely to introduce other bugs.
                    544:                     */
                    545:                    case '+':
                    546:                        if ((month==6) || (month==12))
                    547:                            pp->leap = LEAP_ADDSECOND;
                    548:                        break;
                    549:                      
                    550:                    case '-':
                    551:                        if ((month==6) || (month==12))
                    552:                            pp->leap = LEAP_DELSECOND;
                    553:                        break;
                    554:                      
                    555:                    default:
                    556: #ifdef DEBUG
                    557:                        if (debug)
                    558:                            printf("hpgps: unrecognized leap indicator: %c\n",
                    559:                                   leapchar);
                    560: #endif
                    561:                        refclock_report(peer, CEVNT_BADTIME);
                    562:                        return;
                    563:                } /* end of leapchar switch */
                    564:        }
                    565: 
                    566:        /*
                    567:         * Process the new sample in the median filter and determine the
                    568:         * reference clock offset and dispersion. We use lastrec as both
                    569:         * the reference time and receive time in order to avoid being
                    570:         * cute, like setting the reference time later than the receive
                    571:         * time, which may cause a paranoid protocol module to chuck out
                    572:         * the data.
                    573:         */
                    574:        if (!refclock_process(pp)) {
                    575:                refclock_report(peer, CEVNT_BADTIME);
                    576:                return;
                    577:        }
                    578:        pp->lastref = pp->lastrec;
                    579:        refclock_receive(peer);
                    580: 
                    581:        /*
                    582:         * If CLK_FLAG4 is set, ask for the status screen response.
                    583:         */
                    584:        if (pp->sloppyclockflag & CLK_FLAG4){
                    585:                up->linecnt = 22; 
                    586:                if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15)
                    587:                    refclock_report(peer, CEVNT_FAULT);
                    588:        }
                    589: }
                    590: 
                    591: 
                    592: /*
                    593:  * hpgps_poll - called by the transmit procedure
                    594:  */
                    595: static void
                    596: hpgps_poll(
                    597:        int unit,
                    598:        struct peer *peer
                    599:        )
                    600: {
                    601:        register struct hpgpsunit *up;
                    602:        struct refclockproc *pp;
                    603: 
                    604:        /*
                    605:         * Time to poll the clock. The HP 58503A responds to a
                    606:         * ":PTIME:TCODE?" by returning a timecode in the format specified
                    607:         * above. If nothing is heard from the clock for two polls,
                    608:         * declare a timeout and keep going.
                    609:         */
                    610:        pp = peer->procptr;
                    611:        up = (struct hpgpsunit *)pp->unitptr;
                    612:        if (up->pollcnt == 0)
                    613:            refclock_report(peer, CEVNT_TIMEOUT);
                    614:        else
                    615:            up->pollcnt--;
                    616:        if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) {
                    617:                refclock_report(peer, CEVNT_FAULT);
                    618:        }
                    619:        else
                    620:            pp->polls++;
                    621: }
                    622: 
                    623: #else
                    624: int refclock_hpgps_bs;
                    625: #endif /* REFCLOCK */

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