Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/ntpd/ntp_refclock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ntp_refclock - processing support for reference clocks
3
 */
4
#ifdef HAVE_CONFIG_H
5
# include <config.h>
6
#endif
7
8
#include "ntpd.h"
9
#include "ntp_io.h"
10
#include "ntp_unixtime.h"
11
#include "ntp_tty.h"
12
#include "ntp_refclock.h"
13
#include "ntp_stdlib.h"
14
#include "ntp_assert.h"
15
16
#include <stdio.h>
17
18
#ifdef HAVE_SYS_IOCTL_H
19
# include <sys/ioctl.h>
20
#endif /* HAVE_SYS_IOCTL_H */
21
22
#ifdef REFCLOCK
23
24
#ifdef KERNEL_PLL
25
#include "ntp_syscall.h"
26
#endif /* KERNEL_PLL */
27
28
#ifdef HAVE_PPSAPI
29
#include "ppsapi_timepps.h"
30
#include "refclock_atom.h"
31
#endif /* HAVE_PPSAPI */
32
33
/*
34
 * Reference clock support is provided here by maintaining the fiction
35
 * that the clock is actually a peer.  As no packets are exchanged with
36
 * a reference clock, however, we replace the transmit, receive and
37
 * packet procedures with separate code to simulate them.  Routines
38
 * refclock_transmit() and refclock_receive() maintain the peer
39
 * variables in a state analogous to an actual peer and pass reference
40
 * clock data on through the filters.  Routines refclock_peer() and
41
 * refclock_unpeer() are called to initialize and terminate reference
42
 * clock associations.  A set of utility routines is included to open
43
 * serial devices, process sample data, and to perform various debugging
44
 * functions.
45
 *
46
 * The main interface used by these routines is the refclockproc
47
 * structure, which contains for most drivers the decimal equivalants
48
 * of the year, day, month, hour, second and millisecond/microsecond
49
 * decoded from the ASCII timecode.  Additional information includes
50
 * the receive timestamp, exception report, statistics tallies, etc. 
51
 * In addition, there may be a driver-specific unit structure used for
52
 * local control of the device.
53
 *
54
 * The support routines are passed a pointer to the peer structure,
55
 * which is used for all peer-specific processing and contains a
56
 * pointer to the refclockproc structure, which in turn contains a
57
 * pointer to the unit structure, if used.  The peer structure is 
58
 * identified by an interface address in the dotted quad form 
59
 * 127.127.t.u, where t is the clock type and u the unit.
60
 */
61
0
#define FUDGEFAC  .1  /* fudge correction factor */
62
#define LF    0x0a  /* ASCII LF */
63
64
int cal_enable;   /* enable refclock calibrate */
65
66
/*
67
 * Forward declarations
68
 */
69
static int refclock_cmpl_fp (const void *, const void *);
70
static int refclock_sample (struct refclockproc *);
71
static int refclock_ioctl(int, u_int);
72
73
74
/*
75
 * refclock_report - note the occurance of an event
76
 *
77
 * This routine presently just remembers the report and logs it, but
78
 * does nothing heroic for the trap handler. It tries to be a good
79
 * citizen and bothers the system log only if things change.
80
 */
81
void
82
refclock_report(
83
  struct peer *peer,
84
  int code
85
  )
86
0
{
87
0
  struct refclockproc *pp;
88
89
0
  pp = peer->procptr;
90
0
  if (pp == NULL)
91
0
    return;
92
93
0
  switch (code) {
94
95
0
  case CEVNT_TIMEOUT:
96
0
    pp->noreply++;
97
0
    break;
98
99
0
  case CEVNT_BADREPLY:
100
0
    pp->badformat++;
101
0
    break;
102
103
0
  case CEVNT_FAULT:
104
0
    break;
105
106
0
  case CEVNT_BADDATE:
107
0
  case CEVNT_BADTIME:
108
0
    pp->baddata++;
109
0
    break;
110
111
0
  default:
112
    /* ignore others */
113
0
    break;
114
0
  }
115
0
  if ((code != CEVNT_NOMINAL) && (pp->lastevent < 15))
116
0
    pp->lastevent++;
117
0
  if (pp->currentstatus != code) {
118
0
    pp->currentstatus = (u_char)code;
119
0
    report_event(PEVNT_CLOCK, peer, ceventstr(code));
120
0
  }
121
0
}
122
123
124
/*
125
 * init_refclock - initialize the reference clock drivers
126
 *
127
 * This routine calls each of the drivers in turn to initialize internal
128
 * variables, if necessary. Most drivers have nothing to say at this
129
 * point.
130
 */
131
void
132
init_refclock(void)
133
0
{
134
0
  int i;
135
136
0
  for (i = 0; i < (int)num_refclock_conf; i++)
137
0
    if (refclock_conf[i]->clock_init != noentry)
138
0
      (refclock_conf[i]->clock_init)();
139
0
}
140
141
142
/*
143
 * refclock_newpeer - initialize and start a reference clock
144
 *
145
 * This routine allocates and initializes the interface structure which
146
 * supports a reference clock in the form of an ordinary NTP peer. A
147
 * driver-specific support routine completes the initialization, if
148
 * used. Default peer variables which identify the clock and establish
149
 * its reference ID and stratum are set here. It returns one if success
150
 * and zero if the clock address is invalid or already running,
151
 * insufficient resources are available or the driver declares a bum
152
 * rap.
153
 */
154
int
155
refclock_newpeer(
156
  struct peer *peer /* peer structure pointer */
157
  )
