/contrib/ntp/ntpd/refclock_parse.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 6045 lines · 4944 code · 454 blank · 647 comment · 325 complexity · a9fc6f6dec53b0ddcd71ea98b160bb1f MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
  3. *
  4. * refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
  5. *
  6. * generic reference clock driver for several DCF/GPS/MSF/... receivers
  7. *
  8. * PPS notes:
  9. * On systems that support PPSAPI (RFC2783) PPSAPI is the
  10. * preferred interface.
  11. *
  12. * Optionally make use of a STREAMS module for input processing where
  13. * available and configured. This STREAMS module reduces the time
  14. * stamp latency for serial and PPS events.
  15. * Currently the STREAMS module is only available for Suns running
  16. * SunOS 4.x and SunOS5.x.
  17. *
  18. * Copyright (c) 1995-2007 by Frank Kardel <kardel <AT> ntp.org>
  19. * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
  20. *
  21. * Redistribution and use in source and binary forms, with or without
  22. * modification, are permitted provided that the following conditions
  23. * are met:
  24. * 1. Redistributions of source code must retain the above copyright
  25. * notice, this list of conditions and the following disclaimer.
  26. * 2. Redistributions in binary form must reproduce the above copyright
  27. * notice, this list of conditions and the following disclaimer in the
  28. * documentation and/or other materials provided with the distribution.
  29. * 3. Neither the name of the author nor the names of its contributors
  30. * may be used to endorse or promote products derived from this software
  31. * without specific prior written permission.
  32. *
  33. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  34. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  35. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  37. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  38. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  39. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  40. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  41. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  42. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  43. * SUCH DAMAGE.
  44. *
  45. */
  46. #ifdef HAVE_CONFIG_H
  47. # include "config.h"
  48. #endif
  49. #if defined(REFCLOCK) && defined(CLOCK_PARSE)
  50. /*
  51. * This driver currently provides the support for
  52. * - Meinberg receiver DCF77 PZF 535 (TCXO version) (DCF)
  53. * - Meinberg receiver DCF77 PZF 535 (OCXO version) (DCF)
  54. * - Meinberg receiver DCF77 PZF 509 (DCF)
  55. * - Meinberg receiver DCF77 AM receivers (e.g. C51) (DCF)
  56. * - IGEL CLOCK (DCF)
  57. * - ELV DCF7000 (DCF)
  58. * - Schmid clock (DCF)
  59. * - Conrad DCF77 receiver module (DCF)
  60. * - FAU DCF77 NTP receiver (TimeBrick) (DCF)
  61. * - WHARTON 400A Series clock (DCF)
  62. *
  63. * - Meinberg GPS166/GPS167 (GPS)
  64. * - Trimble (TSIP and TAIP protocol) (GPS)
  65. *
  66. * - RCC8000 MSF Receiver (MSF)
  67. * - VARITEXT clock (MSF)
  68. */
  69. /*
  70. * Meinberg receivers are usually connected via a
  71. * 9600 baud serial line
  72. *
  73. * The Meinberg GPS receivers also have a special NTP time stamp
  74. * format. The firmware release is Uni-Erlangen.
  75. *
  76. * Meinberg generic receiver setup:
  77. * output time code every second
  78. * Baud rate 9600 7E2S
  79. *
  80. * Meinberg GPS16x setup:
  81. * output time code every second
  82. * Baudrate 19200 8N1
  83. *
  84. * This software supports the standard data formats used
  85. * in Meinberg receivers.
  86. *
  87. * Special software versions are only sensible for the
  88. * GPS 16x family of receivers.
  89. *
  90. * Meinberg can be reached via: http://www.meinberg.de/
  91. */
  92. #include "ntpd.h"
  93. #include "ntp_refclock.h"
  94. #include "ntp_unixtime.h" /* includes <sys/time.h> */
  95. #include "ntp_control.h"
  96. #include "ntp_string.h"
  97. #include <stdio.h>
  98. #include <ctype.h>
  99. #ifndef TM_IN_SYS_TIME
  100. # include <time.h>
  101. #endif
  102. #ifdef HAVE_UNISTD_H
  103. # include <unistd.h>
  104. #endif
  105. #if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
  106. # include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"
  107. #endif
  108. #ifdef STREAM
  109. # include <sys/stream.h>
  110. # include <sys/stropts.h>
  111. #endif
  112. #ifdef HAVE_TERMIOS
  113. # define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
  114. # define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
  115. # undef HAVE_SYSV_TTYS
  116. #endif
  117. #ifdef HAVE_SYSV_TTYS
  118. # define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
  119. # define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
  120. #endif
  121. #ifdef HAVE_BSD_TTYS
  122. /* #error CURRENTLY NO BSD TTY SUPPORT */
  123. # include "Bletch: BSD TTY not currently supported"
  124. #endif
  125. #ifdef HAVE_SYS_IOCTL_H
  126. # include <sys/ioctl.h>
  127. #endif
  128. #ifdef HAVE_PPSAPI
  129. # include "ppsapi_timepps.h"
  130. #endif
  131. #ifdef PPS
  132. # ifdef HAVE_SYS_PPSCLOCK_H
  133. # include <sys/ppsclock.h>
  134. # endif
  135. # ifdef HAVE_TIO_SERIAL_STUFF
  136. # include <linux/serial.h>
  137. # endif
  138. #endif
  139. #define BUFFER_SIZE(_BUF, _PTR) ((_BUF) + sizeof(_BUF) - (_PTR))
  140. #define BUFFER_SIZES(_BUF, _PTR, _SZ) ((_BUF) + (_SZ) - (_PTR))
  141. /*
  142. * document type of PPS interfacing - copy of ifdef mechanism in local_input()
  143. */
  144. #undef PPS_METHOD
  145. #ifdef HAVE_PPSAPI
  146. #define PPS_METHOD "PPS API"
  147. #else
  148. #ifdef TIOCDCDTIMESTAMP
  149. #define PPS_METHOD "TIOCDCDTIMESTAMP"
  150. #else /* TIOCDCDTIMESTAMP */
  151. #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
  152. #ifdef HAVE_CIOGETEV
  153. #define PPS_METHOD "CIOGETEV"
  154. #endif
  155. #ifdef HAVE_TIOCGPPSEV
  156. #define PPS_METHOD "TIOCGPPSEV"
  157. #endif
  158. #endif
  159. #endif /* TIOCDCDTIMESTAMP */
  160. #endif /* HAVE_PPSAPI */
  161. #include "ntp_io.h"
  162. #include "ntp_stdlib.h"
  163. #include "parse.h"
  164. #include "mbg_gps166.h"
  165. #include "trimble.h"
  166. #include "binio.h"
  167. #include "ascii.h"
  168. #include "ieee754io.h"
  169. #include "recvbuff.h"
  170. static char rcsid[] = "refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp";
  171. /**===========================================================================
  172. ** external interface to ntp mechanism
  173. **/
  174. static int parse_start P((int, struct peer *));
  175. static void parse_shutdown P((int, struct peer *));
  176. static void parse_poll P((int, struct peer *));
  177. static void parse_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
  178. struct refclock refclock_parse = {
  179. parse_start,
  180. parse_shutdown,
  181. parse_poll,
  182. parse_control,
  183. noentry,
  184. noentry,
  185. NOFLAGS
  186. };
  187. /*
  188. * Definitions
  189. */
  190. #define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
  191. #define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
  192. #define PARSEPPSDEVICE "/dev/refclockpps-%d" /* optional pps device to open %d is unit number */
  193. #undef ABS
  194. #define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
  195. #define PARSE_HARDPPS_DISABLE 0
  196. #define PARSE_HARDPPS_ENABLE 1
  197. /**===========================================================================
  198. ** function vector for dynamically binding io handling mechanism
  199. **/
  200. struct parseunit; /* to keep inquiring minds happy */
  201. typedef struct bind
  202. {
  203. const char *bd_description; /* name of type of binding */
  204. int (*bd_init) P((struct parseunit *)); /* initialize */
  205. void (*bd_end) P((struct parseunit *)); /* end */
  206. int (*bd_setcs) P((struct parseunit *, parsectl_t *)); /* set character size */
  207. int (*bd_disable) P((struct parseunit *)); /* disable */
  208. int (*bd_enable) P((struct parseunit *)); /* enable */
  209. int (*bd_getfmt) P((struct parseunit *, parsectl_t *)); /* get format */
  210. int (*bd_setfmt) P((struct parseunit *, parsectl_t *)); /* setfmt */
  211. int (*bd_timecode) P((struct parseunit *, parsectl_t *)); /* get time code */
  212. void (*bd_receive) P((struct recvbuf *)); /* receive operation */
  213. int (*bd_io_input) P((struct recvbuf *)); /* input operation */
  214. } bind_t;
  215. #define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
  216. #define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)
  217. #define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)
  218. #define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)
  219. #define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
  220. #define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
  221. #define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
  222. /*
  223. * io modes
  224. */
  225. #define PARSE_F_PPSPPS 0x0001 /* use loopfilter PPS code (CIOGETEV) */
  226. #define PARSE_F_PPSONSECOND 0x0002 /* PPS pulses are on second */
  227. /**===========================================================================
  228. ** error message regression handling
  229. **
  230. ** there are quite a few errors that can occur in rapid succession such as
  231. ** noisy input data or no data at all. in order to reduce the amount of
  232. ** syslog messages in such case, we are using a backoff algorithm. We limit
  233. ** the number of error messages of a certain class to 1 per time unit. if a
  234. ** configurable number of messages is displayed that way, we move on to the
  235. ** next time unit / count for that class. a count of messages that have been
  236. ** suppressed is held and displayed whenever a corresponding message is
  237. ** displayed. the time units for a message class will also be displayed.
  238. ** whenever an error condition clears we reset the error message state,
  239. ** thus we would still generate much output on pathological conditions
  240. ** where the system oscillates between OK and NOT OK states. coping
  241. ** with that condition is currently considered too complicated.
  242. **/
  243. #define ERR_ALL (unsigned)~0 /* "all" errors */
  244. #define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */
  245. #define ERR_NODATA (unsigned)1 /* no input data */
  246. #define ERR_BADIO (unsigned)2 /* read/write/select errors */
  247. #define ERR_BADSTATUS (unsigned)3 /* unsync states */
  248. #define ERR_BADEVENT (unsigned)4 /* non nominal events */
  249. #define ERR_INTERNAL (unsigned)5 /* internal error */
  250. #define ERR_CNT (unsigned)(ERR_INTERNAL+1)
  251. #define ERR(_X_) if (list_err(parse, (_X_)))
  252. struct errorregression
  253. {
  254. u_long err_count; /* number of repititions per class */
  255. u_long err_delay; /* minimum delay between messages */
  256. };
  257. static struct errorregression
  258. err_baddata[] = /* error messages for bad input data */
  259. {
  260. { 1, 0 }, /* output first message immediately */
  261. { 5, 60 }, /* output next five messages in 60 second intervals */
  262. { 3, 3600 }, /* output next 3 messages in hour intervals */
  263. { 0, 12*3600 } /* repeat messages only every 12 hours */
  264. };
  265. static struct errorregression
  266. err_nodata[] = /* error messages for missing input data */
  267. {
  268. { 1, 0 }, /* output first message immediately */
  269. { 5, 60 }, /* output next five messages in 60 second intervals */
  270. { 3, 3600 }, /* output next 3 messages in hour intervals */
  271. { 0, 12*3600 } /* repeat messages only every 12 hours */
  272. };
  273. static struct errorregression
  274. err_badstatus[] = /* unsynchronized state messages */
  275. {
  276. { 1, 0 }, /* output first message immediately */
  277. { 5, 60 }, /* output next five messages in 60 second intervals */
  278. { 3, 3600 }, /* output next 3 messages in hour intervals */
  279. { 0, 12*3600 } /* repeat messages only every 12 hours */
  280. };
  281. static struct errorregression
  282. err_badio[] = /* io failures (bad reads, selects, ...) */
  283. {
  284. { 1, 0 }, /* output first message immediately */
  285. { 5, 60 }, /* output next five messages in 60 second intervals */
  286. { 5, 3600 }, /* output next 3 messages in hour intervals */
  287. { 0, 12*3600 } /* repeat messages only every 12 hours */
  288. };
  289. static struct errorregression
  290. err_badevent[] = /* non nominal events */
  291. {
  292. { 20, 0 }, /* output first message immediately */
  293. { 6, 60 }, /* output next five messages in 60 second intervals */
  294. { 5, 3600 }, /* output next 3 messages in hour intervals */
  295. { 0, 12*3600 } /* repeat messages only every 12 hours */
  296. };
  297. static struct errorregression
  298. err_internal[] = /* really bad things - basically coding/OS errors */
  299. {
  300. { 0, 0 }, /* output all messages immediately */
  301. };
  302. static struct errorregression *
  303. err_tbl[] =
  304. {
  305. err_baddata,
  306. err_nodata,
  307. err_badio,
  308. err_badstatus,
  309. err_badevent,
  310. err_internal
  311. };
  312. struct errorinfo
  313. {
  314. u_long err_started; /* begin time (ntp) of error condition */
  315. u_long err_last; /* last time (ntp) error occurred */
  316. u_long err_cnt; /* number of error repititions */
  317. u_long err_suppressed; /* number of suppressed messages */
  318. struct errorregression *err_stage; /* current error stage */
  319. };
  320. /**===========================================================================
  321. ** refclock instance data
  322. **/
  323. struct parseunit
  324. {
  325. /*
  326. * NTP management
  327. */
  328. struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
  329. struct refclockproc *generic; /* backlink to refclockproc structure */
  330. /*
  331. * PARSE io
  332. */
  333. bind_t *binding; /* io handling binding */
  334. /*
  335. * parse state
  336. */
  337. parse_t parseio; /* io handling structure (user level parsing) */
  338. /*
  339. * type specific parameters
  340. */
  341. struct parse_clockinfo *parse_type; /* link to clock description */
  342. /*
  343. * clock state handling/reporting
  344. */
  345. u_char flags; /* flags (leap_control) */
  346. u_long lastchange; /* time (ntp) when last state change accured */
  347. u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
  348. u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */
  349. u_short lastformat; /* last format used */
  350. u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */
  351. u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */
  352. double ppsphaseadjust; /* phase adjustment of PPS time stamp */
  353. u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */
  354. u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
  355. int ppsfd; /* fd to ise for PPS io */
  356. #ifdef HAVE_PPSAPI
  357. pps_handle_t ppshandle; /* store PPSAPI handle */
  358. pps_params_t ppsparams; /* current PPS parameters */
  359. int hardppsstate; /* current hard pps state */
  360. #endif
  361. parsetime_t timedata; /* last (parse module) data */
  362. void *localdata; /* optional local, receiver-specific data */
  363. unsigned long localstate; /* private local state */
  364. struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */
  365. struct ctl_var *kv; /* additional pseudo variables */
  366. u_long laststatistic; /* time when staticstics where output */
  367. };
  368. /**===========================================================================
  369. ** Clockinfo section all parameter for specific clock types
  370. ** includes NTP parameters, TTY parameters and IO handling parameters
  371. **/
  372. static void poll_dpoll P((struct parseunit *));
  373. static void poll_poll P((struct peer *));
  374. static int poll_init P((struct parseunit *));
  375. typedef struct poll_info
  376. {
  377. u_long rate; /* poll rate - once every "rate" seconds - 0 off */
  378. const char *string; /* string to send for polling */
  379. u_long count; /* number of characters in string */
  380. } poll_info_t;
  381. #define NO_CL_FLAGS 0
  382. #define NO_POLL 0
  383. #define NO_INIT 0
  384. #define NO_END 0
  385. #define NO_EVENT 0
  386. #define NO_LCLDATA 0
  387. #define NO_MESSAGE 0
  388. #define NO_PPSDELAY 0
  389. #define DCF_ID "DCF" /* generic DCF */
  390. #define DCF_A_ID "DCFa" /* AM demodulation */
  391. #define DCF_P_ID "DCFp" /* psuedo random phase shift */
  392. #define GPS_ID "GPS" /* GPS receiver */
  393. #define NOCLOCK_ROOTDELAY 0.0
  394. #define NOCLOCK_BASEDELAY 0.0
  395. #define NOCLOCK_DESCRIPTION 0
  396. #define NOCLOCK_MAXUNSYNC 0
  397. #define NOCLOCK_CFLAG 0
  398. #define NOCLOCK_IFLAG 0
  399. #define NOCLOCK_OFLAG 0
  400. #define NOCLOCK_LFLAG 0
  401. #define NOCLOCK_ID "TILT"
  402. #define NOCLOCK_POLL NO_POLL
  403. #define NOCLOCK_INIT NO_INIT
  404. #define NOCLOCK_END NO_END
  405. #define NOCLOCK_DATA NO_LCLDATA
  406. #define NOCLOCK_FORMAT ""
  407. #define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
  408. #define NOCLOCK_SAMPLES 0
  409. #define NOCLOCK_KEEP 0
  410. #define DCF_TYPE CTL_SST_TS_LF
  411. #define GPS_TYPE CTL_SST_TS_UHF
  412. /*
  413. * receiver specific constants
  414. */
  415. #define MBG_SPEED (B9600)
  416. #define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)
  417. #define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
  418. #define MBG_OFLAG 0
  419. #define MBG_LFLAG 0
  420. #define MBG_FLAGS PARSE_F_PPSONSECOND
  421. /*
  422. * Meinberg DCF77 receivers
  423. */
  424. #define DCFUA31_ROOTDELAY 0.0 /* 0 */
  425. #define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */
  426. #define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible"
  427. #define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
  428. #define DCFUA31_SPEED MBG_SPEED
  429. #define DCFUA31_CFLAG MBG_CFLAG
  430. #define DCFUA31_IFLAG MBG_IFLAG
  431. #define DCFUA31_OFLAG MBG_OFLAG
  432. #define DCFUA31_LFLAG MBG_LFLAG
  433. #define DCFUA31_SAMPLES 5
  434. #define DCFUA31_KEEP 3
  435. #define DCFUA31_FORMAT "Meinberg Standard"
  436. /*
  437. * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
  438. */
  439. #define DCFPZF535_ROOTDELAY 0.0
  440. #define DCFPZF535_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  441. #define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/509 / TCXO"
  442. #define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours
  443. * @ 5e-8df/f we have accumulated
  444. * at most 2.16 ms (thus we move to
  445. * NTP synchronisation */
  446. #define DCFPZF535_SPEED MBG_SPEED
  447. #define DCFPZF535_CFLAG MBG_CFLAG
  448. #define DCFPZF535_IFLAG MBG_IFLAG
  449. #define DCFPZF535_OFLAG MBG_OFLAG
  450. #define DCFPZF535_LFLAG MBG_LFLAG
  451. #define DCFPZF535_SAMPLES 5
  452. #define DCFPZF535_KEEP 3
  453. #define DCFPZF535_FORMAT "Meinberg Standard"
  454. /*
  455. * Meinberg DCF PZF535/OCXO receiver
  456. */
  457. #define DCFPZF535OCXO_ROOTDELAY 0.0
  458. #define DCFPZF535OCXO_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  459. #define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / OCXO"
  460. #define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
  461. * @ 5e-9df/f we have accumulated
  462. * at most an error of 1.73 ms
  463. * (thus we move to NTP synchronisation) */
  464. #define DCFPZF535OCXO_SPEED MBG_SPEED
  465. #define DCFPZF535OCXO_CFLAG MBG_CFLAG
  466. #define DCFPZF535OCXO_IFLAG MBG_IFLAG
  467. #define DCFPZF535OCXO_OFLAG MBG_OFLAG
  468. #define DCFPZF535OCXO_LFLAG MBG_LFLAG
  469. #define DCFPZF535OCXO_SAMPLES 5
  470. #define DCFPZF535OCXO_KEEP 3
  471. #define DCFPZF535OCXO_FORMAT "Meinberg Standard"
  472. /*
  473. * Meinberg GPS16X receiver
  474. */
  475. static void gps16x_message P((struct parseunit *, parsetime_t *));
  476. static int gps16x_poll_init P((struct parseunit *));
  477. #define GPS16X_ROOTDELAY 0.0 /* nothing here */
  478. #define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  479. #define GPS16X_DESCRIPTION "Meinberg GPS16x receiver"
  480. #define GPS16X_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
  481. * @ 5e-9df/f we have accumulated
  482. * at most an error of 1.73 ms
  483. * (thus we move to NTP synchronisation) */
  484. #define GPS16X_SPEED B19200
  485. #define GPS16X_CFLAG (CS8|CREAD|CLOCAL|HUPCL)
  486. #define GPS16X_IFLAG (IGNBRK|IGNPAR)
  487. #define GPS16X_OFLAG MBG_OFLAG
  488. #define GPS16X_LFLAG MBG_LFLAG
  489. #define GPS16X_POLLRATE 6
  490. #define GPS16X_POLLCMD ""
  491. #define GPS16X_CMDSIZE 0
  492. static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE };
  493. #define GPS16X_INIT gps16x_poll_init
  494. #define GPS16X_POLL 0
  495. #define GPS16X_END 0
  496. #define GPS16X_DATA ((void *)(&gps16x_pollinfo))
  497. #define GPS16X_MESSAGE gps16x_message
  498. #define GPS16X_ID GPS_ID
  499. #define GPS16X_FORMAT "Meinberg GPS Extended"
  500. #define GPS16X_SAMPLES 5
  501. #define GPS16X_KEEP 3
  502. /*
  503. * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
  504. *
  505. * This is really not the hottest clock - but before you have nothing ...
  506. */
  507. #define DCF7000_ROOTDELAY 0.0 /* 0 */
  508. #define DCF7000_BASEDELAY 0.405 /* slow blow */
  509. #define DCF7000_DESCRIPTION "ELV DCF7000"
  510. #define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
  511. #define DCF7000_SPEED (B9600)
  512. #define DCF7000_CFLAG (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
  513. #define DCF7000_IFLAG (IGNBRK)
  514. #define DCF7000_OFLAG 0
  515. #define DCF7000_LFLAG 0
  516. #define DCF7000_SAMPLES 5
  517. #define DCF7000_KEEP 3
  518. #define DCF7000_FORMAT "ELV DCF7000"
  519. /*
  520. * Schmid DCF Receiver Kit
  521. *
  522. * When the WSDCF clock is operating optimally we want the primary clock
  523. * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer
  524. * structure is set to 290 ms and we compute delays which are at least
  525. * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format
  526. */
  527. #define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */
  528. #define WS_POLLCMD "\163"
  529. #define WS_CMDSIZE 1
  530. static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
  531. #define WSDCF_INIT poll_init
  532. #define WSDCF_POLL poll_dpoll
  533. #define WSDCF_END 0
  534. #define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
  535. #define WSDCF_ROOTDELAY 0.0 /* 0 */
  536. #define WSDCF_BASEDELAY 0.010 /* ~ 10ms */
  537. #define WSDCF_DESCRIPTION "WS/DCF Receiver"
  538. #define WSDCF_FORMAT "Schmid"
  539. #define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */
  540. #define WSDCF_SPEED (B1200)
  541. #define WSDCF_CFLAG (CS8|CREAD|CLOCAL)
  542. #define WSDCF_IFLAG 0
  543. #define WSDCF_OFLAG 0
  544. #define WSDCF_LFLAG 0
  545. #define WSDCF_SAMPLES 5
  546. #define WSDCF_KEEP 3
  547. /*
  548. * RAW DCF77 - input of DCF marks via RS232 - many variants
  549. */
  550. #define RAWDCF_FLAGS 0
  551. #define RAWDCF_ROOTDELAY 0.0 /* 0 */
  552. #define RAWDCF_BASEDELAY 0.258
  553. #define RAWDCF_FORMAT "RAW DCF77 Timecode"
  554. #define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */
  555. #define RAWDCF_SPEED (B50)
  556. #ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */
  557. /* somehow doesn't grok PARENB & IGNPAR (mj) */
  558. # define RAWDCF_CFLAG (CS8|CREAD|CLOCAL)
  559. #else
  560. # define RAWDCF_CFLAG (CS8|CREAD|CLOCAL|PARENB)
  561. #endif
  562. #ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */
  563. # define RAWDCF_IFLAG 0
  564. #else
  565. # define RAWDCF_IFLAG (IGNPAR)
  566. #endif
  567. #define RAWDCF_OFLAG 0
  568. #define RAWDCF_LFLAG 0
  569. #define RAWDCF_SAMPLES 20
  570. #define RAWDCF_KEEP 12
  571. #define RAWDCF_INIT 0
  572. /*
  573. * RAW DCF variants
  574. */
  575. /*
  576. * Conrad receiver
  577. *
  578. * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
  579. * (~40DM - roughly $30 ) followed by a level converter for RS232
  580. */
  581. #define CONRAD_BASEDELAY 0.292 /* Conrad receiver @ 50 Baud on a Sun */
  582. #define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
  583. /* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */
  584. #define GUDE_EMC_USB_V20_SPEED (B4800)
  585. #define GUDE_EMC_USB_V20_BASEDELAY 0.425 /* USB serial<->USB converter FTDI232R */
  586. #define GUDE_EMC_USB_V20_DESCRIPTION "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)"
  587. /*
  588. * TimeBrick receiver
  589. */
  590. #define TIMEBRICK_BASEDELAY 0.210 /* TimeBrick @ 50 Baud on a Sun */
  591. #define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
  592. /*
  593. * IGEL:clock receiver
  594. */
  595. #define IGELCLOCK_BASEDELAY 0.258 /* IGEL:clock receiver */
  596. #define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)"
  597. #define IGELCLOCK_SPEED (B1200)
  598. #define IGELCLOCK_CFLAG (CS8|CREAD|HUPCL|CLOCAL)
  599. /*
  600. * RAWDCF receivers that need to be powered from DTR
  601. * (like Expert mouse clock)
  602. */
  603. static int rawdcf_init_1 P((struct parseunit *));
  604. #define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)"
  605. #define RAWDCFDTRSET_INIT rawdcf_init_1
  606. /*
  607. * RAWDCF receivers that need to be powered from
  608. * DTR CLR and RTS SET
  609. */
  610. static int rawdcf_init_2 P((struct parseunit *));
  611. #define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)"
  612. #define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2
  613. /*
  614. * Trimble GPS receivers (TAIP and TSIP protocols)
  615. */
  616. #ifndef TRIM_POLLRATE
  617. #define TRIM_POLLRATE 0 /* only true direct polling */
  618. #endif
  619. #define TRIM_TAIPPOLLCMD ">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<"
  620. #define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1)
  621. static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
  622. static int trimbletaip_init P((struct parseunit *));
  623. static void trimbletaip_event P((struct parseunit *, int));
  624. /* query time & UTC correction data */
  625. static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
  626. static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
  627. static int trimbletsip_init P((struct parseunit *));
  628. static void trimbletsip_end P((struct parseunit *));
  629. static void trimbletsip_message P((struct parseunit *, parsetime_t *));
  630. static void trimbletsip_event P((struct parseunit *, int));
  631. #define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
  632. #define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME
  633. #define TRIMBLETAIP_SPEED (B4800)
  634. #define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL)
  635. #define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
  636. #define TRIMBLETAIP_OFLAG (OPOST|ONLCR)
  637. #define TRIMBLETAIP_LFLAG (0)
  638. #define TRIMBLETSIP_SPEED (B9600)
  639. #define TRIMBLETSIP_CFLAG (CS8|CLOCAL|CREAD|PARENB|PARODD)
  640. #define TRIMBLETSIP_IFLAG (IGNBRK)
  641. #define TRIMBLETSIP_OFLAG (0)
  642. #define TRIMBLETSIP_LFLAG (ICANON)
  643. #define TRIMBLETSIP_SAMPLES 5
  644. #define TRIMBLETSIP_KEEP 3
  645. #define TRIMBLETAIP_SAMPLES 5
  646. #define TRIMBLETAIP_KEEP 3
  647. #define TRIMBLETAIP_FLAGS (PARSE_F_PPSONSECOND)
  648. #define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS)
  649. #define TRIMBLETAIP_POLL poll_dpoll
  650. #define TRIMBLETSIP_POLL poll_dpoll
  651. #define TRIMBLETAIP_INIT trimbletaip_init
  652. #define TRIMBLETSIP_INIT trimbletsip_init
  653. #define TRIMBLETAIP_EVENT trimbletaip_event
  654. #define TRIMBLETSIP_EVENT trimbletsip_event
  655. #define TRIMBLETSIP_MESSAGE trimbletsip_message
  656. #define TRIMBLETAIP_END 0
  657. #define TRIMBLETSIP_END trimbletsip_end
  658. #define TRIMBLETAIP_DATA ((void *)(&trimbletaip_pollinfo))
  659. #define TRIMBLETSIP_DATA ((void *)(&trimbletsip_pollinfo))
  660. #define TRIMBLETAIP_ID GPS_ID
  661. #define TRIMBLETSIP_ID GPS_ID
  662. #define TRIMBLETAIP_FORMAT "Trimble TAIP"
  663. #define TRIMBLETSIP_FORMAT "Trimble TSIP"
  664. #define TRIMBLETAIP_ROOTDELAY 0x0
  665. #define TRIMBLETSIP_ROOTDELAY 0x0
  666. #define TRIMBLETAIP_BASEDELAY 0.0
  667. #define TRIMBLETSIP_BASEDELAY 0.020 /* GPS time message latency */
  668. #define TRIMBLETAIP_DESCRIPTION "Trimble GPS (TAIP) receiver"
  669. #define TRIMBLETSIP_DESCRIPTION "Trimble GPS (TSIP) receiver"
  670. #define TRIMBLETAIP_MAXUNSYNC 0
  671. #define TRIMBLETSIP_MAXUNSYNC 0
  672. #define TRIMBLETAIP_EOL '<'
  673. /*
  674. * RadioCode Clocks RCC 800 receiver
  675. */
  676. #define RCC_POLLRATE 0 /* only true direct polling */
  677. #define RCC_POLLCMD "\r"
  678. #define RCC_CMDSIZE 1
  679. static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE };
  680. #define RCC8000_FLAGS 0
  681. #define RCC8000_POLL poll_dpoll
  682. #define RCC8000_INIT poll_init
  683. #define RCC8000_END 0
  684. #define RCC8000_DATA ((void *)(&rcc8000_pollinfo))
  685. #define RCC8000_ROOTDELAY 0.0
  686. #define RCC8000_BASEDELAY 0.0
  687. #define RCC8000_ID "MSF"
  688. #define RCC8000_DESCRIPTION "RCC 8000 MSF Receiver"
  689. #define RCC8000_FORMAT "Radiocode RCC8000"
  690. #define RCC8000_MAXUNSYNC (60*60) /* should be ok for an hour */
  691. #define RCC8000_SPEED (B2400)
  692. #define RCC8000_CFLAG (CS8|CREAD|CLOCAL)
  693. #define RCC8000_IFLAG (IGNBRK|IGNPAR)
  694. #define RCC8000_OFLAG 0
  695. #define RCC8000_LFLAG 0
  696. #define RCC8000_SAMPLES 5
  697. #define RCC8000_KEEP 3
  698. /*
  699. * Hopf Radio clock 6021 Format
  700. *
  701. */
  702. #define HOPF6021_ROOTDELAY 0.0
  703. #define HOPF6021_BASEDELAY 0.0
  704. #define HOPF6021_DESCRIPTION "HOPF 6021"
  705. #define HOPF6021_FORMAT "hopf Funkuhr 6021"
  706. #define HOPF6021_MAXUNSYNC (60*60) /* should be ok for an hour */
  707. #define HOPF6021_SPEED (B9600)
  708. #define HOPF6021_CFLAG (CS8|CREAD|CLOCAL)
  709. #define HOPF6021_IFLAG (IGNBRK|ISTRIP)
  710. #define HOPF6021_OFLAG 0
  711. #define HOPF6021_LFLAG 0
  712. #define HOPF6021_FLAGS 0
  713. #define HOPF6021_SAMPLES 5
  714. #define HOPF6021_KEEP 3
  715. /*
  716. * Diem's Computime Radio Clock Receiver
  717. */
  718. #define COMPUTIME_FLAGS 0
  719. #define COMPUTIME_ROOTDELAY 0.0
  720. #define COMPUTIME_BASEDELAY 0.0
  721. #define COMPUTIME_ID DCF_ID
  722. #define COMPUTIME_DESCRIPTION "Diem's Computime receiver"
  723. #define COMPUTIME_FORMAT "Diem's Computime Radio Clock"
  724. #define COMPUTIME_TYPE DCF_TYPE
  725. #define COMPUTIME_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
  726. #define COMPUTIME_SPEED (B9600)
  727. #define COMPUTIME_CFLAG (CSTOPB|CS7|CREAD|CLOCAL)
  728. #define COMPUTIME_IFLAG (IGNBRK|IGNPAR|ISTRIP)
  729. #define COMPUTIME_OFLAG 0
  730. #define COMPUTIME_LFLAG 0
  731. #define COMPUTIME_SAMPLES 5
  732. #define COMPUTIME_KEEP 3
  733. /*
  734. * Varitext Radio Clock Receiver
  735. */
  736. #define VARITEXT_FLAGS 0
  737. #define VARITEXT_ROOTDELAY 0.0
  738. #define VARITEXT_BASEDELAY 0.0
  739. #define VARITEXT_ID "MSF"
  740. #define VARITEXT_DESCRIPTION "Varitext receiver"
  741. #define VARITEXT_FORMAT "Varitext Radio Clock"
  742. #define VARITEXT_TYPE DCF_TYPE
  743. #define VARITEXT_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
  744. #define VARITEXT_SPEED (B9600)
  745. #define VARITEXT_CFLAG (CS7|CREAD|CLOCAL|PARENB|PARODD)
  746. #define VARITEXT_IFLAG (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/
  747. #define VARITEXT_OFLAG 0
  748. #define VARITEXT_LFLAG 0
  749. #define VARITEXT_SAMPLES 32
  750. #define VARITEXT_KEEP 20
  751. static struct parse_clockinfo
  752. {
  753. u_long cl_flags; /* operation flags (io modes) */
  754. void (*cl_poll) P((struct parseunit *)); /* active poll routine */
  755. int (*cl_init) P((struct parseunit *)); /* active poll init routine */
  756. void (*cl_event) P((struct parseunit *, int)); /* special event handling (e.g. reset clock) */
  757. void (*cl_end) P((struct parseunit *)); /* active poll end routine */
  758. void (*cl_message) P((struct parseunit *, parsetime_t *)); /* process a lower layer message */
  759. void *cl_data; /* local data area for "poll" mechanism */
  760. double cl_rootdelay; /* rootdelay */
  761. double cl_basedelay; /* current offset by which the RS232
  762. time code is delayed from the actual time */
  763. const char *cl_id; /* ID code */
  764. const char *cl_description; /* device name */
  765. const char *cl_format; /* fixed format */
  766. u_char cl_type; /* clock type (ntp control) */
  767. u_long cl_maxunsync; /* time to trust oscillator after losing synch */
  768. u_long cl_speed; /* terminal input & output baudrate */
  769. u_long cl_cflag; /* terminal control flags */
  770. u_long cl_iflag; /* terminal input flags */
  771. u_long cl_oflag; /* terminal output flags */
  772. u_long cl_lflag; /* terminal local flags */
  773. u_long cl_samples; /* samples for median filter */
  774. u_long cl_keep; /* samples for median filter to keep */
  775. } parse_clockinfo[] =
  776. {
  777. { /* mode 0 */
  778. MBG_FLAGS,
  779. NO_POLL,
  780. NO_INIT,
  781. NO_EVENT,
  782. NO_END,
  783. NO_MESSAGE,
  784. NO_LCLDATA,
  785. DCFPZF535_ROOTDELAY,
  786. DCFPZF535_BASEDELAY,
  787. DCF_P_ID,
  788. DCFPZF535_DESCRIPTION,
  789. DCFPZF535_FORMAT,
  790. DCF_TYPE,
  791. DCFPZF535_MAXUNSYNC,
  792. DCFPZF535_SPEED,
  793. DCFPZF535_CFLAG,
  794. DCFPZF535_IFLAG,
  795. DCFPZF535_OFLAG,
  796. DCFPZF535_LFLAG,
  797. DCFPZF535_SAMPLES,
  798. DCFPZF535_KEEP
  799. },
  800. { /* mode 1 */
  801. MBG_FLAGS,
  802. NO_POLL,
  803. NO_INIT,
  804. NO_EVENT,
  805. NO_END,
  806. NO_MESSAGE,
  807. NO_LCLDATA,
  808. DCFPZF535OCXO_ROOTDELAY,
  809. DCFPZF535OCXO_BASEDELAY,
  810. DCF_P_ID,
  811. DCFPZF535OCXO_DESCRIPTION,
  812. DCFPZF535OCXO_FORMAT,
  813. DCF_TYPE,
  814. DCFPZF535OCXO_MAXUNSYNC,
  815. DCFPZF535OCXO_SPEED,
  816. DCFPZF535OCXO_CFLAG,
  817. DCFPZF535OCXO_IFLAG,
  818. DCFPZF535OCXO_OFLAG,
  819. DCFPZF535OCXO_LFLAG,
  820. DCFPZF535OCXO_SAMPLES,
  821. DCFPZF535OCXO_KEEP
  822. },
  823. { /* mode 2 */
  824. MBG_FLAGS,
  825. NO_POLL,
  826. NO_INIT,
  827. NO_EVENT,
  828. NO_END,
  829. NO_MESSAGE,
  830. NO_LCLDATA,
  831. DCFUA31_ROOTDELAY,
  832. DCFUA31_BASEDELAY,
  833. DCF_A_ID,
  834. DCFUA31_DESCRIPTION,
  835. DCFUA31_FORMAT,
  836. DCF_TYPE,
  837. DCFUA31_MAXUNSYNC,
  838. DCFUA31_SPEED,
  839. DCFUA31_CFLAG,
  840. DCFUA31_IFLAG,
  841. DCFUA31_OFLAG,
  842. DCFUA31_LFLAG,
  843. DCFUA31_SAMPLES,
  844. DCFUA31_KEEP
  845. },
  846. { /* mode 3 */
  847. MBG_FLAGS,
  848. NO_POLL,
  849. NO_INIT,
  850. NO_EVENT,
  851. NO_END,
  852. NO_MESSAGE,
  853. NO_LCLDATA,
  854. DCF7000_ROOTDELAY,
  855. DCF7000_BASEDELAY,
  856. DCF_A_ID,
  857. DCF7000_DESCRIPTION,
  858. DCF7000_FORMAT,
  859. DCF_TYPE,
  860. DCF7000_MAXUNSYNC,
  861. DCF7000_SPEED,
  862. DCF7000_CFLAG,
  863. DCF7000_IFLAG,
  864. DCF7000_OFLAG,
  865. DCF7000_LFLAG,
  866. DCF7000_SAMPLES,
  867. DCF7000_KEEP
  868. },
  869. { /* mode 4 */
  870. NO_CL_FLAGS,
  871. WSDCF_POLL,
  872. WSDCF_INIT,
  873. NO_EVENT,
  874. WSDCF_END,
  875. NO_MESSAGE,
  876. WSDCF_DATA,
  877. WSDCF_ROOTDELAY,
  878. WSDCF_BASEDELAY,
  879. DCF_A_ID,
  880. WSDCF_DESCRIPTION,
  881. WSDCF_FORMAT,
  882. DCF_TYPE,
  883. WSDCF_MAXUNSYNC,
  884. WSDCF_SPEED,
  885. WSDCF_CFLAG,
  886. WSDCF_IFLAG,
  887. WSDCF_OFLAG,
  888. WSDCF_LFLAG,
  889. WSDCF_SAMPLES,
  890. WSDCF_KEEP
  891. },
  892. { /* mode 5 */
  893. RAWDCF_FLAGS,
  894. NO_POLL,
  895. RAWDCF_INIT,
  896. NO_EVENT,
  897. NO_END,
  898. NO_MESSAGE,
  899. NO_LCLDATA,
  900. RAWDCF_ROOTDELAY,
  901. CONRAD_BASEDELAY,
  902. DCF_A_ID,
  903. CONRAD_DESCRIPTION,
  904. RAWDCF_FORMAT,
  905. DCF_TYPE,
  906. RAWDCF_MAXUNSYNC,
  907. RAWDCF_SPEED,
  908. RAWDCF_CFLAG,
  909. RAWDCF_IFLAG,
  910. RAWDCF_OFLAG,
  911. RAWDCF_LFLAG,
  912. RAWDCF_SAMPLES,
  913. RAWDCF_KEEP
  914. },
  915. { /* mode 6 */
  916. RAWDCF_FLAGS,
  917. NO_POLL,
  918. RAWDCF_INIT,
  919. NO_EVENT,
  920. NO_END,
  921. NO_MESSAGE,
  922. NO_LCLDATA,
  923. RAWDCF_ROOTDELAY,
  924. TIMEBRICK_BASEDELAY,
  925. DCF_A_ID,
  926. TIMEBRICK_DESCRIPTION,
  927. RAWDCF_FORMAT,
  928. DCF_TYPE,
  929. RAWDCF_MAXUNSYNC,
  930. RAWDCF_SPEED,
  931. RAWDCF_CFLAG,
  932. RAWDCF_IFLAG,
  933. RAWDCF_OFLAG,
  934. RAWDCF_LFLAG,
  935. RAWDCF_SAMPLES,
  936. RAWDCF_KEEP
  937. },
  938. { /* mode 7 */
  939. MBG_FLAGS,
  940. GPS16X_POLL,
  941. GPS16X_INIT,
  942. NO_EVENT,
  943. GPS16X_END,
  944. GPS16X_MESSAGE,
  945. GPS16X_DATA,
  946. GPS16X_ROOTDELAY,
  947. GPS16X_BASEDELAY,
  948. GPS16X_ID,
  949. GPS16X_DESCRIPTION,
  950. GPS16X_FORMAT,
  951. GPS_TYPE,
  952. GPS16X_MAXUNSYNC,
  953. GPS16X_SPEED,
  954. GPS16X_CFLAG,
  955. GPS16X_IFLAG,
  956. GPS16X_OFLAG,
  957. GPS16X_LFLAG,
  958. GPS16X_SAMPLES,
  959. GPS16X_KEEP
  960. },
  961. { /* mode 8 */
  962. RAWDCF_FLAGS,
  963. NO_POLL,
  964. NO_INIT,
  965. NO_EVENT,
  966. NO_END,
  967. NO_MESSAGE,
  968. NO_LCLDATA,
  969. RAWDCF_ROOTDELAY,
  970. IGELCLOCK_BASEDELAY,
  971. DCF_A_ID,
  972. IGELCLOCK_DESCRIPTION,
  973. RAWDCF_FORMAT,
  974. DCF_TYPE,
  975. RAWDCF_MAXUNSYNC,
  976. IGELCLOCK_SPEED,
  977. IGELCLOCK_CFLAG,
  978. RAWDCF_IFLAG,
  979. RAWDCF_OFLAG,
  980. RAWDCF_LFLAG,
  981. RAWDCF_SAMPLES,
  982. RAWDCF_KEEP
  983. },
  984. { /* mode 9 */
  985. TRIMBLETAIP_FLAGS,
  986. #if TRIM_POLLRATE /* DHD940515: Allow user config */
  987. NO_POLL,
  988. #else
  989. TRIMBLETAIP_POLL,
  990. #endif
  991. TRIMBLETAIP_INIT,
  992. TRIMBLETAIP_EVENT,
  993. TRIMBLETAIP_END,
  994. NO_MESSAGE,
  995. TRIMBLETAIP_DATA,
  996. TRIMBLETAIP_ROOTDELAY,
  997. TRIMBLETAIP_BASEDELAY,
  998. TRIMBLETAIP_ID,
  999. TRIMBLETAIP_DESCRIPTION,
  1000. TRIMBLETAIP_FORMAT,
  1001. GPS_TYPE,
  1002. TRIMBLETAIP_MAXUNSYNC,
  1003. TRIMBLETAIP_SPEED,
  1004. TRIMBLETAIP_CFLAG,
  1005. TRIMBLETAIP_IFLAG,
  1006. TRIMBLETAIP_OFLAG,
  1007. TRIMBLETAIP_LFLAG,
  1008. TRIMBLETAIP_SAMPLES,
  1009. TRIMBLETAIP_KEEP
  1010. },
  1011. { /* mode 10 */
  1012. TRIMBLETSIP_FLAGS,
  1013. #if TRIM_POLLRATE /* DHD940515: Allow user config */
  1014. NO_POLL,
  1015. #else
  1016. TRIMBLETSIP_POLL,
  1017. #endif
  1018. TRIMBLETSIP_INIT,
  1019. TRIMBLETSIP_EVENT,
  1020. TRIMBLETSIP_END,
  1021. TRIMBLETSIP_MESSAGE,
  1022. TRIMBLETSIP_DATA,
  1023. TRIMBLETSIP_ROOTDELAY,
  1024. TRIMBLETSIP_BASEDELAY,
  1025. TRIMBLETSIP_ID,
  1026. TRIMBLETSIP_DESCRIPTION,
  1027. TRIMBLETSIP_FORMAT,
  1028. GPS_TYPE,
  1029. TRIMBLETSIP_MAXUNSYNC,
  1030. TRIMBLETSIP_SPEED,
  1031. TRIMBLETSIP_CFLAG,
  1032. TRIMBLETSIP_IFLAG,
  1033. TRIMBLETSIP_OFLAG,
  1034. TRIMBLETSIP_LFLAG,
  1035. TRIMBLETSIP_SAMPLES,
  1036. TRIMBLETSIP_KEEP
  1037. },
  1038. { /* mode 11 */
  1039. NO_CL_FLAGS,
  1040. RCC8000_POLL,
  1041. RCC8000_INIT,
  1042. NO_EVENT,
  1043. RCC8000_END,
  1044. NO_MESSAGE,
  1045. RCC8000_DATA,
  1046. RCC8000_ROOTDELAY,
  1047. RCC8000_BASEDELAY,
  1048. RCC8000_ID,
  1049. RCC8000_DESCRIPTION,
  1050. RCC8000_FORMAT,
  1051. DCF_TYPE,
  1052. RCC8000_MAXUNSYNC,
  1053. RCC8000_SPEED,
  1054. RCC8000_CFLAG,
  1055. RCC8000_IFLAG,
  1056. RCC8000_OFLAG,
  1057. RCC8000_LFLAG,
  1058. RCC8000_SAMPLES,
  1059. RCC8000_KEEP
  1060. },
  1061. { /* mode 12 */
  1062. HOPF6021_FLAGS,
  1063. NO_POLL,
  1064. NO_INIT,
  1065. NO_EVENT,
  1066. NO_END,
  1067. NO_MESSAGE,
  1068. NO_LCLDATA,
  1069. HOPF6021_ROOTDELAY,
  1070. HOPF6021_BASEDELAY,
  1071. DCF_ID,
  1072. HOPF6021_DESCRIPTION,
  1073. HOPF6021_FORMAT,
  1074. DCF_TYPE,
  1075. HOPF6021_MAXUNSYNC,
  1076. HOPF6021_SPEED,
  1077. HOPF6021_CFLAG,
  1078. HOPF6021_IFLAG,
  1079. HOPF6021_OFLAG,
  1080. HOPF6021_LFLAG,
  1081. HOPF6021_SAMPLES,
  1082. HOPF6021_KEEP
  1083. },
  1084. { /* mode 13 */
  1085. COMPUTIME_FLAGS,
  1086. NO_POLL,
  1087. NO_INIT,
  1088. NO_EVENT,
  1089. NO_END,
  1090. NO_MESSAGE,
  1091. NO_LCLDATA,
  1092. COMPUTIME_ROOTDELAY,
  1093. COMPUTIME_BASEDELAY,
  1094. COMPUTIME_ID,
  1095. COMPUTIME_DESCRIPTION,
  1096. COMPUTIME_FORMAT,
  1097. COMPUTIME_TYPE,
  1098. COMPUTIME_MAXUNSYNC,
  1099. COMPUTIME_SPEED,
  1100. COMPUTIME_CFLAG,
  1101. COMPUTIME_IFLAG,
  1102. COMPUTIME_OFLAG,
  1103. COMPUTIME_LFLAG,
  1104. COMPUTIME_SAMPLES,
  1105. COMPUTIME_KEEP
  1106. },
  1107. { /* mode 14 */
  1108. RAWDCF_FLAGS,
  1109. NO_POLL,
  1110. RAWDCFDTRSET_INIT,
  1111. NO_EVENT,
  1112. NO_END,
  1113. NO_MESSAGE,
  1114. NO_LCLDATA,
  1115. RAWDCF_ROOTDELAY,
  1116. RAWDCF_BASEDELAY,
  1117. DCF_A_ID,
  1118. RAWDCFDTRSET_DESCRIPTION,
  1119. RAWDCF_FORMAT,
  1120. DCF_TYPE,
  1121. RAWDCF_MAXUNSYNC,
  1122. RAWDCF_SPEED,
  1123. RAWDCF_CFLAG,
  1124. RAWDCF_IFLAG,
  1125. RAWDCF_OFLAG,
  1126. RAWDCF_LFLAG,
  1127. RAWDCF_SAMPLES,
  1128. RAWDCF_KEEP
  1129. },
  1130. { /* mode 15 */
  1131. 0, /* operation flags (io modes) */
  1132. NO_POLL, /* active poll routine */
  1133. NO_INIT, /* active poll init routine */
  1134. NO_EVENT, /* special event handling (e.g. reset clock) */
  1135. NO_END, /* active poll end routine */
  1136. NO_MESSAGE, /* process a lower layer message */
  1137. NO_LCLDATA, /* local data area for "poll" mechanism */
  1138. 0, /* rootdelay */
  1139. 11.0 /* bits */ / 9600, /* current offset by which the RS232
  1140. time code is delayed from the actual time */
  1141. DCF_ID, /* ID code */
  1142. "WHARTON 400A Series clock", /* device name */
  1143. "WHARTON 400A Series clock Output Format 1", /* fixed format */
  1144. /* Must match a format-name in a libparse/clk_xxx.c file */
  1145. DCF_TYPE, /* clock type (ntp control) */
  1146. (1*60*60), /* time to trust oscillator after losing synch */
  1147. B9600, /* terminal input & output baudrate */
  1148. (CS8|CREAD|PARENB|CLOCAL|HUPCL),/* terminal control flags */
  1149. 0, /* terminal input flags */
  1150. 0, /* terminal output flags */
  1151. 0, /* terminal local flags */
  1152. 5, /* samples for median filter */
  1153. 3, /* samples for median filter to keep */
  1154. },
  1155. { /* mode 16 - RAWDCF RTS set, DTR clr */
  1156. RAWDCF_FLAGS,
  1157. NO_POLL,
  1158. RAWDCFDTRCLRRTSSET_INIT,
  1159. NO_EVENT,
  1160. NO_END,
  1161. NO_MESSAGE,
  1162. NO_LCLDATA,
  1163. RAWDCF_ROOTDELAY,
  1164. RAWDCF_BASEDELAY,
  1165. DCF_A_ID,
  1166. RAWDCFDTRCLRRTSSET_DESCRIPTION,
  1167. RAWDCF_FORMAT,
  1168. DCF_TYPE,
  1169. RAWDCF_MAXUNSYNC,
  1170. RAWDCF_SPEED,
  1171. RAWDCF_CFLAG,
  1172. RAWDCF_IFLAG,
  1173. RAWDCF_OFLAG,
  1174. RAWDCF_LFLAG,
  1175. RAWDCF_SAMPLES,
  1176. RAWDCF_KEEP
  1177. },
  1178. { /* mode 17 */
  1179. VARITEXT_FLAGS,
  1180. NO_POLL,
  1181. NO_INIT,
  1182. NO_EVENT,
  1183. NO_END,
  1184. NO_MESSAGE,
  1185. NO_LCLDATA,
  1186. VARITEXT_ROOTDELAY,
  1187. VARITEXT_BASEDELAY,
  1188. VARITEXT_ID,
  1189. VARITEXT_DESCRIPTION,
  1190. VARITEXT_FORMAT,
  1191. VARITEXT_TYPE,
  1192. VARITEXT_MAXUNSYNC,
  1193. VARITEXT_SPEED,
  1194. VARITEXT_CFLAG,
  1195. VARITEXT_IFLAG,
  1196. VARITEXT_OFLAG,
  1197. VARITEXT_LFLAG,
  1198. VARITEXT_SAMPLES,
  1199. VARITEXT_KEEP
  1200. },
  1201. { /* mode 18 */
  1202. MBG_FLAGS,
  1203. NO_POLL,
  1204. NO_INIT,
  1205. NO_EVENT,
  1206. GPS16X_END,
  1207. GPS16X_MESSAGE,
  1208. GPS16X_DATA,
  1209. GPS16X_ROOTDELAY,
  1210. GPS16X_BASEDELAY,
  1211. GPS16X_ID,
  1212. GPS16X_DESCRIPTION,
  1213. GPS16X_FORMAT,
  1214. GPS_TYPE,
  1215. GPS16X_MAXUNSYNC,
  1216. GPS16X_SPEED,
  1217. GPS16X_CFLAG,
  1218. GPS16X_IFLAG,
  1219. GPS16X_OFLAG,
  1220. GPS16X_LFLAG,
  1221. GPS16X_SAMPLES,
  1222. GPS16X_KEEP
  1223. },
  1224. { /* mode 19 */
  1225. RAWDCF_FLAGS,
  1226. NO_POLL,
  1227. RAWDCF_INIT,
  1228. NO_EVENT,
  1229. NO_END,
  1230. NO_MESSAGE,
  1231. NO_LCLDATA,
  1232. RAWDCF_ROOTDELAY,
  1233. GUDE_EMC_USB_V20_BASEDELAY,
  1234. DCF_A_ID,
  1235. GUDE_EMC_USB_V20_DESCRIPTION,
  1236. RAWDCF_FORMAT,
  1237. DCF_TYPE,
  1238. RAWDCF_MAXUNSYNC,
  1239. GUDE_EMC_USB_V20_SPEED,
  1240. RAWDCF_CFLAG,
  1241. RAWDCF_IFLAG,
  1242. RAWDCF_OFLAG,
  1243. RAWDCF_LFLAG,
  1244. RAWDCF_SAMPLES,
  1245. RAWDCF_KEEP
  1246. },
  1247. };
  1248. static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
  1249. #define CLK_REALTYPE(x) ((int)(((x)->ttl) & 0x7F))
  1250. #define CLK_TYPE(x) ((CLK_REALTYPE(x) >= ncltypes) ? ~0 : CLK_REALTYPE(x))
  1251. #define CLK_UNIT(x) ((int)REFCLOCKUNIT(&(x)->srcadr))
  1252. #define CLK_PPS(x) (((x)->ttl) & 0x80)
  1253. /*
  1254. * Other constant stuff
  1255. */
  1256. #define PARSEHSREFID 0x7f7f08ff /* 127.127.8.255 refid for hi strata */
  1257. #define PARSESTATISTICS (60*60) /* output state statistics every hour */
  1258. static int notice = 0;
  1259. #define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
  1260. static void parse_event P((struct parseunit *, int));
  1261. static void parse_process P((struct parseunit *, parsetime_t *));
  1262. static void clear_err P((struct parseunit *, u_long));
  1263. static int list_err P((struct parseunit *, u_long));
  1264. static char * l_mktime P((u_long));
  1265. /**===========================================================================
  1266. ** implementation error message regression module
  1267. **/
  1268. static void
  1269. clear_err(
  1270. struct parseunit *parse,
  1271. u_long lstate
  1272. )
  1273. {
  1274. if (lstate == ERR_ALL)
  1275. {
  1276. int i;
  1277. for (i = 0; i < ERR_CNT; i++)
  1278. {
  1279. parse->errors[i].err_stage = err_tbl[i];
  1280. parse->errors[i].err_cnt = 0;
  1281. parse->errors[i].err_last = 0;
  1282. parse->errors[i].err_started = 0;
  1283. parse->errors[i].err_suppressed = 0;
  1284. }
  1285. }
  1286. else
  1287. {
  1288. parse->errors[lstate].err_stage = err_tbl[lstate];
  1289. parse->errors[lstate].err_cnt = 0;
  1290. parse->errors[lstate].err_last = 0;
  1291. parse->errors[lstate].err_started = 0;
  1292. parse->errors[lstate].err_suppressed = 0;
  1293. }
  1294. }
  1295. static int
  1296. list_err(
  1297. struct parseunit *parse,
  1298. u_long lstate
  1299. )
  1300. {
  1301. int do_it;
  1302. struct errorinfo *err = &parse->errors[lstate];
  1303. if (err->err_started == 0)
  1304. {
  1305. err->err_started = current_time;
  1306. }
  1307. do_it = (current_time - err->err_last) >= err->err_stage->err_delay;
  1308. if (do_it)
  1309. err->err_cnt++;
  1310. if (err->err_stage->err_count &&
  1311. (err->err_cnt >= err->err_stage->err_count))
  1312. {
  1313. err->err_stage++;
  1314. err->err_cnt = 0;
  1315. }
  1316. if (!err->err_cnt && do_it)
  1317. msyslog(LOG_INFO, "PARSE receiver #%d: interval for following error message class is at least %s",
  1318. CLK_UNIT(parse->peer), l_mktime(err->err_stage->err_delay));
  1319. if (!do_it)
  1320. err->err_suppressed++;
  1321. else
  1322. err->err_last = current_time;
  1323. if (do_it && err->err_suppressed)
  1324. {
  1325. msyslog(LOG_INFO, "PARSE receiver #%d: %ld message%s suppressed, error condition class persists for %s",
  1326. CLK_UNIT(parse->peer), err->err_suppressed, (err->err_suppressed == 1) ? " was" : "s where",
  1327. l_mktime(current_time - err->err_started));
  1328. err->err_suppressed = 0;
  1329. }
  1330. return do_it;
  1331. }
  1332. /*--------------------------------------------------
  1333. * mkreadable - make a printable ascii string (without
  1334. * embedded quotes so that the ntpq protocol isn't
  1335. * fooled
  1336. */
  1337. #ifndef isprint
  1338. #define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
  1339. #endif
  1340. static char *
  1341. mkreadable(
  1342. char *buffer,
  1343. long blen,
  1344. const char *src,
  1345. u_long srclen,
  1346. int hex
  1347. )
  1348. {
  1349. char *b = buffer;
  1350. char *endb = (char *)0;
  1351. if (blen < 4)
  1352. return (char *)0; /* don't bother with mini buffers */
  1353. endb = buffer + blen - 4;
  1354. blen--; /* account for '\0' */
  1355. while (blen && srclen--)
  1356. {
  1357. if (!hex && /* no binary only */
  1358. (*src != '\\') && /* no plain \ */
  1359. (*src != '"') && /* no " */
  1360. isprint((int)*src)) /* only printables */
  1361. { /* they are easy... */
  1362. *buffer++ = *src++;
  1363. blen--;
  1364. }
  1365. else
  1366. {
  1367. if (blen < 4)
  1368. {
  1369. while (blen--)
  1370. {
  1371. *buffer++ = '.';
  1372. }
  1373. *buffer = '\0';
  1374. return b;
  1375. }
  1376. else
  1377. {
  1378. if (*src == '\\')
  1379. {
  1380. strcpy(buffer,"\\\\");
  1381. buffer += 2;
  1382. blen -= 2;
  1383. src++;
  1384. }
  1385. else
  1386. {
  1387. sprintf(buffer, "\\x%02x", *src++);
  1388. blen -= 4;
  1389. buffer += 4;
  1390. }
  1391. }
  1392. }
  1393. if (srclen && !blen && endb) /* overflow - set last chars to ... */
  1394. strcpy(endb, "...");
  1395. }
  1396. *buffer = '\0';
  1397. return b;
  1398. }
  1399. /*--------------------------------------------------
  1400. * mkascii - make a printable ascii string
  1401. * assumes (unless defined better) 7-bit ASCII
  1402. */
  1403. static char *
  1404. mkascii(
  1405. char *buffer,
  1406. long blen,
  1407. const char *src,
  1408. u_long srclen
  1409. )
  1410. {
  1411. return mkreadable(buffer, blen, src, srclen, 0);
  1412. }
  1413. /**===========================================================================
  1414. ** implementation of i/o handling methods
  1415. ** (all STREAM, partial STREAM, user level)
  1416. **/
  1417. /*
  1418. * define possible io handling methods
  1419. */
  1420. #ifdef STREAM
  1421. static int ppsclock_init P((struct parseunit *));
  1422. static int stream_init P((struct parseunit *));
  1423. static void stream_end P((struct parseunit *));
  1424. static int stream_enable P((struct parseunit *));
  1425. static int stream_disable P((struct parseunit *));
  1426. static int stream_setcs P((struct parseunit *, parsectl_t *));
  1427. static int stream_getfmt P((struct parseunit *, parsectl_t *));
  1428. static int stream_setfmt P((struct parseunit *, parsectl_t *));
  1429. static int stream_timecode P((struct parseunit *, parsectl_t *));
  1430. static void stream_receive P((struct recvbuf *));
  1431. #endif
  1432. static int local_init P((struct parseunit *));
  1433. static void local_end P((struct parseunit *));
  1434. static int local_nop P((struct parseunit *));
  1435. static int local_setcs P((struct parseunit *, parsectl_t *));
  1436. static int local_getfmt P((struct parseunit *, parsectl_t *));
  1437. static int local_setfmt P((struct parseunit *, parsectl_t *));
  1438. static int local_timecode P((struct parseunit *, parsectl_t *));
  1439. static void local_receive P((struct recvbuf *));
  1440. static int local_input P((struct recvbuf *));
  1441. static bind_t io_bindings[] =
  1442. {
  1443. #ifdef STREAM
  1444. {
  1445. "parse STREAM",
  1446. stream_init,
  1447. stream_end,
  1448. stream_setcs,
  1449. stream_disable,
  1450. stream_enable,
  1451. stream_getfmt,
  1452. stream_setfmt,
  1453. stream_timecode,
  1454. stream_receive,
  1455. 0,
  1456. },
  1457. {
  1458. "ppsclock STREAM",
  1459. ppsclock_init,
  1460. local_end,
  1461. local_setcs,
  1462. local_nop,
  1463. local_nop,
  1464. local_getfmt,
  1465. local_setfmt,
  1466. local_timecode,
  1467. local_receive,
  1468. local_input,
  1469. },
  1470. #endif
  1471. {
  1472. "normal",
  1473. local_init,
  1474. local_end,
  1475. local_setcs,
  1476. local_nop,
  1477. local_nop,
  1478. local_getfmt,
  1479. local_setfmt,
  1480. local_timecode,
  1481. local_receive,
  1482. local_input,
  1483. },
  1484. {
  1485. (char *)0,
  1486. }
  1487. };
  1488. #ifdef STREAM
  1489. #define fix_ts(_X_) \
  1490. if ((&(_X_))->tv.tv_usec >= 1000000) \
  1491. { \
  1492. (&(_X_))->tv.tv_usec -= 1000000; \
  1493. (&(_X_))->tv.tv_sec += 1; \
  1494. }
  1495. #define cvt_ts(_X_, _Y_) \
  1496. { \
  1497. l_fp ts; \
  1498. fix_ts((_X_)); \
  1499. if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
  1500. { \
  1501. ERR(ERR_BADDATA) \
  1502. msyslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%ld.%06ld) ", (_Y_), (long)(&(_X_))->tv.tv_sec, (long)(&(_X_))->tv.tv_usec);\
  1503. return; \
  1504. } \
  1505. else \
  1506. { \
  1507. (&(_X_))->fp = ts; \
  1508. } \
  1509. }
  1510. /*--------------------------------------------------
  1511. * ppsclock STREAM init
  1512. */
  1513. static int
  1514. ppsclock_init(
  1515. struct parseunit *parse
  1516. )
  1517. {
  1518. static char m1[] = "ppsclocd";
  1519. static char m2[] = "ppsclock";
  1520. /*
  1521. * now push the parse streams module
  1522. * it will ensure exclusive access to the device
  1523. */
  1524. if (ioctl(parse->ppsfd, I_PUSH, (caddr_t)m1) == -1 &&
  1525. ioctl(parse->ppsfd, I_PUSH, (caddr_t)m2) == -1)
  1526. {
  1527. if (errno != EINVAL)
  1528. {
  1529. msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
  1530. CLK_UNIT(parse->peer));
  1531. }
  1532. return 0;
  1533. }
  1534. if (!local_init(parse))
  1535. {
  1536. (void)ioctl(parse->ppsfd, I_POP, (caddr_t)0);
  1537. return 0;
  1538. }
  1539. parse->flags |= PARSE_PPSCLOCK;
  1540. return 1;
  1541. }
  1542. /*--------------------------------------------------
  1543. * parse STREAM init
  1544. */
  1545. static int
  1546. stream_init(
  1547. struct parseunit *parse
  1548. )
  1549. {
  1550. static char m1[] = "parse";
  1551. /*
  1552. * now push the parse streams module
  1553. * to test whether it is there (neat interface 8-( )
  1554. */
  1555. if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
  1556. {
  1557. if (errno != EINVAL) /* accept non-existence */
  1558. {
  1559. msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
  1560. }
  1561. return 0;
  1562. }
  1563. else
  1564. {
  1565. while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
  1566. /* empty loop */;
  1567. /*
  1568. * now push it a second time after we have removed all
  1569. * module garbage
  1570. */
  1571. if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
  1572. {
  1573. msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
  1574. return 0;
  1575. }
  1576. else
  1577. {
  1578. return 1;
  1579. }
  1580. }
  1581. }
  1582. /*--------------------------------------------------
  1583. * parse STREAM end
  1584. */
  1585. static void
  1586. stream_end(
  1587. struct parseunit *parse
  1588. )
  1589. {
  1590. while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
  1591. /* empty loop */;
  1592. }
  1593. /*-------------------…