/contrib/ntp/parseutil/dcfd.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1903 lines · 1176 code · 224 blank · 503 comment · 185 complexity · 631e9c94a64b729f6a16ed49a8362491 MD5 · raw file

  1. /*
  2. * /src/NTP/REPOSITORY/ntp4-dev/parseutil/dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
  3. *
  4. * dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
  5. *
  6. * DCF77 100/200ms pulse synchronisation daemon program (via 50Baud serial line)
  7. *
  8. * Features:
  9. * DCF77 decoding
  10. * simple NTP loopfilter logic for local clock
  11. * interactive display for debugging
  12. *
  13. * Lacks:
  14. * Leap second handling (at that level you should switch to NTP Version 4 - really!)
  15. *
  16. * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
  17. * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
  18. *
  19. * Redistribution and use in source and binary forms, with or without
  20. * modification, are permitted provided that the following conditions
  21. * are met:
  22. * 1. Redistributions of source code must retain the above copyright
  23. * notice, this list of conditions and the following disclaimer.
  24. * 2. Redistributions in binary form must reproduce the above copyright
  25. * notice, this list of conditions and the following disclaimer in the
  26. * documentation and/or other materials provided with the distribution.
  27. * 3. Neither the name of the author nor the names of its contributors
  28. * may be used to endorse or promote products derived from this software
  29. * without specific prior written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  32. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  35. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41. * SUCH DAMAGE.
  42. *
  43. */
  44. #ifdef HAVE_CONFIG_H
  45. # include <config.h>
  46. #endif
  47. #include <sys/ioctl.h>
  48. #include <unistd.h>
  49. #include <stdio.h>
  50. #include <fcntl.h>
  51. #include <sys/types.h>
  52. #include <sys/time.h>
  53. #include <signal.h>
  54. #include <syslog.h>
  55. #include <time.h>
  56. /*
  57. * NTP compilation environment
  58. */
  59. #include "ntp_stdlib.h"
  60. #include "ntpd.h" /* indirectly include ntp.h to get YEAR_PIVOT Y2KFixes */
  61. /*
  62. * select which terminal handling to use (currently only SysV variants)
  63. */
  64. #if defined(HAVE_TERMIOS_H) || defined(STREAM)
  65. #include <termios.h>
  66. #define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
  67. #define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
  68. #else /* not HAVE_TERMIOS_H || STREAM */
  69. # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
  70. # include <termio.h>
  71. # define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
  72. # define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
  73. # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
  74. #endif /* not HAVE_TERMIOS_H || STREAM */
  75. #ifndef TTY_GETATTR
  76. #include "Bletch: MUST DEFINE ONE OF 'HAVE_TERMIOS_H' or 'HAVE_TERMIO_H'"
  77. #endif
  78. #ifndef days_per_year
  79. #define days_per_year(_x_) (((_x_) % 4) ? 365 : (((_x_) % 400) ? 365 : 366))
  80. #endif
  81. #define timernormalize(_a_) \
  82. if ((_a_)->tv_usec >= 1000000) \
  83. { \
  84. (_a_)->tv_sec += (_a_)->tv_usec / 1000000; \
  85. (_a_)->tv_usec = (_a_)->tv_usec % 1000000; \
  86. } \
  87. if ((_a_)->tv_usec < 0) \
  88. { \
  89. (_a_)->tv_sec -= 1 + (-(_a_)->tv_usec / 1000000); \
  90. (_a_)->tv_usec = 999999 - (-(_a_)->tv_usec - 1); \
  91. }
  92. #ifdef timeradd
  93. #undef timeradd
  94. #endif
  95. #define timeradd(_a_, _b_) \
  96. (_a_)->tv_sec += (_b_)->tv_sec; \
  97. (_a_)->tv_usec += (_b_)->tv_usec; \
  98. timernormalize((_a_))
  99. #ifdef timersub
  100. #undef timersub
  101. #endif
  102. #define timersub(_a_, _b_) \
  103. (_a_)->tv_sec -= (_b_)->tv_sec; \
  104. (_a_)->tv_usec -= (_b_)->tv_usec; \
  105. timernormalize((_a_))
  106. /*
  107. * debug macros
  108. */
  109. #define PRINTF if (interactive) printf
  110. #define LPRINTF if (interactive && loop_filter_debug) printf
  111. #ifdef DEBUG
  112. #define dprintf(_x_) LPRINTF _x_
  113. #else
  114. #define dprintf(_x_)
  115. #endif
  116. #ifdef DECL_ERRNO
  117. extern int errno;
  118. #endif
  119. static char *revision = "4.18";
  120. /*
  121. * display received data (avoids also detaching from tty)
  122. */
  123. static int interactive = 0;
  124. /*
  125. * display loopfilter (clock control) variables
  126. */
  127. static int loop_filter_debug = 0;
  128. /*
  129. * do not set/adjust system time
  130. */
  131. static int no_set = 0;
  132. /*
  133. * time that passes between start of DCF impulse and time stamping (fine
  134. * adjustment) in microseconds (receiver/OS dependent)
  135. */
  136. #define DEFAULT_DELAY 230000 /* rough estimate */
  137. /*
  138. * The two states we can be in - eithe we receive nothing
  139. * usable or we have the correct time
  140. */
  141. #define NO_SYNC 0x01
  142. #define SYNC 0x02
  143. static int sync_state = NO_SYNC;
  144. static time_t last_sync;
  145. static unsigned long ticks = 0;
  146. static char pat[] = "-\\|/";
  147. #define LINES (24-2) /* error lines after which the two headlines are repeated */
  148. #define MAX_UNSYNC (10*60) /* allow synchronisation loss for 10 minutes */
  149. #define NOTICE_INTERVAL (20*60) /* mention missing synchronisation every 20 minutes */
  150. /*
  151. * clock adjustment PLL - see NTP protocol spec (RFC1305) for details
  152. */
  153. #define USECSCALE 10
  154. #define TIMECONSTANT 2
  155. #define ADJINTERVAL 0
  156. #define FREQ_WEIGHT 18
  157. #define PHASE_WEIGHT 7
  158. #define MAX_DRIFT 0x3FFFFFFF
  159. #define R_SHIFT(_X_, _Y_) (((_X_) < 0) ? -(-(_X_) >> (_Y_)) : ((_X_) >> (_Y_)))
  160. static struct timeval max_adj_offset = { 0, 128000 };
  161. static long clock_adjust = 0; /* current adjustment value (usec * 2^USECSCALE) */
  162. static long accum_drift = 0; /* accumulated drift value (usec / ADJINTERVAL) */
  163. static long adjustments = 0;
  164. static char skip_adjust = 1; /* discard first adjustment (bad samples) */
  165. /*
  166. * DCF77 state flags
  167. */
  168. #define DCFB_ANNOUNCE 0x0001 /* switch time zone warning (DST switch) */
  169. #define DCFB_DST 0x0002 /* DST in effect */
  170. #define DCFB_LEAP 0x0004 /* LEAP warning (1 hour prior to occurrence) */
  171. #define DCFB_ALTERNATE 0x0008 /* alternate antenna used */
  172. struct clocktime /* clock time broken up from time code */
  173. {
  174. long wday; /* Day of week: 1: Monday - 7: Sunday */
  175. long day;
  176. long month;
  177. long year;
  178. long hour;
  179. long minute;
  180. long second;
  181. long usecond;
  182. long utcoffset; /* in minutes */
  183. long flags; /* current clock status (DCF77 state flags) */
  184. };
  185. typedef struct clocktime clocktime_t;
  186. /*
  187. * (usually) quick constant multiplications
  188. */
  189. #define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1)) /* *8 + *2 */
  190. #define TIMES24(_X_) (((_X_) << 4) + ((_X_) << 3)) /* *16 + *8 */
  191. #define TIMES60(_X_) ((((_X_) << 4) - (_X_)) << 2) /* *(16 - 1) *4 */
  192. /*
  193. * generic l_abs() function
  194. */
  195. #define l_abs(_x_) (((_x_) < 0) ? -(_x_) : (_x_))
  196. /*
  197. * conversion related return/error codes
  198. */
  199. #define CVT_MASK 0x0000000F /* conversion exit code */
  200. #define CVT_NONE 0x00000001 /* format not applicable */
  201. #define CVT_FAIL 0x00000002 /* conversion failed - error code returned */
  202. #define CVT_OK 0x00000004 /* conversion succeeded */
  203. #define CVT_BADFMT 0x00000010 /* general format error - (unparsable) */
  204. #define CVT_BADDATE 0x00000020 /* invalid date */
  205. #define CVT_BADTIME 0x00000040 /* invalid time */
  206. /*
  207. * DCF77 raw time code
  208. *
  209. * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig
  210. * und Berlin, Maerz 1989
  211. *
  212. * Timecode transmission:
  213. * AM:
  214. * time marks are send every second except for the second before the
  215. * next minute mark
  216. * time marks consist of a reduction of transmitter power to 25%
  217. * of the nominal level
  218. * the falling edge is the time indication (on time)
  219. * time marks of a 100ms duration constitute a logical 0
  220. * time marks of a 200ms duration constitute a logical 1
  221. * FM:
  222. * see the spec. (basically a (non-)inverted psuedo random phase shift)
  223. *
  224. * Encoding:
  225. * Second Contents
  226. * 0 - 10 AM: free, FM: 0
  227. * 11 - 14 free
  228. * 15 R - alternate antenna
  229. * 16 A1 - expect zone change (1 hour before)
  230. * 17 - 18 Z1,Z2 - time zone
  231. * 0 0 illegal
  232. * 0 1 MEZ (MET)
  233. * 1 0 MESZ (MED, MET DST)
  234. * 1 1 illegal
  235. * 19 A2 - expect leap insertion/deletion (1 hour before)
  236. * 20 S - start of time code (1)
  237. * 21 - 24 M1 - BCD (lsb first) Minutes
  238. * 25 - 27 M10 - BCD (lsb first) 10 Minutes
  239. * 28 P1 - Minute Parity (even)
  240. * 29 - 32 H1 - BCD (lsb first) Hours
  241. * 33 - 34 H10 - BCD (lsb first) 10 Hours
  242. * 35 P2 - Hour Parity (even)
  243. * 36 - 39 D1 - BCD (lsb first) Days
  244. * 40 - 41 D10 - BCD (lsb first) 10 Days
  245. * 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday)
  246. * 45 - 49 MO - BCD (lsb first) Month
  247. * 50 MO0 - 10 Months
  248. * 51 - 53 Y1 - BCD (lsb first) Years
  249. * 54 - 57 Y10 - BCD (lsb first) 10 Years
  250. * 58 P3 - Date Parity (even)
  251. * 59 - usually missing (minute indication), except for leap insertion
  252. */
  253. /*-----------------------------------------------------------------------
  254. * conversion table to map DCF77 bit stream into data fields.
  255. * Encoding:
  256. * Each field of the DCF77 code is described with two adjacent entries in
  257. * this table. The first entry specifies the offset into the DCF77 data stream
  258. * while the length is given as the difference between the start index and
  259. * the start index of the following field.
  260. */
  261. static struct rawdcfcode
  262. {
  263. char offset; /* start bit */
  264. } rawdcfcode[] =
  265. {
  266. { 0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 },
  267. { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 }
  268. };
  269. /*-----------------------------------------------------------------------
  270. * symbolic names for the fields of DCF77 describes in "rawdcfcode".
  271. * see comment above for the structure of the DCF77 data
  272. */
  273. #define DCF_M 0
  274. #define DCF_R 1
  275. #define DCF_A1 2
  276. #define DCF_Z 3
  277. #define DCF_A2 4
  278. #define DCF_S 5
  279. #define DCF_M1 6
  280. #define DCF_M10 7
  281. #define DCF_P1 8
  282. #define DCF_H1 9
  283. #define DCF_H10 10
  284. #define DCF_P2 11
  285. #define DCF_D1 12
  286. #define DCF_D10 13
  287. #define DCF_DW 14
  288. #define DCF_MO 15
  289. #define DCF_MO0 16
  290. #define DCF_Y1 17
  291. #define DCF_Y10 18
  292. #define DCF_P3 19
  293. /*-----------------------------------------------------------------------
  294. * parity field table (same encoding as rawdcfcode)
  295. * This table describes the sections of the DCF77 code that are
  296. * parity protected
  297. */
  298. static struct partab
  299. {
  300. char offset; /* start bit of parity field */
  301. } partab[] =
  302. {
  303. { 21 }, { 29 }, { 36 }, { 59 }
  304. };
  305. /*-----------------------------------------------------------------------
  306. * offsets for parity field descriptions
  307. */
  308. #define DCF_P_P1 0
  309. #define DCF_P_P2 1
  310. #define DCF_P_P3 2
  311. /*-----------------------------------------------------------------------
  312. * legal values for time zone information
  313. */
  314. #define DCF_Z_MET 0x2
  315. #define DCF_Z_MED 0x1
  316. /*-----------------------------------------------------------------------
  317. * symbolic representation if the DCF77 data stream
  318. */
  319. static struct dcfparam
  320. {
  321. unsigned char onebits[60];
  322. unsigned char zerobits[60];
  323. } dcfparam =
  324. {
  325. "###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */
  326. "--------------------s-------p------p----------------------p" /* 'ZERO' representation */
  327. };
  328. /*-----------------------------------------------------------------------
  329. * extract a bitfield from DCF77 datastream
  330. * All numeric fields are LSB first.
  331. * buf holds a pointer to a DCF77 data buffer in symbolic
  332. * representation
  333. * idx holds the index to the field description in rawdcfcode
  334. */
  335. static unsigned long
  336. ext_bf(
  337. register unsigned char *buf,
  338. register int idx
  339. )
  340. {
  341. register unsigned long sum = 0;
  342. register int i, first;
  343. first = rawdcfcode[idx].offset;
  344. for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--)
  345. {
  346. sum <<= 1;
  347. sum |= (buf[i] != dcfparam.zerobits[i]);
  348. }
  349. return sum;
  350. }
  351. /*-----------------------------------------------------------------------
  352. * check even parity integrity for a bitfield
  353. *
  354. * buf holds a pointer to a DCF77 data buffer in symbolic
  355. * representation
  356. * idx holds the index to the field description in partab
  357. */
  358. static unsigned
  359. pcheck(
  360. register unsigned char *buf,
  361. register int idx
  362. )
  363. {
  364. register int i,last;
  365. register unsigned psum = 1;
  366. last = partab[idx+1].offset;
  367. for (i = partab[idx].offset; i < last; i++)
  368. psum ^= (buf[i] != dcfparam.zerobits[i]);
  369. return psum;
  370. }
  371. /*-----------------------------------------------------------------------
  372. * convert a DCF77 data buffer into wall clock time + flags
  373. *
  374. * buffer holds a pointer to a DCF77 data buffer in symbolic
  375. * representation
  376. * size describes the length of DCF77 information in bits (represented
  377. * as chars in symbolic notation
  378. * clock points to a wall clock time description of the DCF77 data (result)
  379. */
  380. static unsigned long
  381. convert_rawdcf(
  382. unsigned char *buffer,
  383. int size,
  384. clocktime_t *clock_time
  385. )
  386. {
  387. if (size < 57)
  388. {
  389. PRINTF("%-30s", "*** INCOMPLETE");
  390. return CVT_NONE;
  391. }
  392. /*
  393. * check Start and Parity bits
  394. */
  395. if ((ext_bf(buffer, DCF_S) == 1) &&
  396. pcheck(buffer, DCF_P_P1) &&
  397. pcheck(buffer, DCF_P_P2) &&
  398. pcheck(buffer, DCF_P_P3))
  399. {
  400. /*
  401. * buffer OK - extract all fields and build wall clock time from them
  402. */
  403. clock_time->flags = 0;
  404. clock_time->usecond= 0;
  405. clock_time->second = 0;
  406. clock_time->minute = ext_bf(buffer, DCF_M10);
  407. clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1);
  408. clock_time->hour = ext_bf(buffer, DCF_H10);
  409. clock_time->hour = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1);
  410. clock_time->day = ext_bf(buffer, DCF_D10);
  411. clock_time->day = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1);
  412. clock_time->month = ext_bf(buffer, DCF_MO0);
  413. clock_time->month = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO);
  414. clock_time->year = ext_bf(buffer, DCF_Y10);
  415. clock_time->year = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1);
  416. clock_time->wday = ext_bf(buffer, DCF_DW);
  417. /*
  418. * determine offset to UTC by examining the time zone
  419. */
  420. switch (ext_bf(buffer, DCF_Z))
  421. {
  422. case DCF_Z_MET:
  423. clock_time->utcoffset = -60;
  424. break;
  425. case DCF_Z_MED:
  426. clock_time->flags |= DCFB_DST;
  427. clock_time->utcoffset = -120;
  428. break;
  429. default:
  430. PRINTF("%-30s", "*** BAD TIME ZONE");
  431. return CVT_FAIL|CVT_BADFMT;
  432. }
  433. /*
  434. * extract various warnings from DCF77
  435. */
  436. if (ext_bf(buffer, DCF_A1))
  437. clock_time->flags |= DCFB_ANNOUNCE;
  438. if (ext_bf(buffer, DCF_A2))
  439. clock_time->flags |= DCFB_LEAP;
  440. if (ext_bf(buffer, DCF_R))
  441. clock_time->flags |= DCFB_ALTERNATE;
  442. return CVT_OK;
  443. }
  444. else
  445. {
  446. /*
  447. * bad format - not for us
  448. */
  449. PRINTF("%-30s", "*** BAD FORMAT (invalid/parity)");
  450. return CVT_FAIL|CVT_BADFMT;
  451. }
  452. }
  453. /*-----------------------------------------------------------------------
  454. * raw dcf input routine - fix up 50 baud
  455. * characters for 1/0 decision
  456. */
  457. static unsigned long
  458. cvt_rawdcf(
  459. unsigned char *buffer,
  460. int size,
  461. clocktime_t *clock_time
  462. )
  463. {
  464. register unsigned char *s = buffer;
  465. register unsigned char *e = buffer + size;
  466. register unsigned char *b = dcfparam.onebits;
  467. register unsigned char *c = dcfparam.zerobits;
  468. register unsigned rtc = CVT_NONE;
  469. register unsigned int i, lowmax, highmax, cutoff, span;
  470. #define BITS 9
  471. unsigned char histbuf[BITS];
  472. /*
  473. * the input buffer contains characters with runs of consecutive
  474. * bits set. These set bits are an indication of the DCF77 pulse
  475. * length. We assume that we receive the pulse at 50 Baud. Thus
  476. * a 100ms pulse would generate a 4 bit train (20ms per bit and
  477. * start bit)
  478. * a 200ms pulse would create all zeroes (and probably a frame error)
  479. *
  480. * The basic idea is that on corret reception we must have two
  481. * maxima in the pulse length distribution histogram. (one for
  482. * the zero representing pulses and one for the one representing
  483. * pulses)
  484. * There will always be ones in the datastream, thus we have to see
  485. * two maxima.
  486. * The best point to cut for a 1/0 decision is the minimum between those
  487. * between the maxima. The following code tries to find this cutoff point.
  488. */
  489. /*
  490. * clear histogram buffer
  491. */
  492. for (i = 0; i < BITS; i++)
  493. {
  494. histbuf[i] = 0;
  495. }
  496. cutoff = 0;
  497. lowmax = 0;
  498. /*
  499. * convert sequences of set bits into bits counts updating
  500. * the histogram alongway
  501. */
  502. while (s < e)
  503. {
  504. register unsigned int ch = *s ^ 0xFF;
  505. /*
  506. * check integrity and update histogramm
  507. */
  508. if (!((ch+1) & ch) || !*s)
  509. {
  510. /*
  511. * character ok
  512. */
  513. for (i = 0; ch; i++)
  514. {
  515. ch >>= 1;
  516. }
  517. *s = i;
  518. histbuf[i]++;
  519. cutoff += i;
  520. lowmax++;
  521. }
  522. else
  523. {
  524. /*
  525. * invalid character (no consecutive bit sequence)
  526. */
  527. dprintf(("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, s - buffer));
  528. *s = (unsigned char)~0;
  529. rtc = CVT_FAIL|CVT_BADFMT;
  530. }
  531. s++;
  532. }
  533. /*
  534. * first cutoff estimate (average bit count - must be between both
  535. * maxima)
  536. */
  537. if (lowmax)
  538. {
  539. cutoff /= lowmax;
  540. }
  541. else
  542. {
  543. cutoff = 4; /* doesn't really matter - it'll fail anyway, but gives error output */
  544. }
  545. dprintf(("parse: cvt_rawdcf: average bit count: %d\n", cutoff));
  546. lowmax = 0; /* weighted sum */
  547. highmax = 0; /* bitcount */
  548. /*
  549. * collect weighted sum of lower bits (left of initial guess)
  550. */
  551. dprintf(("parse: cvt_rawdcf: histogram:"));
  552. for (i = 0; i <= cutoff; i++)
  553. {
  554. lowmax += histbuf[i] * i;
  555. highmax += histbuf[i];
  556. dprintf((" %d", histbuf[i]));
  557. }
  558. dprintf((" <M>"));
  559. /*
  560. * round up
  561. */
  562. lowmax += highmax / 2;
  563. /*
  564. * calculate lower bit maximum (weighted sum / bit count)
  565. *
  566. * avoid divide by zero
  567. */
  568. if (highmax)
  569. {
  570. lowmax /= highmax;
  571. }
  572. else
  573. {
  574. lowmax = 0;
  575. }
  576. highmax = 0; /* weighted sum of upper bits counts */
  577. cutoff = 0; /* bitcount */
  578. /*
  579. * collect weighted sum of lower bits (right of initial guess)
  580. */
  581. for (; i < BITS; i++)
  582. {
  583. highmax+=histbuf[i] * i;
  584. cutoff +=histbuf[i];
  585. dprintf((" %d", histbuf[i]));
  586. }
  587. dprintf(("\n"));
  588. /*
  589. * determine upper maximum (weighted sum / bit count)
  590. */
  591. if (cutoff)
  592. {
  593. highmax /= cutoff;
  594. }
  595. else
  596. {
  597. highmax = BITS-1;
  598. }
  599. /*
  600. * following now holds:
  601. * lowmax <= cutoff(initial guess) <= highmax
  602. * best cutoff is the minimum nearest to higher bits
  603. */
  604. /*
  605. * find the minimum between lowmax and highmax (detecting
  606. * possibly a minimum span)
  607. */
  608. span = cutoff = lowmax;
  609. for (i = lowmax; i <= highmax; i++)
  610. {
  611. if (histbuf[cutoff] > histbuf[i])
  612. {
  613. /*
  614. * got a new minimum move beginning of minimum (cutoff) and
  615. * end of minimum (span) there
  616. */
  617. cutoff = span = i;
  618. }
  619. else
  620. if (histbuf[cutoff] == histbuf[i])
  621. {
  622. /*
  623. * minimum not better yet - but it spans more than
  624. * one bit value - follow it
  625. */
  626. span = i;
  627. }
  628. }
  629. /*
  630. * cutoff point for 1/0 decision is the middle of the minimum section
  631. * in the histogram
  632. */
  633. cutoff = (cutoff + span) / 2;
  634. dprintf(("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff));
  635. /*
  636. * convert the bit counts to symbolic 1/0 information for data conversion
  637. */
  638. s = buffer;
  639. while ((s < e) && *c && *b)
  640. {
  641. if (*s == (unsigned char)~0)
  642. {
  643. /*
  644. * invalid character
  645. */
  646. *s = '?';
  647. }
  648. else
  649. {
  650. /*
  651. * symbolic 1/0 representation
  652. */
  653. *s = (*s >= cutoff) ? *b : *c;
  654. }
  655. s++;
  656. b++;
  657. c++;
  658. }
  659. /*
  660. * if everything went well so far return the result of the symbolic
  661. * conversion routine else just the accumulated errors
  662. */
  663. if (rtc != CVT_NONE)
  664. {
  665. PRINTF("%-30s", "*** BAD DATA");
  666. }
  667. return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, clock_time) : rtc;
  668. }
  669. /*-----------------------------------------------------------------------
  670. * convert a wall clock time description of DCF77 to a Unix time (seconds
  671. * since 1.1. 1970 UTC)
  672. */
  673. static time_t
  674. dcf_to_unixtime(
  675. clocktime_t *clock_time,
  676. unsigned *cvtrtc
  677. )
  678. {
  679. #define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
  680. static int days_of_month[] =
  681. {
  682. 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  683. };
  684. register int i;
  685. time_t t;
  686. /*
  687. * map 2 digit years to 19xx (DCF77 is a 20th century item)
  688. */
  689. if ( clock_time->year < YEAR_PIVOT ) /* in case of Y2KFixes [ */
  690. clock_time->year += 100; /* *year%100, make tm_year */
  691. /* *(do we need this?) */
  692. if ( clock_time->year < YEAR_BREAK ) /* (failsafe if) */
  693. clock_time->year += 1900; /* Y2KFixes ] */
  694. /*
  695. * must have been a really bad year code - drop it
  696. */
  697. if (clock_time->year < (YEAR_PIVOT + 1900) ) /* Y2KFixes */
  698. {
  699. SETRTC(CVT_FAIL|CVT_BADDATE);
  700. return -1;
  701. }
  702. /*
  703. * sorry, slow section here - but it's not time critical anyway
  704. */
  705. /*
  706. * calculate days since 1970 (watching leap years)
  707. */
  708. t = julian0( clock_time->year ) - julian0( 1970 );
  709. /* month */
  710. if (clock_time->month <= 0 || clock_time->month > 12)
  711. {
  712. SETRTC(CVT_FAIL|CVT_BADDATE);
  713. return -1; /* bad month */
  714. }
  715. /* adjust current leap year */
  716. #if 0
  717. if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
  718. t--;
  719. #endif
  720. /*
  721. * collect days from months excluding the current one
  722. */
  723. for (i = 1; i < clock_time->month; i++)
  724. {
  725. t += days_of_month[i];
  726. }
  727. /* day */
  728. if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
  729. clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
  730. {
  731. SETRTC(CVT_FAIL|CVT_BADDATE);
  732. return -1; /* bad day */
  733. }
  734. /*
  735. * collect days from date excluding the current one
  736. */
  737. t += clock_time->day - 1;
  738. /* hour */
  739. if (clock_time->hour < 0 || clock_time->hour >= 24)
  740. {
  741. SETRTC(CVT_FAIL|CVT_BADTIME);
  742. return -1; /* bad hour */
  743. }
  744. /*
  745. * calculate hours from 1. 1. 1970
  746. */
  747. t = TIMES24(t) + clock_time->hour;
  748. /* min */
  749. if (clock_time->minute < 0 || clock_time->minute > 59)
  750. {
  751. SETRTC(CVT_FAIL|CVT_BADTIME);
  752. return -1; /* bad min */
  753. }
  754. /*
  755. * calculate minutes from 1. 1. 1970
  756. */
  757. t = TIMES60(t) + clock_time->minute;
  758. /* sec */
  759. /*
  760. * calculate UTC in minutes
  761. */
  762. t += clock_time->utcoffset;
  763. if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */
  764. {
  765. SETRTC(CVT_FAIL|CVT_BADTIME);
  766. return -1; /* bad sec */
  767. }
  768. /*
  769. * calculate UTC in seconds - phew !
  770. */
  771. t = TIMES60(t) + clock_time->second;
  772. /* done */
  773. return t;
  774. }
  775. /*-----------------------------------------------------------------------
  776. * cheap half baked 1/0 decision - for interactive operation only
  777. */
  778. static char
  779. type(
  780. unsigned int c
  781. )
  782. {
  783. c ^= 0xFF;
  784. return (c > 0xF);
  785. }
  786. /*-----------------------------------------------------------------------
  787. * week day representation
  788. */
  789. static const char *wday[8] =
  790. {
  791. "??",
  792. "Mo",
  793. "Tu",
  794. "We",
  795. "Th",
  796. "Fr",
  797. "Sa",
  798. "Su"
  799. };
  800. /*-----------------------------------------------------------------------
  801. * generate a string representation for a timeval
  802. */
  803. static char *
  804. pr_timeval(
  805. struct timeval *val
  806. )
  807. {
  808. static char buf[20];
  809. if (val->tv_sec == 0)
  810. sprintf(buf, "%c0.%06ld", (val->tv_usec < 0) ? '-' : '+', (long int)l_abs(val->tv_usec));
  811. else
  812. sprintf(buf, "%ld.%06ld", (long int)val->tv_sec, (long int)l_abs(val->tv_usec));
  813. return buf;
  814. }
  815. /*-----------------------------------------------------------------------
  816. * correct the current time by an offset by setting the time rigorously
  817. */
  818. static void
  819. set_time(
  820. struct timeval *offset
  821. )
  822. {
  823. struct timeval the_time;
  824. if (no_set)
  825. return;
  826. LPRINTF("set_time: %s ", pr_timeval(offset));
  827. syslog(LOG_NOTICE, "setting time (offset %s)", pr_timeval(offset));
  828. if (gettimeofday(&the_time, 0L) == -1)
  829. {
  830. perror("gettimeofday()");
  831. }
  832. else
  833. {
  834. timeradd(&the_time, offset);
  835. if (settimeofday(&the_time, 0L) == -1)
  836. {
  837. perror("settimeofday()");
  838. }
  839. }
  840. }
  841. /*-----------------------------------------------------------------------
  842. * slew the time by a given offset
  843. */
  844. static void
  845. adj_time(
  846. long offset
  847. )
  848. {
  849. struct timeval time_offset;
  850. if (no_set)
  851. return;
  852. time_offset.tv_sec = offset / 1000000;
  853. time_offset.tv_usec = offset % 1000000;
  854. LPRINTF("adj_time: %ld us ", (long int)offset);
  855. if (adjtime(&time_offset, 0L) == -1)
  856. perror("adjtime()");
  857. }
  858. /*-----------------------------------------------------------------------
  859. * read in a possibly previously written drift value
  860. */
  861. static void
  862. read_drift(
  863. const char *drift_file
  864. )
  865. {
  866. FILE *df;
  867. df = fopen(drift_file, "r");
  868. if (df != NULL)
  869. {
  870. int idrift = 0, fdrift = 0;
  871. fscanf(df, "%4d.%03d", &idrift, &fdrift);
  872. fclose(df);
  873. LPRINTF("read_drift: %d.%03d ppm ", idrift, fdrift);
  874. accum_drift = idrift << USECSCALE;
  875. fdrift = (fdrift << USECSCALE) / 1000;
  876. accum_drift += fdrift & (1<<USECSCALE);
  877. LPRINTF("read_drift: drift_comp %ld ", (long int)accum_drift);
  878. }
  879. }
  880. /*-----------------------------------------------------------------------
  881. * write out the current drift value
  882. */
  883. static void
  884. update_drift(
  885. const char *drift_file,
  886. long offset,
  887. time_t reftime
  888. )
  889. {
  890. FILE *df;
  891. df = fopen(drift_file, "w");
  892. if (df != NULL)
  893. {
  894. int idrift = R_SHIFT(accum_drift, USECSCALE);
  895. int fdrift = accum_drift & ((1<<USECSCALE)-1);
  896. LPRINTF("update_drift: drift_comp %ld ", (long int)accum_drift);
  897. fdrift = (fdrift * 1000) / (1<<USECSCALE);
  898. fprintf(df, "%4d.%03d %c%ld.%06ld %.24s\n", idrift, fdrift,
  899. (offset < 0) ? '-' : '+', (long int)(l_abs(offset) / 1000000),
  900. (long int)(l_abs(offset) % 1000000), asctime(localtime(&reftime)));
  901. fclose(df);
  902. LPRINTF("update_drift: %d.%03d ppm ", idrift, fdrift);
  903. }
  904. }
  905. /*-----------------------------------------------------------------------
  906. * process adjustments derived from the DCF77 observation
  907. * (controls clock PLL)
  908. */
  909. static void
  910. adjust_clock(
  911. struct timeval *offset,
  912. const char *drift_file,
  913. time_t reftime
  914. )
  915. {
  916. struct timeval toffset;
  917. register long usecoffset;
  918. int tmp;
  919. if (no_set)
  920. return;
  921. if (skip_adjust)
  922. {
  923. skip_adjust = 0;
  924. return;
  925. }
  926. toffset = *offset;
  927. toffset.tv_sec = l_abs(toffset.tv_sec);
  928. toffset.tv_usec = l_abs(toffset.tv_usec);
  929. if (timercmp(&toffset, &max_adj_offset, >))
  930. {
  931. /*
  932. * hopeless - set the clock - and clear the timing
  933. */
  934. set_time(offset);
  935. clock_adjust = 0;
  936. skip_adjust = 1;
  937. return;
  938. }
  939. usecoffset = offset->tv_sec * 1000000 + offset->tv_usec;
  940. clock_adjust = R_SHIFT(usecoffset, TIMECONSTANT); /* adjustment to make for next period */
  941. tmp = 0;
  942. while (adjustments > (1 << tmp))
  943. tmp++;
  944. adjustments = 0;
  945. if (tmp > FREQ_WEIGHT)
  946. tmp = FREQ_WEIGHT;
  947. accum_drift += R_SHIFT(usecoffset << USECSCALE, TIMECONSTANT+TIMECONSTANT+FREQ_WEIGHT-tmp);
  948. if (accum_drift > MAX_DRIFT) /* clamp into interval */
  949. accum_drift = MAX_DRIFT;
  950. else
  951. if (accum_drift < -MAX_DRIFT)
  952. accum_drift = -MAX_DRIFT;
  953. update_drift(drift_file, usecoffset, reftime);
  954. LPRINTF("clock_adjust: %s, clock_adjust %ld, drift_comp %ld(%ld) ",
  955. pr_timeval(offset),(long int) R_SHIFT(clock_adjust, USECSCALE),
  956. (long int)R_SHIFT(accum_drift, USECSCALE), (long int)accum_drift);
  957. }
  958. /*-----------------------------------------------------------------------
  959. * adjust the clock by a small mount to simulate frequency correction
  960. */
  961. static void
  962. periodic_adjust(
  963. void
  964. )
  965. {
  966. register long adjustment;
  967. adjustments++;
  968. adjustment = R_SHIFT(clock_adjust, PHASE_WEIGHT);
  969. clock_adjust -= adjustment;
  970. adjustment += R_SHIFT(accum_drift, USECSCALE+ADJINTERVAL);
  971. adj_time(adjustment);
  972. }
  973. /*-----------------------------------------------------------------------
  974. * control synchronisation status (warnings) and do periodic adjusts
  975. * (frequency control simulation)
  976. */
  977. static void
  978. tick(
  979. int signum
  980. )
  981. {
  982. static unsigned long last_notice = 0;
  983. #if !defined(HAVE_SIGACTION) && !defined(HAVE_SIGVEC)
  984. (void)signal(SIGALRM, tick);
  985. #endif
  986. periodic_adjust();
  987. ticks += 1<<ADJINTERVAL;
  988. if ((ticks - last_sync) > MAX_UNSYNC)
  989. {
  990. /*
  991. * not getting time for a while
  992. */
  993. if (sync_state == SYNC)
  994. {
  995. /*
  996. * completely lost information
  997. */
  998. sync_state = NO_SYNC;
  999. syslog(LOG_INFO, "DCF77 reception lost (timeout)");
  1000. last_notice = ticks;
  1001. }
  1002. else
  1003. /*
  1004. * in NO_SYNC state - look whether its time to speak up again
  1005. */
  1006. if ((ticks - last_notice) > NOTICE_INTERVAL)
  1007. {
  1008. syslog(LOG_NOTICE, "still not synchronized to DCF77 - check receiver/signal");
  1009. last_notice = ticks;
  1010. }
  1011. }
  1012. #ifndef ITIMER_REAL
  1013. (void) alarm(1<<ADJINTERVAL);
  1014. #endif
  1015. }
  1016. /*-----------------------------------------------------------------------
  1017. * break association from terminal to avoid catching terminal
  1018. * or process group related signals (-> daemon operation)
  1019. */
  1020. static void
  1021. detach(
  1022. void
  1023. )
  1024. {
  1025. # ifdef HAVE_DAEMON
  1026. daemon(0, 0);
  1027. # else /* not HAVE_DAEMON */
  1028. if (fork())
  1029. exit(0);
  1030. {
  1031. u_long s;
  1032. int max_fd;
  1033. #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
  1034. max_fd = sysconf(_SC_OPEN_MAX);
  1035. #else /* HAVE_SYSCONF && _SC_OPEN_MAX */
  1036. max_fd = getdtablesize();
  1037. #endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
  1038. for (s = 0; s < max_fd; s++)
  1039. (void) close((int)s);
  1040. (void) open("/", 0);
  1041. (void) dup2(0, 1);
  1042. (void) dup2(0, 2);
  1043. #ifdef SYS_DOMAINOS
  1044. {
  1045. uid_$t puid;
  1046. status_$t st;
  1047. proc2_$who_am_i(&puid);
  1048. proc2_$make_server(&puid, &st);
  1049. }
  1050. #endif /* SYS_DOMAINOS */
  1051. #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
  1052. # ifdef HAVE_SETSID
  1053. if (setsid() == (pid_t)-1)
  1054. syslog(LOG_ERR, "dcfd: setsid(): %m");
  1055. # else
  1056. if (setpgid(0, 0) == -1)
  1057. syslog(LOG_ERR, "dcfd: setpgid(): %m");
  1058. # endif
  1059. #else /* HAVE_SETPGID || HAVE_SETSID */
  1060. {
  1061. int fid;
  1062. fid = open("/dev/tty", 2);
  1063. if (fid >= 0)
  1064. {
  1065. (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
  1066. (void) close(fid);
  1067. }
  1068. # ifdef HAVE_SETPGRP_0
  1069. (void) setpgrp();
  1070. # else /* HAVE_SETPGRP_0 */
  1071. (void) setpgrp(0, getpid());
  1072. # endif /* HAVE_SETPGRP_0 */
  1073. }
  1074. #endif /* HAVE_SETPGID || HAVE_SETSID */
  1075. }
  1076. #endif /* not HAVE_DAEMON */
  1077. }
  1078. /*-----------------------------------------------------------------------
  1079. * list possible arguments and options
  1080. */
  1081. static void
  1082. usage(
  1083. char *program
  1084. )
  1085. {
  1086. fprintf(stderr, "usage: %s [-n] [-f] [-l] [-t] [-i] [-o] [-d <drift_file>] [-D <input delay>] <device>\n", program);
  1087. fprintf(stderr, "\t-n do not change time\n");
  1088. fprintf(stderr, "\t-i interactive\n");
  1089. fprintf(stderr, "\t-t trace (print all datagrams)\n");
  1090. fprintf(stderr, "\t-f print all databits (includes PTB private data)\n");
  1091. fprintf(stderr, "\t-l print loop filter debug information\n");
  1092. fprintf(stderr, "\t-o print offet average for current minute\n");
  1093. fprintf(stderr, "\t-Y make internal Y2K checks then exit\n"); /* Y2KFixes */
  1094. fprintf(stderr, "\t-d <drift_file> specify alternate drift file\n");
  1095. fprintf(stderr, "\t-D <input delay>specify delay from input edge to processing in micro seconds\n");
  1096. }
  1097. /*-----------------------------------------------------------------------
  1098. * check_y2k() - internal check of Y2K logic
  1099. * (a lot of this logic lifted from ../ntpd/check_y2k.c)
  1100. */
  1101. static int
  1102. check_y2k( void )
  1103. {
  1104. int year; /* current working year */
  1105. int year0 = 1900; /* sarting year for NTP time */
  1106. int yearend; /* ending year we test for NTP time.
  1107. * 32-bit systems: through 2036, the
  1108. **year in which NTP time overflows.
  1109. * 64-bit systems: a reasonable upper
  1110. **limit (well, maybe somewhat beyond
  1111. **reasonable, but well before the
  1112. **max time, by which time the earth
  1113. **will be dead.) */
  1114. time_t Time;
  1115. struct tm LocalTime;
  1116. int Fatals, Warnings;
  1117. #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
  1118. Warnings++; else Fatals++
  1119. Fatals = Warnings = 0;
  1120. Time = time( (time_t *)NULL );
  1121. LocalTime = *localtime( &Time );
  1122. year = ( sizeof( u_long ) > 4 ) /* save max span using year as temp */
  1123. ? ( 400 * 3 ) /* three greater gregorian cycles */
  1124. : ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
  1125. /* NOTE: will automacially expand test years on
  1126. * 64 bit machines.... this may cause some of the
  1127. * existing ntp logic to fail for years beyond
  1128. * 2036 (the current 32-bit limit). If all checks
  1129. * fail ONLY beyond year 2036 you may ignore such
  1130. * errors, at least for a decade or so. */
  1131. yearend = year0 + year;
  1132. year = 1900+YEAR_PIVOT;
  1133. printf( " starting year %04d\n", (int) year );
  1134. printf( " ending year %04d\n", (int) yearend );
  1135. for ( ; year < yearend; year++ )
  1136. {
  1137. clocktime_t ct;
  1138. time_t Observed;
  1139. time_t Expected;
  1140. unsigned Flag;
  1141. unsigned long t;
  1142. ct.day = 1;
  1143. ct.month = 1;
  1144. ct.year = year;
  1145. ct.hour = ct.minute = ct.second = ct.usecond = 0;
  1146. ct.utcoffset = 0;
  1147. ct.flags = 0;
  1148. Flag = 0;
  1149. Observed = dcf_to_unixtime( &ct, &Flag );
  1150. /* seems to be a clone of parse_to_unixtime() with
  1151. * *a minor difference to arg2 type */
  1152. if ( ct.year != year )
  1153. {
  1154. fprintf( stdout,
  1155. "%04d: dcf_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
  1156. (int)year, (int)Flag, (int)ct.year );
  1157. Error(year);
  1158. break;
  1159. }
  1160. t = julian0(year) - julian0(1970); /* Julian day from 1970 */
  1161. Expected = t * 24 * 60 * 60;
  1162. if ( Observed != Expected || Flag )
  1163. { /* time difference */
  1164. fprintf( stdout,
  1165. "%04d: dcf_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
  1166. year, (int)Flag,
  1167. (unsigned long)Observed, (unsigned long)Expected,
  1168. ((long)Observed - (long)Expected) );
  1169. Error(year);
  1170. break;
  1171. }
  1172. if ( year >= YEAR_PIVOT+1900 )
  1173. {
  1174. /* check year % 100 code we put into dcf_to_unixtime() */
  1175. ct.year = year % 100;
  1176. Flag = 0;
  1177. Observed = dcf_to_unixtime( &ct, &Flag );
  1178. if ( Observed != Expected || Flag )
  1179. { /* time difference */
  1180. fprintf( stdout,
  1181. "%04d: dcf_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
  1182. year, (int)ct.year, (int)Flag,
  1183. (unsigned long)Observed, (unsigned long)Expected,
  1184. ((long)Observed - (long)Expected) );
  1185. Error(year);
  1186. break;
  1187. }
  1188. /* check year - 1900 code we put into dcf_to_unixtime() */
  1189. ct.year = year - 1900;
  1190. Flag = 0;
  1191. Observed = dcf_to_unixtime( &ct, &Flag );
  1192. if ( Observed != Expected || Flag ) { /* time difference */
  1193. fprintf( stdout,
  1194. "%04d: dcf_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
  1195. year, (int)ct.year, (int)Flag,
  1196. (unsigned long)Observed, (unsigned long)Expected,
  1197. ((long)Observed - (long)Expected) );
  1198. Error(year);
  1199. break;
  1200. }
  1201. }
  1202. }
  1203. return ( Fatals );
  1204. }
  1205. /*--------------------------------------------------
  1206. * rawdcf_init - set up modem lines for RAWDCF receivers
  1207. */
  1208. #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
  1209. static void
  1210. rawdcf_init(
  1211. int fd
  1212. )
  1213. {
  1214. /*
  1215. * You can use the RS232 to supply the power for a DCF77 receiver.
  1216. * Here a voltage between the DTR and the RTS line is used. Unfortunately
  1217. * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
  1218. */
  1219. #ifdef TIOCM_DTR
  1220. int sl232 = TIOCM_DTR; /* turn on DTR for power supply */
  1221. #else
  1222. int sl232 = CIOCM_DTR; /* turn on DTR for power supply */
  1223. #endif
  1224. if (ioctl(fd, TIOCMSET, (caddr_t)&sl232) == -1)
  1225. {
  1226. syslog(LOG_NOTICE, "rawdcf_init: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m");
  1227. }
  1228. }
  1229. #else
  1230. static void
  1231. rawdcf_init(
  1232. int fd
  1233. )
  1234. {
  1235. syslog(LOG_NOTICE, "rawdcf_init: WARNING: OS interface incapable of setting DTR to power DCF modules");
  1236. }
  1237. #endif /* DTR initialisation type */
  1238. /*-----------------------------------------------------------------------
  1239. * main loop - argument interpreter / setup / main loop
  1240. */
  1241. int
  1242. main(
  1243. int argc,
  1244. char **argv
  1245. )
  1246. {
  1247. unsigned char c;
  1248. char **a = argv;
  1249. int ac = argc;
  1250. char *file = NULL;
  1251. const char *drift_file = "/etc/dcfd.drift";
  1252. int fd;
  1253. int offset = 15;
  1254. int offsets = 0;
  1255. int delay = DEFAULT_DELAY; /* average delay from input edge to time stamping */
  1256. int trace = 0;
  1257. int errs = 0;
  1258. /*
  1259. * process arguments
  1260. */
  1261. while (--ac)
  1262. {
  1263. char *arg = *++a;
  1264. if (*arg == '-')
  1265. while ((c = *++arg))
  1266. switch (c)
  1267. {
  1268. case 't':
  1269. trace = 1;
  1270. interactive = 1;
  1271. break;
  1272. case 'f':
  1273. offset = 0;
  1274. interactive = 1;
  1275. break;
  1276. case 'l':
  1277. loop_filter_debug = 1;
  1278. offsets = 1;
  1279. interactive = 1;
  1280. break;
  1281. case 'n':
  1282. no_set = 1;
  1283. break;
  1284. case 'o':
  1285. offsets = 1;
  1286. interactive = 1;
  1287. break;
  1288. case 'i':
  1289. interactive = 1;
  1290. break;
  1291. case 'D':
  1292. if (ac > 1)
  1293. {
  1294. delay = atoi(*++a);
  1295. ac--;
  1296. }
  1297. else
  1298. {
  1299. fprintf(stderr, "%s: -D requires integer argument\n", argv[0]);
  1300. errs=1;
  1301. }
  1302. break;
  1303. case 'd':
  1304. if (ac > 1)
  1305. {
  1306. drift_file = *++a;
  1307. ac--;
  1308. }
  1309. else
  1310. {
  1311. fprintf(stderr, "%s: -d requires file name argument\n", argv[0]);
  1312. errs=1;
  1313. }
  1314. break;
  1315. case 'Y':
  1316. errs=check_y2k();
  1317. exit( errs ? 1 : 0 );
  1318. default:
  1319. fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
  1320. errs=1;
  1321. break;
  1322. }
  1323. else
  1324. if (file == NULL)
  1325. file = arg;
  1326. else
  1327. {
  1328. fprintf(stderr, "%s: device specified twice\n", argv[0]);
  1329. errs=1;
  1330. }
  1331. }
  1332. if (errs)
  1333. {
  1334. usage(argv[0]);
  1335. exit(1);
  1336. }
  1337. else
  1338. if (file == NULL)
  1339. {
  1340. fprintf(stderr, "%s: device not specified\n", argv[0]);
  1341. usage(argv[0]);
  1342. exit(1);
  1343. }
  1344. errs = LINES+1;
  1345. /*
  1346. * get access to DCF77 tty port
  1347. */
  1348. fd = open(file, O_RDONLY);
  1349. if (fd == -1)
  1350. {
  1351. perror(file);
  1352. exit(1);
  1353. }
  1354. else
  1355. {
  1356. int i, rrc;
  1357. struct timeval t, tt, tlast;
  1358. struct timeval timeout;
  1359. struct timeval phase;
  1360. struct timeval time_offset;
  1361. char pbuf[61]; /* printable version */
  1362. char buf[61]; /* raw data */
  1363. clocktime_t clock_time; /* wall clock time */
  1364. time_t utc_time = 0;
  1365. time_t last_utc_time = 0;
  1366. long usecerror = 0;
  1367. long lasterror = 0;
  1368. #if defined(HAVE_TERMIOS_H) || defined(STREAM)
  1369. struct termios term;
  1370. #else /* not HAVE_TERMIOS_H || STREAM */
  1371. # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
  1372. struct termio term;
  1373. # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
  1374. #endif /* not HAVE_TERMIOS_H || STREAM */
  1375. unsigned int rtc = CVT_NONE;
  1376. rawdcf_init(fd);
  1377. timeout.tv_sec = 1;
  1378. timeout.tv_usec = 500000;
  1379. phase.tv_sec = 0;
  1380. phase.tv_usec = delay;
  1381. /*
  1382. * setup TTY (50 Baud, Read, 8Bit, No Hangup, 1 character IO)
  1383. */
  1384. if (TTY_GETATTR(fd, &term) == -1)
  1385. {
  1386. perror("tcgetattr");
  1387. exit(1);
  1388. }
  1389. memset(term.c_cc, 0, sizeof(term.c_cc));
  1390. term.c_cc[VMIN] = 1;
  1391. #ifdef NO_PARENB_IGNPAR
  1392. term.c_cflag = CS8|CREAD|CLOCAL;
  1393. #else
  1394. term.c_cflag = CS8|CREAD|CLOCAL|PARENB;
  1395. #endif
  1396. term.c_iflag = IGNPAR;
  1397. term.c_oflag = 0;
  1398. term.c_lflag = 0;
  1399. cfsetispeed(&term, B50);
  1400. cfsetospeed(&term, B50);
  1401. if (TTY_SETATTR(fd, &term) == -1)
  1402. {
  1403. perror("tcsetattr");
  1404. exit(1);
  1405. }
  1406. /*
  1407. * lose terminal if in daemon operation
  1408. */
  1409. if (!interactive)
  1410. detach();
  1411. /*
  1412. * get syslog() initialized
  1413. */
  1414. #ifdef LOG_DAEMON
  1415. openlog("dcfd", LOG_PID, LOG_DAEMON);
  1416. #else
  1417. openlog("dcfd", LOG_PID);
  1418. #endif
  1419. /*
  1420. * setup periodic operations (state control / frequency control)
  1421. */
  1422. #ifdef HAVE_SIGACTION
  1423. {
  1424. struct sigaction act;
  1425. # ifdef HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION
  1426. act.sa_sigaction = (void (*) P((int, siginfo_t *, void *)))0;
  1427. # endif /* HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION */
  1428. act.sa_handler = tick;
  1429. sigemptyset(&act.sa_mask);
  1430. act.sa_flags = 0;
  1431. if (sigaction(SIGALRM, &act, (struct sigaction *)0) == -1)
  1432. {
  1433. syslog(LOG_ERR, "sigaction(SIGALRM): %m");
  1434. exit(1);
  1435. }
  1436. }
  1437. #else
  1438. #ifdef HAVE_SIGVEC
  1439. {
  1440. struct sigvec vec;
  1441. vec.sv_handler = tick;
  1442. vec.sv_mask = 0;
  1443. vec.sv_flags = 0;
  1444. if (sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1)
  1445. {
  1446. syslog(LOG_ERR, "sigvec(SIGALRM): %m");
  1447. exit(1);
  1448. }
  1449. }
  1450. #else
  1451. (void) signal(SIGALRM, tick);
  1452. #endif
  1453. #endif
  1454. #ifdef ITIMER_REAL
  1455. {
  1456. struct itimerval it;
  1457. it.it_interval.tv_sec = 1<<ADJINTERVAL;
  1458. it.it_interval.tv_usec = 0;
  1459. it.it_value.tv_sec = 1<<ADJINTERVAL;
  1460. it.it_value.tv_usec = 0;
  1461. if (setitimer(ITIMER_REAL, &it, (struct itimerval *)0) == -1)
  1462. {
  1463. syslog(LOG_ERR, "setitimer: %m");
  1464. exit(1);
  1465. }
  1466. }
  1467. #else
  1468. (void) alarm(1<<ADJINTERVAL);
  1469. #endif
  1470. PRINTF(" DCF77 monitor %s - Copyright (C) 1993-2005 by Frank Kardel\n\n", revision);
  1471. pbuf[60] = '\0';
  1472. for ( i = 0; i < 60; i++)
  1473. pbuf[i] = '.';
  1474. read_drift(drift_file);
  1475. /*
  1476. * what time is it now (for interval measurement)
  1477. */
  1478. gettimeofday(&tlast, 0L);
  1479. i = 0;
  1480. /*
  1481. * loop until input trouble ...
  1482. */
  1483. do
  1484. {
  1485. /*
  1486. * get an impulse
  1487. */
  1488. while ((rrc = read(fd, &c, 1)) == 1)
  1489. {
  1490. gettimeofday(&t, 0L);
  1491. tt = t;
  1492. timersub(&t, &tlast);
  1493. if (errs > LINES)
  1494. {
  1495. PRINTF(" %s", &"PTB private....RADMLSMin....PHour..PMDay..DayMonthYear....P\n"[offset]);
  1496. PRINTF(" %s", &"---------------RADMLS1248124P124812P1248121241248112481248P\n"[offset]);
  1497. errs = 0;
  1498. }
  1499. /*
  1500. * timeout -> possible minute mark -> interpretation
  1501. */
  1502. if (timercmp(&t, &timeout, >))
  1503. {
  1504. PRINTF("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &pbuf[offset]);
  1505. if ((rtc = cvt_rawdcf((unsigned char *)buf, i, &clock_time)) != CVT_OK)
  1506. {
  1507. /*
  1508. * this data was bad - well - forget synchronisation for now
  1509. */
  1510. PRINTF("\n");
  1511. if (sync_state == SYNC)
  1512. {
  1513. sync_state = NO_SYNC;
  1514. syslog(LOG_INFO, "DCF77 reception lost (bad data)");
  1515. }
  1516. errs++;
  1517. }
  1518. else
  1519. if (trace)
  1520. {
  1521. PRINTF("\r %.*s ", 59 - offset, &buf[offset]);
  1522. }
  1523. buf[0] = c;
  1524. /*
  1525. * collect first character
  1526. */
  1527. if (((c^0xFF)+1) & (c^0xFF))
  1528. pbuf[0] = '?';
  1529. else
  1530. pbuf[0] = type(c) ? '#' : '-';
  1531. for ( i = 1; i < 60; i++)
  1532. pbuf[i] = '.';
  1533. i = 0;
  1534. }
  1535. else
  1536. {
  1537. /*
  1538. * collect character
  1539. */
  1540. buf[i] = c;
  1541. /*
  1542. * initial guess (usually correct)
  1543. */
  1544. if (((c^0xFF)+1) & (c^0xFF))
  1545. pbuf[i] = '?';
  1546. else
  1547. pbuf[i] = type(c) ? '#' : '-';
  1548. PRINTF("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &pbuf[offset]);
  1549. }
  1550. if (i == 0 && rtc == CVT_OK)
  1551. {
  1552. /*
  1553. * we got a good time code here - try to convert it to
  1554. * UTC
  1555. */
  1556. if ((utc_time = dcf_to_unixtime(&clock_time, &rtc)) == -1)
  1557. {
  1558. PRINTF("*** BAD CONVERSION\n");
  1559. }
  1560. if (utc_time != (last_utc_time + 60))
  1561. {
  1562. /*
  1563. * well, two successive sucessful telegrams are not 60 seconds
  1564. * apart
  1565. */
  1566. PRINTF("*** NO MINUTE INC\n");
  1567. if (sync_state == SYNC)
  1568. {
  1569. sync_state = NO_SYNC;
  1570. syslog(LOG_INFO, "DCF77 reception lost (data mismatch)");
  1571. }
  1572. errs++;
  1573. rtc = CVT_FAIL|CVT_BADTIME|CVT_BADDATE;
  1574. }
  1575. else
  1576. usecerror = 0;
  1577. last_utc_time = utc_time;
  1578. }
  1579. if (rtc == CVT_OK)
  1580. {
  1581. if (i == 0)
  1582. {
  1583. /*
  1584. * valid time code - determine offset and
  1585. * note regained reception
  1586. */
  1587. last_sync = ticks;
  1588. if (sync_state == NO_SYNC)
  1589. {
  1590. syslog(LOG_INFO, "receiving DCF77");
  1591. }
  1592. else
  1593. {
  1594. /*
  1595. * we had at least one minute SYNC - thus
  1596. * last error is valid
  1597. */
  1598. time_offset.tv_sec = lasterror / 1000000;
  1599. time_offset.tv_usec = lasterror % 1000000;
  1600. adjust_clock(&time_offset, drift_file, utc_time);
  1601. }
  1602. sync_state = SYNC;
  1603. }
  1604. time_offset.tv_sec = utc_time + i;
  1605. time_offset.tv_usec = 0;
  1606. timeradd(&time_offset, &phase);
  1607. usecerror += (time_offset.tv_sec - tt.tv_sec) * 1000000 + time_offset.tv_usec
  1608. -tt.tv_usec;
  1609. /*
  1610. * output interpreted DCF77 data
  1611. */
  1612. PRINTF(offsets ? "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s> (%c%ld.%06lds)" :
  1613. "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s>",
  1614. wday[clock_time.wday],
  1615. clock_time.hour, clock_time.minute, i, clock_time.day, clock_time.month,
  1616. clock_time.year,
  1617. (clock_time.flags & DCFB_ALTERNATE) ? "R" : "_",
  1618. (clock_time.flags & DCFB_ANNOUNCE) ? "A" : "_",
  1619. (clock_time.flags & DCFB_DST) ? "D" : "_",
  1620. (clock_time.flags & DCFB_LEAP) ? "L" : "_",
  1621. (lasterror < 0) ? '-' : '+', l_abs(lasterror) / 1000000, l_abs(lasterror) % 1000000
  1622. );
  1623. if (trace && (i == 0))
  1624. {
  1625. PRINTF("\n");
  1626. errs++;
  1627. }
  1628. lasterror = usecerror / (i+1);
  1629. }
  1630. else
  1631. {
  1632. lasterror = 0; /* we cannot calculate phase errors on bad reception */
  1633. }
  1634. PRINTF("\r");
  1635. if (i < 60)
  1636. {
  1637. i++;
  1638. }
  1639. tlast = tt;
  1640. if (interactive)
  1641. fflush(stdout);
  1642. }
  1643. } while ((rrc == -1) && (errno == EINTR));
  1644. /*
  1645. * lost IO - sorry guys
  1646. */
  1647. syslog(LOG_ERR, "TERMINATING - cannot read from device %s (%m)", file);
  1648. (void)close(fd);
  1649. }
  1650. closelog();
  1651. return 0;
  1652. }
  1653. /*
  1654. * History:
  1655. *
  1656. * dcfd.c,v
  1657. * Revision 4.18 2005/10/07 22:08:18 kardel
  1658. * make dcfd.c compile on NetBSD 3.99.9 again (configure/sigvec compatibility fix)
  1659. *
  1660. * Revision 4.17.2.1 2005/10/03 19:15:16 kardel
  1661. * work around configure not detecting a missing sigvec compatibility
  1662. * interface on NetBSD 3.99.9 and above
  1663. *
  1664. * Revision 4.17 2005/08/10 10:09:44 kardel
  1665. * output revision information
  1666. *
  1667. * Revision 4.16 2005/08/10 06:33:25 kardel
  1668. * cleanup warnings
  1669. *
  1670. * Revision 4.15 2005/08/10 06:28:45 kardel
  1671. * fix setting of baud rate
  1672. *
  1673. * Revision 4.14 2005/04/16 17:32:10 kardel
  1674. * update copyright
  1675. *
  1676. * Revision 4.13 2004/11/14 15:29:41 kardel
  1677. * support PPSAPI, upgrade Copyright to Berkeley style
  1678. *
  1679. */