158
0
{
159
0
  struct refclockproc *pp;
160
0
  u_char clktype;
161
0
  int unit;
162
163
  /*
164
   * Check for valid clock address. If already running, shut it
165
   * down first.
166
   */
167
0
  if (!ISREFCLOCKADR(&peer->srcadr)) {
168
0
    msyslog(LOG_ERR,
169
0
      "refclock_newpeer: clock address %s invalid",
170
0
      stoa(&peer->srcadr));
171
0
    return (0);
172
0
  }
173
0
  clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
174
0
  unit = REFCLOCKUNIT(&peer->srcadr);
175
0
  if (clktype >= num_refclock_conf ||
176
0
    refclock_conf[clktype]->clock_start == noentry) {
177
0
    msyslog(LOG_ERR,
178
0
      "refclock_newpeer: clock type %d invalid\n",
179
0
      clktype);
180
0
    return (0);
181
0
  }
182
183
  /*
184
   * Allocate and initialize interface structure
185
   */
186
0
  pp = emalloc_zero(sizeof(*pp));
187
0
  peer->procptr = pp;
188
189
  /*
190
   * Initialize structures
191
   */
192
0
  peer->refclktype = clktype;
193
0
  peer->refclkunit = (u_char)unit;
194
0
  peer->flags |= FLAG_REFCLOCK;
195
0
  peer->leap = LEAP_NOTINSYNC;
196
0
  peer->stratum = STRATUM_REFCLOCK;
197
0
  peer->ppoll = peer->maxpoll;
198
0
  pp->type = clktype;
199
0
  pp->conf = refclock_conf[clktype];
200
0
  pp->timestarted = current_time;
201
0
  pp->io.fd = -1;
202
203
  /*
204
   * Set peer.pmode based on the hmode. For appearances only.
205
   */
206
0
  switch (peer->hmode) {
207
0
  case MODE_ACTIVE:
208
0
    peer->pmode = MODE_PASSIVE;
209
0
    break;
210
211
0
  default:
212
0
    peer->pmode = MODE_SERVER;
213
0
    break;
214
0
  }
215
216
  /*
217
   * Do driver dependent initialization. The above defaults
218
   * can be wiggled, then finish up for consistency.
219
   */
220
0
  if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
221
0
    refclock_unpeer(peer);
222
0
    return (0);
223
0
  }
224
0
  peer->refid = pp->refid;
225
0
  return (1);
226
0
}
227
228
229
/*
230
 * refclock_unpeer - shut down a clock
231
 */
232
void
233
refclock_unpeer(
234
  struct peer *peer /* peer structure pointer */
235
  )
236
0
{
237
0
  u_char clktype;
238
0
  int unit;
239
240
  /*
241
   * Wiggle the driver to release its resources, then give back
242
   * the interface structure.
243
   */
244
0
  if (NULL == peer->procptr)
245
0
    return;
246
247
0
  clktype = peer->refclktype;
248
0
  unit = peer->refclkunit;
249
0
  if (refclock_conf[clktype]->clock_shutdown != noentry)
250
0
    (refclock_conf[clktype]->clock_shutdown)(unit, peer);
251
0
  free(peer->procptr);
252
0
  peer->procptr = NULL;
253
0
}
254
255
256
/*
257
 * refclock_timer - called once per second for housekeeping.
258
 */
259
void
260
refclock_timer(
261
  struct peer *p
262
  )
263
0
{
264
0
  struct refclockproc * pp;
265
0
  int     unit;
266
267
0
  unit = p->refclkunit;
268
0
  pp = p->procptr;
269
0
  if (pp->conf->clock_timer != noentry)
270
0
    (*pp->conf->clock_timer)(unit, p);
271
0
  if (pp->action != NULL && pp->nextaction <= current_time)
272
0
    (*pp->action)(p);
273
0
}
274
  
275
276
/*
277
 * refclock_transmit - simulate the transmit procedure
278
 *
279
 * This routine implements the NTP transmit procedure for a reference
280
 * clock. This provides a mechanism to call the driver at the NTP poll
281
 * interval, as well as provides a reachability mechanism to detect a
282
 * broken radio or other madness.
283
 */
284
void
285
refclock_transmit(
286
  struct peer *peer /* peer structure pointer */
287
  )
288
0
{
289
0
  u_char clktype;
290
0
  int unit;
291
292
0
  clktype = peer->refclktype;
293
0
  unit = peer->refclkunit;
294
0
  peer->sent++;
295
0
  get_systime(&peer->xmt);
296
297
  /*
298
   * This is a ripoff of the peer transmit routine, but
299
   * specialized for reference clocks. We do a little less
300
   * protocol here and call the driver-specific transmit routine.
301
   */
302
0
  if (peer->burst == 0) {
303
0
    u_char oreach;
304
0
#ifdef DEBUG
305
0
    if (debug)
306
0
      printf("refclock_transmit: at %ld %s\n",
307
0
          current_time, stoa(&(peer->srcadr)));
308
0
#endif
309
310
    /*
311
     * Update reachability and poll variables like the
312
     * network code.
313
     */
314
0
    oreach = peer->reach & 0xfe;
315
0
    peer->reach <<= 1;
316
0
    if (!(peer->reach & 0x0f))
317
0
      clock_filter(peer, 0., 0., MAXDISPERSE);
318
0
    peer->outdate = current_time;
319
0
    if (!peer->reach) {
320
0
      if (oreach) {
321
0
        report_event(PEVNT_UNREACH, peer, NULL);
322
0
        peer->timereachable = current_time;
323
0
      }
324
0
    } else {
325
0
      if (peer->flags & FLAG_BURST)
326
0
        peer->burst = NSTAGE;
327
0
    }
328
0
  } else {
329
0
    peer->burst--;
330
0
  }
331
0
  if (refclock_conf[clktype]->clock_poll != noentry)
332
0
    (refclock_conf[clktype]->clock_poll)(unit, peer);
333
0
  poll_update(peer, peer->hpoll);
334
0
}
335
336
337
/*
338
 * Compare two doubles - used with qsort()
339
 */
340
static int
341
refclock_cmpl_fp(
342
  const void *p1,
343
  const void *p2
344
  )
345
0
{
346
0
  const double *dp1 = (const double *)p1;
347
0
  const double *dp2 = (const double *)p2;
348
349
0
  if (*dp1 < *dp2)
350
0
    return -1;
351
0
  if (*dp1 > *dp2)
352
0
    return 1;
353
0
  return 0;
354
0
}
355
356
357
/*
358
 * refclock_process_offset - update median filter
359
 *
360
 * This routine uses the given offset and timestamps to construct a new
361
 * entry in the median filter circular buffer. Samples that overflow the
362
 * filter are quietly discarded.
363
 */
364
void
365
refclock_process_offset(
366
  struct refclockproc *pp,  /* refclock structure pointer */
367
  l_fp lasttim,     /* last timecode timestamp */
368
  l_fp lastrec,     /* last receive timestamp */
369
  double fudge
370
  )
371
0
{
372
0
  l_fp lftemp;
373
0
  double doffset;
374
375
0
  pp->lastrec = lastrec;
376
0
  lftemp = lasttim;
377
0
  L_SUB(&lftemp, &lastrec);
378
0
  LFPTOD(&lftemp, doffset);
379
0
  SAMPLE(doffset + fudge);
380
0
}
381
382
383
/*
384
 * refclock_process - process a sample from the clock
385
 * refclock_process_f - refclock_process with other than time1 fudge
386
 *
387
 * This routine converts the timecode in the form days, hours, minutes,
388
 * seconds and milliseconds/microseconds to internal timestamp format,
389
 * then constructs a new entry in the median filter circular buffer.
390
 * Return success (1) if the data are correct and consistent with the
391
 * converntional calendar.
392
 *
393
 * Important for PPS users: Normally, the pp->lastrec is set to the
394
 * system time when the on-time character is received and the pp->year,
395
 * ..., pp->second decoded and the seconds fraction pp->nsec in
396
 * nanoseconds). When a PPS offset is available, pp->nsec is forced to
397
 * zero and the fraction for pp->lastrec is set to the PPS offset.
398
 */
399
int
400
refclock_process_f(
401
  struct refclockproc *pp,  /* refclock structure pointer */
402
  double fudge
403
  )
404
0
{
405
0
  l_fp offset, ltemp;
406
407
  /*
408
   * Compute the timecode timestamp from the days, hours, minutes,
409
   * seconds and milliseconds/microseconds of the timecode. Use
410
   * clocktime() for the aggregate seconds and the msec/usec for
411
   * the fraction, when present. Note that this code relies on the
412
   * filesystem time for the years and does not use the years of
413
   * the timecode.
414
   */
415
0
  if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
416
0
    pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
417
0
    return (0);
418
419
0
  offset.l_uf = 0;
420
0
  DTOLFP(pp->nsec / 1e9, &ltemp);
421
0
  L_ADD(&offset, &ltemp);
422
0
  refclock_process_offset(pp, offset, pp->lastrec, fudge);
423
0
  return (1);
424
0
}
425
426
427
int
428
refclock_process(
429
  struct refclockproc *pp   /* refclock structure pointer */
430
)
431
0
{
432
0
  return refclock_process_f(pp, pp->fudgetime1);
433
0
}
434
435
436
/*
437
 * refclock_sample - process a pile of samples from the clock
438
 *
439
 * This routine implements a recursive median filter to suppress spikes
440
 * in the data, as well as determine a performance statistic. It
441
 * calculates the mean offset and RMS jitter. A time adjustment
442
 * fudgetime1 can be added to the final offset to compensate for various
443
 * systematic errors. The routine returns the number of samples
444
 * processed, which could be zero.
445
 */
446
static int
447
refclock_sample(
448
  struct refclockproc *pp   /* refclock structure pointer */
449
  )
450
0
{
451
0
  size_t  i, j, k, m, n;
452
0
  double  off[MAXSTAGE];
453
0
  double  offset;
454
455
  /*
456
   * Copy the raw offsets and sort into ascending order. Don't do
457
   * anything if the buffer is empty.
458
   */
459
0
  n = 0;
460
0
  while (pp->codeproc != pp->coderecv) {
461
0
    pp->codeproc = (pp->codeproc + 1) % MAXSTAGE;
462
0
    off[n] = pp->filter[pp->codeproc];
463
0
    n++;
464
0
  }
465
0
  if (n == 0)
466
0
    return (0);
467
468
0
  if (n > 1)
469
0
    qsort(off, n, sizeof(off[0]), refclock_cmpl_fp);
470
471
  /*
472
   * Reject the furthest from the median of the samples until
473
   * approximately 60 percent of the samples remain.
474
   */
475
0
  i = 0; j = n;
476
0
  m = n - (n * 4) / 10;
477
0
  while ((j - i) > m) {
478
0
    offset = off[(j + i) / 2];
479
0
    if (off[j - 1] - offset < offset - off[i])
480
0
      i++; /* reject low end */
481
0
    else
482
0
      j--; /* reject high end */
483
0
  }
484
485
  /*
486
   * Determine the offset and jitter.
487
   */
488
0
  pp->offset = 0;
489
0
  pp->jitter = 0;
490
0
  for (k = i; k < j; k++) {
491
0
    pp->offset += off[k];
492
0
    if (k > i)
493
0
      pp->jitter += SQUARE(off[k] - off[k - 1]);
494
0
  }
495
0
  pp->offset /= m;
496
0
  pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision));
497
0
#ifdef DEBUG
498
0
  if (debug)
499
0
    printf(
500
0
        "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
501
0
        (int)n, pp->offset, pp->disp, pp->jitter);
502
0
#endif
503
0
  return (int)n;
504
0
}
505
506
507
/*
508
 * refclock_receive - simulate the receive and packet procedures
509
 *
510
 * This routine simulates the NTP receive and packet procedures for a
511
 * reference clock. This provides a mechanism in which the ordinary NTP
512
 * filter, selection and combining algorithms can be used to suppress
513
 * misbehaving radios and to mitigate between them when more than one is
514
 * available for backup.
515
 */
516
void
517
refclock_receive(
518
  struct peer *peer /* peer structure pointer */
519
  )
520
0
{
521
0
  struct refclockproc *pp;
522
523
0
#ifdef DEBUG
524
0
  if (debug)
525
0
    printf("refclock_receive: at %lu %s\n",
526
0
        current_time, stoa(&peer->srcadr));
527
0
#endif
528
529
  /*
530
   * Do a little sanity dance and update the peer structure. Groom
531
   * the median filter samples and give the data to the clock
532
   * filter.
533
   */
534
0
  pp = peer->procptr;
535
0
  peer->leap = pp->leap;
536
0
  if (peer->leap == LEAP_NOTINSYNC)
537
0
    return;
538
539
0
  peer->received++;
540
0
  peer->timereceived = current_time;
541
0
  if (!peer->reach) {
542
0
    report_event(PEVNT_REACH, peer, NULL);
543
0
    peer->timereachable = current_time;
544
0
  }
545
0
  peer->reach |= 1;
546
0
  peer->reftime = pp->lastref;
547
0
  peer->aorg = pp->lastrec;
548
0
  peer->rootdisp = pp->disp;
549
0
  get_systime(&peer->dst);
550
0
  if (!refclock_sample(pp))
551
0
    return;
552
553
0
  clock_filter(peer, pp->offset, 0., pp->jitter);
554
0
  if (cal_enable && fabs(last_offset) < sys_mindisp && sys_peer !=
555
0
      NULL) {
556
0
    if (sys_peer->refclktype == REFCLK_ATOM_PPS &&
557
0
        peer->refclktype != REFCLK_ATOM_PPS)
558
0
      pp->fudgetime1 -= pp->offset * FUDGEFAC;
559
0
  }
560
0
}
561
562
563
/*
564
 * refclock_gtlin - groom next input line and extract timestamp
565
 *
566
 * This routine processes the timecode received from the clock and
567
 * strips the parity bit and control characters. It returns the number
568
 * of characters in the line followed by a NULL character ('\0'), which
569
 * is not included in the count. In case of an empty line, the previous
570
 * line is preserved.
571
 */
572
int
573
refclock_gtlin(
574
  struct recvbuf *rbufp,  /* receive buffer pointer */
575
  char  *lineptr, /* current line pointer */
576
  int bmax,   /* remaining characters in line */
577
  l_fp  *tsptr    /* pointer to timestamp returned */
578
  )
579
0
{
580
0
  const char *sp, *spend;
581
0
  char     *dp, *dpend;
582
0
  int         dlen;
583
584
0
  if (bmax <= 0)
585
0
    return (0);
586
587
0
  dp    = lineptr;
588
0
  dpend = dp + bmax - 1; /* leave room for NUL pad */
589
0
  sp    = (const char *)rbufp->recv_buffer;
590
0
  spend = sp + rbufp->recv_length;
591
592
0
  while (sp != spend && dp != dpend) {
593
0
    char c;
594
    
595
0
    c = *sp++ & 0x7f;
596
0
    if (c >= 0x20 && c < 0x7f)
597
0
      *dp++ = c;
598
0
  }
599
  /* Get length of data written to the destination buffer. If
600
   * zero, do *not* place a NUL byte to preserve the previous
601
   * buffer content.
602
   */
603
0
  dlen = dp - lineptr;
604
0
  if (dlen)
605
0
      *dp  = '\0';
606
0
  *tsptr = rbufp->recv_time;
607
0
  DPRINTF(2, ("refclock_gtlin: fd %d time %s timecode %d %s\n",
608
0
        rbufp->fd, ulfptoa(&rbufp->recv_time, 6), dlen,
609
0
        (dlen != 0)
610
0
      ? lineptr
611
0
      : ""));
612
0
  return (dlen);
613
0
}
614
615
616
/*
617
 * refclock_gtraw - get next line/chunk of data
618
 *
619
 * This routine returns the raw data received from the clock in both
620
 * canonical or raw modes. The terminal interface routines map CR to LF.
621
 * In canonical mode this results in two lines, one containing data
622
 * followed by LF and another containing only LF. In raw mode the
623
 * interface routines can deliver arbitraty chunks of data from one
624
 * character to a maximum specified by the calling routine. In either
625
 * mode the routine returns the number of characters in the line
626
 * followed by a NULL character ('\0'), which is not included in the
627
 * count.
628
 *
629
 * *tsptr receives a copy of the buffer timestamp.
630
 */
631
int
632
refclock_gtraw(
633
  struct recvbuf *rbufp,  /* receive buffer pointer */
634
  char  *lineptr, /* current line pointer */
635
  int bmax,   /* remaining characters in line */
636
  l_fp  *tsptr    /* pointer to timestamp returned */
637
  )
638
0
{
639
0
  if (bmax <= 0)
640
0
    return (0);
641
0
  bmax -= 1; /* leave room for trailing NUL */
642
0
  if (bmax > rbufp->recv_length)
643
0
    bmax = rbufp->recv_length;
644
0
  memcpy(lineptr, rbufp->recv_buffer, bmax);
645
0
  lineptr[bmax] = '\0';
646
647
0
  *tsptr = rbufp->recv_time;
648
0
  DPRINTF(2, ("refclock_gtraw: fd %d time %s timecode %d %s\n",
649
0
        rbufp->fd, ulfptoa(&rbufp->recv_time, 6), bmax,
650
0
        lineptr));
651
0
  return (bmax);
652
0
}
653
654
655
/*
656
 * indicate_refclock_packet()
657
 *
658
 * Passes a fragment of refclock input read from the device to the
659
 * driver direct input routine, which may consume it (batch it for
660
 * queuing once a logical unit is assembled).  If it is not so
661
 * consumed, queue it for the driver's receive entrypoint.
662
 *
663
 * The return value is TRUE if the data has been consumed as a fragment
664
 * and should not be counted as a received packet.
665
 */
666
int
667
indicate_refclock_packet(
668
  struct refclockio * rio,
669
  struct recvbuf *  rb
670
  )
671
0
{
672
  /* Does this refclock use direct input routine? */
673
0
  if (rio->io_input != NULL && (*rio->io_input)(rb) == 0) {
674
    /*
675
     * data was consumed - nothing to pass up
676
     * into block input machine
677
     */
678
0
    freerecvbuf(rb);
679
680
0
    return TRUE;
681
0
  }
682
0
  add_full_recv_buffer(rb);
683
684
0
  return FALSE;
685
0
}
686
687
688
/*
689
 * process_refclock_packet()
690
 *
691
 * Used for deferred processing of 'io_input' on systems where threading
692
 * is used (notably Windows). This is acting as a trampoline to make the
693
 * real calls to the refclock functions.
694
 */
695
#ifdef HAVE_IO_COMPLETION_PORT
696
void
697
process_refclock_packet(
698
  struct recvbuf * rb
699
  )
700
{
701
  struct refclockio * rio;
702
703
  /* get the refclockio structure from the receive buffer */
704
  rio  = &rb->recv_peer->procptr->io;
705
706
  /* call 'clock_recv' if either there is no input function or the
707
   * raw input function tells us to feed the packet to the
708
   * receiver.
709
   */
710
  if (rio->io_input == NULL || (*rio->io_input)(rb) != 0) {
711
    rio->recvcount++;
712
    packets_received++;
713
    handler_pkts++;
714
    (*rio->clock_recv)(rb);
715
  }
716
}
717
#endif  /* HAVE_IO_COMPLETION_PORT */
718
719
720
/*
721
 * The following code does not apply to WINNT & VMS ...
722
 */
723
#if !defined(SYS_VXWORKS) && !defined(SYS_WINNT)
724
#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
725
726
/*
727
 * refclock_open - open serial port for reference clock
728
 *
729
 * This routine opens a serial port for I/O and sets default options. It
730
 * returns the file descriptor if successful, or logs an error and
731
 * returns -1.
732
 */
733
int
734
refclock_open(
735
  const char  *dev, /* device name pointer */
736
  u_int   speed,  /* serial port speed (code) */
737
  u_int   lflags  /* line discipline flags */
738
  )
739
0
{
740
0
  int fd;
741
0
  int omode;
742
0
#ifdef O_NONBLOCK
743
0
  char  trash[128]; /* litter bin for old input data */
744
0
#endif
745
746
  /*
747
   * Open serial port and set default options
748
   */
749
0
  omode = O_RDWR;
750
0
#ifdef O_NONBLOCK
751
0
  omode |= O_NONBLOCK;
752
0
#endif
753
0
#ifdef O_NOCTTY
754
0
  omode |= O_NOCTTY;
755
0
#endif
756
757
0
  fd = open(dev, omode, 0777);
758
  /* refclock_open() long returned 0 on failure, avoid it. */
759
0
  if (0 == fd) {
760
0
    fd = dup(0);
761
0
    SAVE_ERRNO(
762
0
      close(0);
763
0
    )
764
0
  }
765
0
  if (fd < 0) {
766
0
    SAVE_ERRNO(
767
0
      msyslog(LOG_ERR, "refclock_open %s: %m", dev);
768
0
    )
769
0
    return -1;
770
0
  }
771
0
  if (!refclock_setup(fd, speed, lflags)) {
772
0
    close(fd);
773
0
    return -1;
774
0
  }
775
0
  if (!refclock_ioctl(fd, lflags)) {
776
0
    close(fd);
777
0
    return -1;
778
0
  }
779
0
#ifdef O_NONBLOCK
780
  /*
781
   * We want to make sure there is no pending trash in the input
782
   * buffer. Since we have non-blocking IO available, this is a
783
   * good moment to read and dump all available outdated stuff
784
   * that might have become toxic for the driver.
785
   */
786
0
  while (read(fd, trash, sizeof(trash)) > 0 || errno == EINTR)
787
0
    /*NOP*/;
788
0
#endif
789
0
  return fd;
790
0
}
791
792
793
/*
794
 * refclock_setup - initialize terminal interface structure
795
 */
796
int
797
refclock_setup(
798
  int fd,   /* file descriptor */
799
  u_int speed,    /* serial port speed (code) */
800
  u_int lflags    /* line discipline flags */
801
  )
802
0
{
803
0
  int i;
804
0
  TTY  ttyb, *ttyp;
805
806
  /*
807
   * By default, the serial line port is initialized in canonical
808
   * (line-oriented) mode at specified line speed, 8 bits and no
809
   * parity. LF ends the line and CR is mapped to LF. The break,
810
   * erase and kill functions are disabled. There is a different
811
   * section for each terminal interface, as selected at compile
812
   * time. The flag bits can be used to set raw mode and echo.
813
   */
814
0
  ttyp = &ttyb;
815
0
#ifdef HAVE_TERMIOS
816
817
  /*
818
   * POSIX serial line parameters (termios interface)
819
   */
820
0
  if (tcgetattr(fd, ttyp) < 0) {
821
0
    SAVE_ERRNO(
822
0
      msyslog(LOG_ERR,
823
0
        "refclock_setup fd %d tcgetattr: %m",
824
0
        fd);
825
0
    )
826
0
    return FALSE;
827
0
  }
828
829
  /*
830
   * Set canonical mode and local connection; set specified speed,
831
   * 8 bits and no parity; map CR to NL; ignore break.
832
   */
833
0
  if (speed) {
834
0
    u_int ltemp = 0;
835
836
0
    ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
837
0
    ttyp->c_oflag = 0;
838
0
    ttyp->c_cflag = CS8 | CLOCAL | CREAD;
839
0
    if (lflags & LDISC_7O1) {
840
      /* HP Z3801A needs 7-bit, odd parity */
841
0
      ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD;
842
0
    }
843
0
    cfsetispeed(&ttyb, speed);
844
0
    cfsetospeed(&ttyb, speed);
845
0
    for (i = 0; i < NCCS; ++i)
846
0
      ttyp->c_cc[i] = '\0';
847
848
0
#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
849
850
    /*
851
     * If we have modem control, check to see if modem leads
852
     * are active; if so, set remote connection. This is
853
     * necessary for the kernel pps mods to work.
854
     */
855
0
    if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
856
0
      msyslog(LOG_ERR,
857
0
          "refclock_setup fd %d TIOCMGET: %m", fd);
858
0
#ifdef DEBUG
859
0
    if (debug)
860
0
      printf("refclock_setup fd %d modem status: 0x%x\n",
861
0
          fd, ltemp);
862
0
#endif
863
0
    if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE)
864
0
      ttyp->c_cflag &= ~CLOCAL;
865
0
#endif /* TIOCMGET */
866
0
  }
867
868
  /*
869
   * Set raw and echo modes. These can be changed on-fly.
870
   */
871
0
  ttyp->c_lflag = ICANON;
872
0
  if (lflags & LDISC_RAW) {
873
0
    ttyp->c_lflag = 0;
874
0
    ttyp->c_iflag = 0;
875
0
    ttyp->c_cc[VMIN] = 1;
876
0
  }
877
0
  if (lflags & LDISC_ECHO)
878
0
    ttyp->c_lflag |= ECHO;
879
0
  if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
880
0
    SAVE_ERRNO(
881
0
      msyslog(LOG_ERR,
882
0
        "refclock_setup fd %d TCSANOW: %m",
883
0
        fd);
884
0
    )
885
0
    return FALSE;
886
0
  }
887
888
  /*
889
   * flush input and output buffers to discard any outdated stuff
890
   * that might have become toxic for the driver. Failing to do so
891
   * is logged, but we keep our fingers crossed otherwise.
892
   */
893
0
  if (tcflush(fd, TCIOFLUSH) < 0)
894
0
    msyslog(LOG_ERR, "refclock_setup fd %d tcflush(): %m",
895
0
      fd);
896
0
#endif /* HAVE_TERMIOS */
897
898
#ifdef HAVE_SYSV_TTYS
899
900
  /*
901
   * System V serial line parameters (termio interface)
902
   *
903
   */
904
  if (ioctl(fd, TCGETA, ttyp) < 0) {
905
    SAVE_ERRNO(
906
      msyslog(LOG_ERR,
907
        "refclock_setup fd %d TCGETA: %m",
908
        fd);
909
    )
910
    return FALSE;
911
  }
912
913
  /*
914
   * Set canonical mode and local connection; set specified speed,
915
   * 8 bits and no parity; map CR to NL; ignore break.
916
   */
917
  if (speed) {
918
    u_int ltemp = 0;
919
920
    ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
921
    ttyp->c_oflag = 0;
922
    ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
923
    for (i = 0; i < NCCS; ++i)
924
      ttyp->c_cc[i] = '\0';
925
926
#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
927
928
    /*
929
     * If we have modem control, check to see if modem leads
930
     * are active; if so, set remote connection. This is
931
     * necessary for the kernel pps mods to work.
932
     */
933
    if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
934
      msyslog(LOG_ERR,
935
          "refclock_setup fd %d TIOCMGET: %m", fd);
936
#ifdef DEBUG
937
    if (debug)
938
      printf("refclock_setup fd %d modem status: %x\n",
939
          fd, ltemp);
940
#endif
941
    if (ltemp & TIOCM_DSR)
942
      ttyp->c_cflag &= ~CLOCAL;
943
#endif /* TIOCMGET */
944
  }
945
946
  /*
947
   * Set raw and echo modes. These can be changed on-fly.
948
   */
949
  ttyp->c_lflag = ICANON;
950
  if (lflags & LDISC_RAW) {
951
    ttyp->c_lflag = 0;
952
    ttyp->c_iflag = 0;
953
    ttyp->c_cc[VMIN] = 1;
954
  }
955
  if (ioctl(fd, TCSETA, ttyp) < 0) {
956
    SAVE_ERRNO(
957
      msyslog(LOG_ERR,
958
        "refclock_setup fd %d TCSETA: %m", fd);
959
    )
960
    return FALSE;
961
  }
962
#endif /* HAVE_SYSV_TTYS */
963
964
#ifdef HAVE_BSD_TTYS
965
966
  /*
967
   * 4.3bsd serial line parameters (sgttyb interface)
968
   */
969
  if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
970
    SAVE_ERRNO(
971
      msyslog(LOG_ERR,
972
        "refclock_setup fd %d TIOCGETP: %m",
973
        fd);
974
    )
975
    return FALSE;
976
  }
977
  if (speed)
978
    ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
979
  ttyp->sg_flags = EVENP | ODDP | CRMOD;
980
  if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
981
    SAVE_ERRNO(
982
      msyslog(LOG_ERR, "refclock_setup TIOCSETP: %m");
983
    )
984
    return FALSE;
985
  }
986
#endif /* HAVE_BSD_TTYS */
987
0
  return(1);
988
0
}
989
#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
990
991
992
/*
993
 * refclock_ioctl - set serial port control functions
994
 *
995
 * This routine attempts to hide the internal, system-specific details
996
 * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
997
 * (sgtty) interfaces with varying degrees of success. The routine sets
998
 * up optional features such as tty_clk. The routine returns TRUE if
999
 * successful.
1000
 */
1001
int
1002
refclock_ioctl(
1003
  int fd,     /* file descriptor */
1004
  u_int lflags    /* line discipline flags */
1005
  )
1006
0
{
1007
  /*
1008
   * simply return TRUE if no UNIX line discipline is supported
1009
   */
1010
0
  DPRINTF(1, ("refclock_ioctl: fd %d flags 0x%x\n", fd, lflags));
1011
1012
0
  return TRUE;
1013
0
}
1014
#endif /* !defined(SYS_VXWORKS) && !defined(SYS_WINNT) */
1015
1016
1017
/*
1018
 * refclock_control - set and/or return clock values
1019
 *
1020
 * This routine is used mainly for debugging. It returns designated
1021
 * values from the interface structure that can be displayed using
1022
 * ntpdc and the clockstat command. It can also be used to initialize
1023
 * configuration variables, such as fudgetimes, fudgevalues, reference
1024
 * ID and stratum.
1025
 */
1026
void
1027
refclock_control(
1028
  sockaddr_u *srcadr,
1029
  const struct refclockstat *in,
1030
  struct refclockstat *out
1031
  )
1032
0
{
1033
0
  struct peer *peer;
1034
0
  struct refclockproc *pp;
1035
0
  u_char clktype;
1036
0
  int unit;
1037
1038
  /*
1039
   * Check for valid address and running peer
1040
   */
1041
0
  if (!ISREFCLOCKADR(srcadr))
1042
0
    return;
1043
1044
0
  clktype = (u_char)REFCLOCKTYPE(srcadr);
1045
0
  unit = REFCLOCKUNIT(srcadr);
1046
1047
0
  peer = findexistingpeer(srcadr, NULL, NULL, -1, 0, NULL);
1048
1049
0
  if (NULL == peer)
1050
0
    return;
1051
1052
0
  INSIST(peer->procptr != NULL);
1053
0
  pp = peer->procptr;
1054
1055
  /*
1056
   * Initialize requested data
1057
   */
1058
0
  if (in != NULL) {
1059
0
    if (in->haveflags & CLK_HAVETIME1)
1060
0
      pp->fudgetime1 = in->fudgetime1;
1061
0
    if (in->haveflags & CLK_HAVETIME2)
1062
0
      pp->fudgetime2 = in->fudgetime2;
1063
0
    if (in->haveflags & CLK_HAVEVAL1)
1064
0
      peer->stratum = pp->stratum = (u_char)in->fudgeval1;
1065
0
    if (in->haveflags & CLK_HAVEVAL2)
1066
0
      peer->refid = pp->refid = in->fudgeval2;
1067
0
    if (in->haveflags & CLK_HAVEFLAG1) {
1068
0
      pp->sloppyclockflag &= ~CLK_FLAG1;
1069
0
      pp->sloppyclockflag |= in->flags & CLK_FLAG1;
1070
0
    }
1071
0
    if (in->haveflags & CLK_HAVEFLAG2) {
1072
0
      pp->sloppyclockflag &= ~CLK_FLAG2;
1073
0
      pp->sloppyclockflag |= in->flags & CLK_FLAG2;
1074
0
    }
1075
0
    if (in->haveflags & CLK_HAVEFLAG3) {
1076
0
      pp->sloppyclockflag &= ~CLK_FLAG3;
1077
0
      pp->sloppyclockflag |= in->flags & CLK_FLAG3;
1078
0
    }
1079
0
    if (in->haveflags & CLK_HAVEFLAG4) {
1080
0
      pp->sloppyclockflag &= ~CLK_FLAG4;
1081
0
      pp->sloppyclockflag |= in->flags & CLK_FLAG4;
1082
0
    }
1083
0
  }
1084
1085
  /*
1086
   * Readback requested data
1087
   */
1088
0
  if (out != NULL) {
1089
0
    out->fudgeval1 = pp->stratum;
1090
0
    out->fudgeval2 = pp->refid;
1091
0
    out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
1092
0
    out->fudgetime1 = pp->fudgetime1;
1093
0
    if (0.0 != out->fudgetime1)
1094
0
      out->haveflags |= CLK_HAVETIME1;
1095
0
    out->fudgetime2 = pp->fudgetime2;
1096
0
    if (0.0 != out->fudgetime2)
1097
0
      out->haveflags |= CLK_HAVETIME2;
1098
0
    out->flags = (u_char) pp->sloppyclockflag;
1099
0
    if (CLK_FLAG1 & out->flags)
1100
0
      out->haveflags |= CLK_HAVEFLAG1;
1101
0
    if (CLK_FLAG2 & out->flags)
1102
0
      out->haveflags |= CLK_HAVEFLAG2;
1103
0
    if (CLK_FLAG3 & out->flags)
1104
0
      out->haveflags |= CLK_HAVEFLAG3;
1105
0
    if (CLK_FLAG4 & out->flags)
1106
0
      out->haveflags |= CLK_HAVEFLAG4;
1107
1108
0
    out->timereset = current_time - pp->timestarted;
1109
0
    out->polls = pp->polls;
1110
0
    out->noresponse = pp->noreply;
1111
0
    out->badformat = pp->badformat;
1112
0
    out->baddata = pp->baddata;
1113
1114
0
    out->lastevent = pp->lastevent;
1115
0
    out->currentstatus = pp->currentstatus;
1116
0
    out->type = pp->type;
1117
0
    out->clockdesc = pp->clockdesc;
1118
0
    out->lencode = (u_short)pp->lencode;
1119
0
    out->p_lastcode = pp->a_lastcode;
1120
0
  }
1121
1122
  /*
1123
   * Give the stuff to the clock
1124
   */
1125
0
  if (refclock_conf[clktype]->clock_control != noentry)
1126
0
    (refclock_conf[clktype]->clock_control)(unit, in, out, peer);
1127
0
}
1128
1129
1130
/*
1131
 * refclock_buginfo - return debugging info
1132
 *
1133
 * This routine is used mainly for debugging. It returns designated
1134
 * values from the interface structure that can be displayed using
1135
 * ntpdc and the clkbug command.
1136
 */
1137
void
1138
refclock_buginfo(
1139
  sockaddr_u *srcadr, /* clock address */
1140
  struct refclockbug *bug /* output structure */
1141
  )
1142
0
{
1143
0
  struct peer *peer;
1144
0
  struct refclockproc *pp;
1145
0
  int clktype;
1146
0
  int unit;
1147
0
  unsigned u;
1148
1149
  /*
1150
   * Check for valid address and peer structure
1151
   */
1152
0
  if (!ISREFCLOCKADR(srcadr))
1153
0
    return;
1154
1155
0
  clktype = (u_char) REFCLOCKTYPE(srcadr);
1156
0
  unit = REFCLOCKUNIT(srcadr);
1157
1158
0
  peer = findexistingpeer(srcadr, NULL, NULL, -1, 0, NULL);
1159
1160
0
  if (NULL == peer || NULL == peer->procptr)
1161
0
    return;
1162
1163
0
  pp = peer->procptr;
1164
1165
  /*
1166
   * Copy structure values
1167
   */
1168
0
  bug->nvalues = 8;
1169
0
  bug->svalues = 0x0000003f;
1170
0
  bug->values[0] = pp->year;
1171
0
  bug->values[1] = pp->day;
1172
0
  bug->values[2] = pp->hour;
1173
0
  bug->values[3] = pp->minute;
1174
0
  bug->values[4] = pp->second;
1175
0
  bug->values[5] = pp->nsec;
1176
0
  bug->values[6] = pp->yearstart;
1177
0
  bug->values[7] = pp->coderecv;
1178
0
  bug->stimes = 0xfffffffc;
1179
0
  bug->times[0] = pp->lastref;
1180
0
  bug->times[1] = pp->lastrec;
1181
0
  for (u = 2; u < bug->ntimes; u++)
1182
0
    DTOLFP(pp->filter[u - 2], &bug->times[u]);
1183
1184
  /*
1185
   * Give the stuff to the clock
1186
   */
1187
0
  if (refclock_conf[clktype]->clock_buginfo != noentry)
1188
0
    (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
1189
0
}
1190
1191
1192
#ifdef HAVE_PPSAPI
1193
/*
1194
 * refclock_ppsapi - initialize/update ppsapi
1195
 *
1196
 * This routine is called after the fudge command to open the PPSAPI
1197
 * interface for later parameter setting after the fudge command.
1198
 */
1199
int
1200
refclock_ppsapi(
1201
  int fddev,      /* fd device */
1202
  struct refclock_atom *ap  /* atom structure pointer */
1203
  )
1204
{
1205
  if (ap->handle == 0) {
1206
    if (time_pps_create(fddev, &ap->handle) < 0) {
1207
      msyslog(LOG_ERR,
1208
          "refclock_ppsapi: time_pps_create: %m");
1209
      return (0);
1210
    }
1211
    ZERO(ap->ts); /* [Bug 2689] defined INIT state */
1212
  }
1213
  return (1);
1214
}
1215
1216
1217
/*
1218
 * refclock_params - set ppsapi parameters
1219
 *
1220
 * This routine is called to set the PPSAPI parameters after the fudge
1221
 * command.
1222
 */
1223
int
1224
refclock_params(
1225
  int mode,     /* mode bits */
1226
  struct refclock_atom *ap  /* atom structure pointer */
1227
  )
1228
{
1229
  ZERO(ap->pps_params);
1230
  ap->pps_params.api_version = PPS_API_VERS_1;
1231
1232
  /*
1233
   * Solaris serial ports provide PPS pulse capture only on the
1234
   * assert edge. FreeBSD serial ports provide capture on the
1235
   * clear edge, while FreeBSD parallel ports provide capture
1236
   * on the assert edge. Your mileage may vary.
1237
   */
1238
  if (mode & CLK_FLAG2)
1239
    ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTURECLEAR;
1240
  else
1241
    ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTUREASSERT;
1242
  if (time_pps_setparams(ap->handle, &ap->pps_params) < 0) {
1243
    msyslog(LOG_ERR,
1244
        "refclock_params: time_pps_setparams: %m");
1245
    return (0);
1246
  }
1247
1248
  /*
1249
   * If flag3 is lit, select the kernel PPS if we can.
1250
   *
1251
   * Note: EOPNOTSUPP is the only 'legal' error code we deal with;
1252
   * it is part of the 'if we can' strategy.  Any other error
1253
   * indicates something more sinister and makes this function fail.
1254
   */
1255
  if (mode & CLK_FLAG3) {
1256
    if (time_pps_kcbind(ap->handle, PPS_KC_HARDPPS,
1257
        ap->pps_params.mode & ~PPS_TSFMT_TSPEC,
1258
        PPS_TSFMT_TSPEC) < 0)
1259
    {
1260
      if (errno != EOPNOTSUPP) { 
1261
        msyslog(LOG_ERR,
1262
          "refclock_params: time_pps_kcbind: %m");
1263
        return (0);
1264
      }
1265
    } else {
1266
      hardpps_enable = 1;
1267
    }
1268
  }
1269
  return (1);
1270
}
1271
1272
1273
/*
1274
 * refclock_pps - called once per second
1275
 *
1276
 * This routine is called once per second. It snatches the PPS
1277
 * timestamp from the kernel and saves the sign-extended fraction in
1278
 * a circular buffer for processing at the next poll event.
1279
 */
1280
int
1281
refclock_pps(
1282
  struct peer *peer,    /* peer structure pointer */
1283
  struct refclock_atom *ap, /* atom structure pointer */
1284
  int mode      /* mode bits */ 
1285
  )
1286
{
1287
  struct refclockproc *pp;
1288
  pps_info_t pps_info;
1289
  struct timespec timeout;
1290
  double  dtemp, dcorr, trash;
1291
1292
  /*
1293
   * We require the clock to be synchronized before setting the
1294
   * parameters. When the parameters have been set, fetch the
1295
   * most recent PPS timestamp.
1296
   */ 
1297
  pp = peer->procptr;
1298
  if (ap->handle == 0)
1299
    return (0);
1300
1301
  if (ap->pps_params.mode == 0 && sys_leap != LEAP_NOTINSYNC) {
1302
    if (refclock_params(pp->sloppyclockflag, ap) < 1)
1303
      return (0);
1304
  }
1305
  ZERO(timeout);
1306
  ZERO(pps_info);
1307
  if (time_pps_fetch(ap->handle, PPS_TSFMT_TSPEC, &pps_info,
1308
      &timeout) < 0) {
1309
    refclock_report(peer, CEVNT_FAULT);
1310
    return (0);
1311
  }
1312
  timeout = ap->ts; /* save old timestamp for check */
1313
  if (ap->pps_params.mode & PPS_CAPTUREASSERT)
1314
    ap->ts = pps_info.assert_timestamp;
1315
  else if (ap->pps_params.mode & PPS_CAPTURECLEAR)
1316
    ap->ts = pps_info.clear_timestamp;
1317
  else
1318
    return (0);
1319
1320
  /* [Bug 2689] Discard the first sample we read -- if the PPS
1321
   * source is currently down / disconnected, we have read a
1322
   * potentially *very* stale value here. So if our old TS value
1323
   * is all-zero, we consider this sample unrealiable and drop it.
1324
   *
1325
   * Note 1: a better check would compare the PPS time stamp to
1326
   * the current system time and drop it if it's more than say 3s
1327
   * away.
1328
   *
1329
   * Note 2: If we ever again get an all-zero PPS sample, the next
1330
   * one will be discarded. This can happen every 136yrs and is
1331
   * unlikely to be ever observed.
1332
   */
1333
  if (0 == (timeout.tv_sec | timeout.tv_nsec))
1334
    return (0);
1335
1336
  /* If the PPS source fails to deliver a new sample between
1337
   * polls, it regurgitates the last sample. We do not want to
1338
   * process the same sample multiple times.
1339
   */
1340
  if (0 == memcmp(&timeout, &ap->ts, sizeof(timeout)))
1341
    return (0);
1342
1343
  /*
1344
   * Convert to signed fraction offset, apply fudge and properly
1345
   * fold the correction into the [-0.5s,0.5s] range. Handle
1346
   * excessive fudge times, too.
1347
   */
1348
  dtemp = ap->ts.tv_nsec / 1e9;
1349
  dcorr = modf((pp->fudgetime1 - dtemp), &trash);
1350
  if (dcorr > 0.5)
1351
    dcorr -= 1.0;
1352
  else if (dcorr < -0.5)
1353
    dcorr += 1.0;
1354
1355
  /* phase gate check: avoid wobbling by +/-1s when too close to
1356
   * the switch-over point. We allow +/-400ms max phase deviation.
1357
   * The trade-off is clear: The smaller the limit, the less
1358
   * sensitive to sampling noise the clock becomes. OTOH the
1359
   * system must get into phase gate range by other means for the
1360
   * PPS clock to lock in.
1361
   */
1362
  if (fabs(dcorr) > 0.4)
1363
    return (0);
1364
1365
  /*
1366
   * record this time stamp and stuff in median filter
1367
   */
1368
  pp->lastrec.l_ui = (u_int32)ap->ts.tv_sec + JAN_1970;
1369
  pp->lastrec.l_uf = (u_int32)(dtemp * FRAC);
1370
  SAMPLE(dcorr);
1371
  
1372
#ifdef DEBUG
1373
  if (debug > 1)
1374
    printf("refclock_pps: %lu %f %f\n", current_time,
1375
        dcorr, pp->fudgetime1);
1376
#endif
1377
  return (1);
1378
}
1379
#endif /* HAVE_PPSAPI */
1380
#endif /* REFCLOCK */