PageRenderTime 65ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/ntp/ntpd/refclock_parse.c

https://bitbucket.org/freebsd/freebsd-head/
C | 6045 lines | 5010 code | 328 blank | 707 comment | 147 complexity | a9fc6f6dec53b0ddcd71ea98b160bb1f MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  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. /*--------------------------------------------------
  1594. * STREAM setcs
  1595. */
  1596. static int
  1597. stream_setcs(
  1598. struct parseunit *parse,
  1599. parsectl_t *tcl
  1600. )
  1601. {
  1602. struct strioctl strioc;
  1603. strioc.ic_cmd = PARSEIOC_SETCS;
  1604. strioc.ic_timout = 0;
  1605. strioc.ic_dp = (char *)tcl;
  1606. strioc.ic_len = sizeof (*tcl);
  1607. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1608. {
  1609. msyslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CLK_UNIT(parse->peer));
  1610. return 0;
  1611. }
  1612. return 1;
  1613. }
  1614. /*--------------------------------------------------
  1615. * STREAM enable
  1616. */
  1617. static int
  1618. stream_enable(
  1619. struct parseunit *parse
  1620. )
  1621. {
  1622. struct strioctl strioc;
  1623. strioc.ic_cmd = PARSEIOC_ENABLE;
  1624. strioc.ic_timout = 0;
  1625. strioc.ic_dp = (char *)0;
  1626. strioc.ic_len = 0;
  1627. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1628. {
  1629. msyslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CLK_UNIT(parse->peer));
  1630. return 0;
  1631. }
  1632. parse->generic->io.clock_recv = stream_receive; /* ok - parse input in kernel */
  1633. return 1;
  1634. }
  1635. /*--------------------------------------------------
  1636. * STREAM disable
  1637. */
  1638. static int
  1639. stream_disable(
  1640. struct parseunit *parse
  1641. )
  1642. {
  1643. struct strioctl strioc;
  1644. strioc.ic_cmd = PARSEIOC_DISABLE;
  1645. strioc.ic_timout = 0;
  1646. strioc.ic_dp = (char *)0;
  1647. strioc.ic_len = 0;
  1648. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1649. {
  1650. msyslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CLK_UNIT(parse->peer));
  1651. return 0;
  1652. }
  1653. parse->generic->io.clock_recv = local_receive; /* ok - parse input in daemon */
  1654. return 1;
  1655. }
  1656. /*--------------------------------------------------
  1657. * STREAM getfmt
  1658. */
  1659. static int
  1660. stream_getfmt(
  1661. struct parseunit *parse,
  1662. parsectl_t *tcl
  1663. )
  1664. {
  1665. struct strioctl strioc;
  1666. strioc.ic_cmd = PARSEIOC_GETFMT;
  1667. strioc.ic_timout = 0;
  1668. strioc.ic_dp = (char *)tcl;
  1669. strioc.ic_len = sizeof (*tcl);
  1670. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1671. {
  1672. msyslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CLK_UNIT(parse->peer));
  1673. return 0;
  1674. }
  1675. return 1;
  1676. }
  1677. /*--------------------------------------------------
  1678. * STREAM setfmt
  1679. */
  1680. static int
  1681. stream_setfmt(
  1682. struct parseunit *parse,
  1683. parsectl_t *tcl
  1684. )
  1685. {
  1686. struct strioctl strioc;
  1687. strioc.ic_cmd = PARSEIOC_SETFMT;
  1688. strioc.ic_timout = 0;
  1689. strioc.ic_dp = (char *)tcl;
  1690. strioc.ic_len = sizeof (*tcl);
  1691. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1692. {
  1693. msyslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CLK_UNIT(parse->peer));
  1694. return 0;
  1695. }
  1696. return 1;
  1697. }
  1698. /*--------------------------------------------------
  1699. * STREAM timecode
  1700. */
  1701. static int
  1702. stream_timecode(
  1703. struct parseunit *parse,
  1704. parsectl_t *tcl
  1705. )
  1706. {
  1707. struct strioctl strioc;
  1708. strioc.ic_cmd = PARSEIOC_TIMECODE;
  1709. strioc.ic_timout = 0;
  1710. strioc.ic_dp = (char *)tcl;
  1711. strioc.ic_len = sizeof (*tcl);
  1712. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1713. {
  1714. ERR(ERR_INTERNAL)
  1715. msyslog(LOG_ERR, "PARSE receiver #%d: stream_timecode: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CLK_UNIT(parse->peer));
  1716. return 0;
  1717. }
  1718. clear_err(parse, ERR_INTERNAL);
  1719. return 1;
  1720. }
  1721. /*--------------------------------------------------
  1722. * STREAM receive
  1723. */
  1724. static void
  1725. stream_receive(
  1726. struct recvbuf *rbufp
  1727. )
  1728. {
  1729. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  1730. parsetime_t parsetime;
  1731. if (!parse->peer)
  1732. return;
  1733. if (rbufp->recv_length != sizeof(parsetime_t))
  1734. {
  1735. ERR(ERR_BADIO)
  1736. msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
  1737. CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
  1738. parse_event(parse, CEVNT_BADREPLY);
  1739. return;
  1740. }
  1741. clear_err(parse, ERR_BADIO);
  1742. memmove((caddr_t)&parsetime,
  1743. (caddr_t)rbufp->recv_buffer,
  1744. sizeof(parsetime_t));
  1745. #ifdef DEBUG
  1746. if (debug > 3)
  1747. {
  1748. printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
  1749. CLK_UNIT(parse->peer),
  1750. (unsigned int)parsetime.parse_status,
  1751. (unsigned int)parsetime.parse_state,
  1752. (unsigned long)parsetime.parse_time.tv.tv_sec,
  1753. (unsigned long)parsetime.parse_time.tv.tv_usec,
  1754. (unsigned long)parsetime.parse_stime.tv.tv_sec,
  1755. (unsigned long)parsetime.parse_stime.tv.tv_usec,
  1756. (unsigned long)parsetime.parse_ptime.tv.tv_sec,
  1757. (unsigned long)parsetime.parse_ptime.tv.tv_usec);
  1758. }
  1759. #endif
  1760. /*
  1761. * switch time stamp world - be sure to normalize small usec field
  1762. * errors.
  1763. */
  1764. cvt_ts(parsetime.parse_stime, "parse_stime");
  1765. if (PARSE_TIMECODE(parsetime.parse_state))
  1766. {
  1767. cvt_ts(parsetime.parse_time, "parse_time");
  1768. }
  1769. if (PARSE_PPS(parsetime.parse_state))
  1770. cvt_ts(parsetime.parse_ptime, "parse_ptime");
  1771. parse_process(parse, &parsetime);
  1772. }
  1773. #endif
  1774. /*--------------------------------------------------
  1775. * local init
  1776. */
  1777. static int
  1778. local_init(
  1779. struct parseunit *parse
  1780. )
  1781. {
  1782. return parse_ioinit(&parse->parseio);
  1783. }
  1784. /*--------------------------------------------------
  1785. * local end
  1786. */
  1787. static void
  1788. local_end(
  1789. struct parseunit *parse
  1790. )
  1791. {
  1792. parse_ioend(&parse->parseio);
  1793. }
  1794. /*--------------------------------------------------
  1795. * local nop
  1796. */
  1797. static int
  1798. local_nop(
  1799. struct parseunit *parse
  1800. )
  1801. {
  1802. return 1;
  1803. }
  1804. /*--------------------------------------------------
  1805. * local setcs
  1806. */
  1807. static int
  1808. local_setcs(
  1809. struct parseunit *parse,
  1810. parsectl_t *tcl
  1811. )
  1812. {
  1813. return parse_setcs(tcl, &parse->parseio);
  1814. }
  1815. /*--------------------------------------------------
  1816. * local getfmt
  1817. */
  1818. static int
  1819. local_getfmt(
  1820. struct parseunit *parse,
  1821. parsectl_t *tcl
  1822. )
  1823. {
  1824. return parse_getfmt(tcl, &parse->parseio);
  1825. }
  1826. /*--------------------------------------------------
  1827. * local setfmt
  1828. */
  1829. static int
  1830. local_setfmt(
  1831. struct parseunit *parse,
  1832. parsectl_t *tcl
  1833. )
  1834. {
  1835. return parse_setfmt(tcl, &parse->parseio);
  1836. }
  1837. /*--------------------------------------------------
  1838. * local timecode
  1839. */
  1840. static int
  1841. local_timecode(
  1842. struct parseunit *parse,
  1843. parsectl_t *tcl
  1844. )
  1845. {
  1846. return parse_timecode(tcl, &parse->parseio);
  1847. }
  1848. /*--------------------------------------------------
  1849. * local input
  1850. */
  1851. static int
  1852. local_input(
  1853. struct recvbuf *rbufp
  1854. )
  1855. {
  1856. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  1857. int count;
  1858. unsigned char *s;
  1859. timestamp_t ts;
  1860. if (!parse->peer)
  1861. return 0;
  1862. /*
  1863. * eat all characters, parsing then and feeding complete samples
  1864. */
  1865. count = rbufp->recv_length;
  1866. s = (unsigned char *)rbufp->recv_buffer;
  1867. ts.fp = rbufp->recv_time;
  1868. while (count--)
  1869. {
  1870. if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
  1871. {
  1872. struct recvbuf *buf;
  1873. /*
  1874. * got something good to eat
  1875. */
  1876. if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
  1877. {
  1878. #ifdef HAVE_PPSAPI
  1879. if (parse->flags & PARSE_PPSCLOCK)
  1880. {
  1881. struct timespec pps_timeout;
  1882. pps_info_t pps_info;
  1883. pps_timeout.tv_sec = 0;
  1884. pps_timeout.tv_nsec = 0;
  1885. if (time_pps_fetch(parse->ppshandle, PPS_TSFMT_TSPEC, &pps_info,
  1886. &pps_timeout) == 0)
  1887. {
  1888. if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
  1889. {
  1890. double dtemp;
  1891. struct timespec pts;
  1892. /*
  1893. * add PPS time stamp if available via ppsclock module
  1894. * and not supplied already.
  1895. */
  1896. if (parse->flags & PARSE_CLEAR)
  1897. pts = pps_info.clear_timestamp;
  1898. else
  1899. pts = pps_info.assert_timestamp;
  1900. parse->parseio.parse_dtime.parse_ptime.fp.l_ui = pts.tv_sec + JAN_1970;
  1901. dtemp = pts.tv_nsec / 1e9;
  1902. if (dtemp < 0.) {
  1903. dtemp += 1;
  1904. parse->parseio.parse_dtime.parse_ptime.fp.l_ui--;
  1905. }
  1906. if (dtemp > 1.) {
  1907. dtemp -= 1;
  1908. parse->parseio.parse_dtime.parse_ptime.fp.l_ui++;
  1909. }
  1910. parse->parseio.parse_dtime.parse_ptime.fp.l_uf = dtemp * FRAC;
  1911. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  1912. #ifdef DEBUG
  1913. if (debug > 3)
  1914. {
  1915. printf(
  1916. "parse: local_receive: fd %d PPSAPI seq %ld - PPS %s\n",
  1917. rbufp->fd,
  1918. (long)pps_info.assert_sequence + (long)pps_info.clear_sequence,
  1919. lfptoa(&parse->parseio.parse_dtime.parse_ptime.fp, 6));
  1920. }
  1921. #endif
  1922. }
  1923. #ifdef DEBUG
  1924. else
  1925. {
  1926. if (debug > 3)
  1927. {
  1928. printf(
  1929. "parse: local_receive: fd %d PPSAPI seq assert %ld, seq clear %ld - NO PPS event\n",
  1930. rbufp->fd,
  1931. (long)pps_info.assert_sequence, (long)pps_info.clear_sequence);
  1932. }
  1933. }
  1934. #endif
  1935. parse->ppsserial = pps_info.assert_sequence + pps_info.clear_sequence;
  1936. }
  1937. #ifdef DEBUG
  1938. else
  1939. {
  1940. if (debug > 3)
  1941. {
  1942. printf(
  1943. "parse: local_receive: fd %d PPSAPI time_pps_fetch errno = %d\n",
  1944. rbufp->fd,
  1945. errno);
  1946. }
  1947. }
  1948. #endif
  1949. }
  1950. #else
  1951. #ifdef TIOCDCDTIMESTAMP
  1952. struct timeval dcd_time;
  1953. if (ioctl(parse->ppsfd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
  1954. {
  1955. l_fp tstmp;
  1956. TVTOTS(&dcd_time, &tstmp);
  1957. tstmp.l_ui += JAN_1970;
  1958. L_SUB(&ts.fp, &tstmp);
  1959. if (ts.fp.l_ui == 0)
  1960. {
  1961. #ifdef DEBUG
  1962. if (debug)
  1963. {
  1964. printf(
  1965. "parse: local_receive: fd %d DCDTIMESTAMP %s\n",
  1966. parse->ppsfd,
  1967. lfptoa(&tstmp, 6));
  1968. printf(" sigio %s\n",
  1969. lfptoa(&ts.fp, 6));
  1970. }
  1971. #endif
  1972. parse->parseio.parse_dtime.parse_ptime.fp = tstmp;
  1973. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  1974. }
  1975. }
  1976. #else /* TIOCDCDTIMESTAMP */
  1977. #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
  1978. if (parse->flags & PARSE_PPSCLOCK)
  1979. {
  1980. l_fp tts;
  1981. struct ppsclockev ev;
  1982. #ifdef HAVE_CIOGETEV
  1983. if (ioctl(parse->ppsfd, CIOGETEV, (caddr_t)&ev) == 0)
  1984. #endif
  1985. #ifdef HAVE_TIOCGPPSEV
  1986. if (ioctl(parse->ppsfd, TIOCGPPSEV, (caddr_t)&ev) == 0)
  1987. #endif
  1988. {
  1989. if (ev.serial != parse->ppsserial)
  1990. {
  1991. /*
  1992. * add PPS time stamp if available via ppsclock module
  1993. * and not supplied already.
  1994. */
  1995. if (!buftvtots((const char *)&ev.tv, &tts))
  1996. {
  1997. ERR(ERR_BADDATA)
  1998. msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
  1999. }
  2000. else
  2001. {
  2002. parse->parseio.parse_dtime.parse_ptime.fp = tts;
  2003. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  2004. }
  2005. }
  2006. parse->ppsserial = ev.serial;
  2007. }
  2008. }
  2009. #endif
  2010. #endif /* TIOCDCDTIMESTAMP */
  2011. #endif /* !HAVE_PPSAPI */
  2012. }
  2013. if (count)
  2014. { /* simulate receive */
  2015. buf = get_free_recv_buffer();
  2016. if (buf != NULL) {
  2017. memmove((caddr_t)buf->recv_buffer,
  2018. (caddr_t)&parse->parseio.parse_dtime,
  2019. sizeof(parsetime_t));
  2020. buf->recv_length = sizeof(parsetime_t);
  2021. buf->recv_time = rbufp->recv_time;
  2022. buf->srcadr = rbufp->srcadr;
  2023. buf->dstadr = rbufp->dstadr;
  2024. buf->receiver = rbufp->receiver;
  2025. buf->fd = rbufp->fd;
  2026. buf->X_from_where = rbufp->X_from_where;
  2027. add_full_recv_buffer(buf);
  2028. }
  2029. parse_iodone(&parse->parseio);
  2030. }
  2031. else
  2032. {
  2033. memmove((caddr_t)rbufp->recv_buffer,
  2034. (caddr_t)&parse->parseio.parse_dtime,
  2035. sizeof(parsetime_t));
  2036. parse_iodone(&parse->parseio);
  2037. rbufp->recv_length = sizeof(parsetime_t);
  2038. return 1; /* got something & in place return */
  2039. }
  2040. }
  2041. }
  2042. return 0; /* nothing to pass up */
  2043. }
  2044. /*--------------------------------------------------
  2045. * local receive
  2046. */
  2047. static void
  2048. local_receive(
  2049. struct recvbuf *rbufp
  2050. )
  2051. {
  2052. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  2053. parsetime_t parsetime;
  2054. if (!parse->peer)
  2055. return;
  2056. if (rbufp->recv_length != sizeof(parsetime_t))
  2057. {
  2058. ERR(ERR_BADIO)
  2059. msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
  2060. CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
  2061. parse_event(parse, CEVNT_BADREPLY);
  2062. return;
  2063. }
  2064. clear_err(parse, ERR_BADIO);
  2065. memmove((caddr_t)&parsetime,
  2066. (caddr_t)rbufp->recv_buffer,
  2067. sizeof(parsetime_t));
  2068. #ifdef DEBUG
  2069. if (debug > 3)
  2070. {
  2071. printf("PARSE receiver #%d: status %06x, state %08x, time(fp) %lx.%08lx, stime(fp) %lx.%08lx, ptime(fp) %lx.%08lx\n",
  2072. CLK_UNIT(parse->peer),
  2073. (unsigned int)parsetime.parse_status,
  2074. (unsigned int)parsetime.parse_state,
  2075. (unsigned long)parsetime.parse_time.fp.l_ui,
  2076. (unsigned long)parsetime.parse_time.fp.l_uf,
  2077. (unsigned long)parsetime.parse_stime.fp.l_ui,
  2078. (unsigned long)parsetime.parse_stime.fp.l_uf,
  2079. (unsigned long)parsetime.parse_ptime.fp.l_ui,
  2080. (unsigned long)parsetime.parse_ptime.fp.l_uf);
  2081. }
  2082. #endif
  2083. parse_process(parse, &parsetime);
  2084. }
  2085. /*--------------------------------------------------
  2086. * init_iobinding - find and initialize lower layers
  2087. */
  2088. static bind_t *
  2089. init_iobinding(
  2090. struct parseunit *parse
  2091. )
  2092. {
  2093. bind_t *b = io_bindings;
  2094. while (b->bd_description != (char *)0)
  2095. {
  2096. if ((*b->bd_init)(parse))
  2097. {
  2098. return b;
  2099. }
  2100. b++;
  2101. }
  2102. return (bind_t *)0;
  2103. }
  2104. /**===========================================================================
  2105. ** support routines
  2106. **/
  2107. /*--------------------------------------------------
  2108. * convert a flag field to a string
  2109. */
  2110. static char *
  2111. parsestate(
  2112. u_long lstate,
  2113. char *buffer,
  2114. int size
  2115. )
  2116. {
  2117. static struct bits
  2118. {
  2119. u_long bit;
  2120. const char *name;
  2121. } flagstrings[] =
  2122. {
  2123. { PARSEB_ANNOUNCE, "DST SWITCH WARNING" },
  2124. { PARSEB_POWERUP, "NOT SYNCHRONIZED" },
  2125. { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
  2126. { PARSEB_DST, "DST" },
  2127. { PARSEB_UTC, "UTC DISPLAY" },
  2128. { PARSEB_LEAPADD, "LEAP ADD WARNING" },
  2129. { PARSEB_LEAPDEL, "LEAP DELETE WARNING" },
  2130. { PARSEB_LEAPSECOND, "LEAP SECOND" },
  2131. { PARSEB_ALTERNATE, "ALTERNATE ANTENNA" },
  2132. { PARSEB_TIMECODE, "TIME CODE" },
  2133. { PARSEB_PPS, "PPS" },
  2134. { PARSEB_POSITION, "POSITION" },
  2135. { 0 }
  2136. };
  2137. static struct sbits
  2138. {
  2139. u_long bit;
  2140. const char *name;
  2141. } sflagstrings[] =
  2142. {
  2143. { PARSEB_S_LEAP, "LEAP INDICATION" },
  2144. { PARSEB_S_PPS, "PPS SIGNAL" },
  2145. { PARSEB_S_ANTENNA, "ANTENNA" },
  2146. { PARSEB_S_POSITION, "POSITION" },
  2147. { 0 }
  2148. };
  2149. int i;
  2150. char *s, *t;
  2151. *buffer = '\0';
  2152. s = t = buffer;
  2153. i = 0;
  2154. while (flagstrings[i].bit)
  2155. {
  2156. if (flagstrings[i].bit & lstate)
  2157. {
  2158. if (s != t)
  2159. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2160. strncat(t, flagstrings[i].name, BUFFER_SIZES(buffer, t, size));
  2161. t += strlen(t);
  2162. }
  2163. i++;
  2164. }
  2165. if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
  2166. {
  2167. if (s != t)
  2168. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2169. t += strlen(t);
  2170. strncpy(t, "(", BUFFER_SIZES(buffer, t, size));
  2171. s = t = t + strlen(t);
  2172. i = 0;
  2173. while (sflagstrings[i].bit)
  2174. {
  2175. if (sflagstrings[i].bit & lstate)
  2176. {
  2177. if (t != s)
  2178. {
  2179. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2180. t += 2;
  2181. }
  2182. strncpy(t, sflagstrings[i].name, BUFFER_SIZES(buffer, t, size));
  2183. t += strlen(t);
  2184. }
  2185. i++;
  2186. }
  2187. strncpy(t, ")", BUFFER_SIZES(buffer, t, size));
  2188. }
  2189. return buffer;
  2190. }
  2191. /*--------------------------------------------------
  2192. * convert a status flag field to a string
  2193. */
  2194. static char *
  2195. parsestatus(
  2196. u_long lstate,
  2197. char *buffer,
  2198. int size
  2199. )
  2200. {
  2201. static struct bits
  2202. {
  2203. u_long bit;
  2204. const char *name;
  2205. } flagstrings[] =
  2206. {
  2207. { CVT_OK, "CONVERSION SUCCESSFUL" },
  2208. { CVT_NONE, "NO CONVERSION" },
  2209. { CVT_FAIL, "CONVERSION FAILED" },
  2210. { CVT_BADFMT, "ILLEGAL FORMAT" },
  2211. { CVT_BADDATE, "DATE ILLEGAL" },
  2212. { CVT_BADTIME, "TIME ILLEGAL" },
  2213. { CVT_ADDITIONAL, "ADDITIONAL DATA" },
  2214. { 0 }
  2215. };
  2216. int i;
  2217. *buffer = '\0';
  2218. i = 0;
  2219. while (flagstrings[i].bit)
  2220. {
  2221. if (flagstrings[i].bit & lstate)
  2222. {
  2223. if (buffer[0])
  2224. strncat(buffer, "; ", size);
  2225. strncat(buffer, flagstrings[i].name, size);
  2226. }
  2227. i++;
  2228. }
  2229. return buffer;
  2230. }
  2231. /*--------------------------------------------------
  2232. * convert a clock status flag field to a string
  2233. */
  2234. static const char *
  2235. clockstatus(
  2236. u_long lstate
  2237. )
  2238. {
  2239. static char buffer[20];
  2240. static struct status
  2241. {
  2242. u_long value;
  2243. const char *name;
  2244. } flagstrings[] =
  2245. {
  2246. { CEVNT_NOMINAL, "NOMINAL" },
  2247. { CEVNT_TIMEOUT, "NO RESPONSE" },
  2248. { CEVNT_BADREPLY,"BAD FORMAT" },
  2249. { CEVNT_FAULT, "FAULT" },
  2250. { CEVNT_PROP, "PROPAGATION DELAY" },
  2251. { CEVNT_BADDATE, "ILLEGAL DATE" },
  2252. { CEVNT_BADTIME, "ILLEGAL TIME" },
  2253. { (unsigned)~0L }
  2254. };
  2255. int i;
  2256. i = 0;
  2257. while (flagstrings[i].value != ~0)
  2258. {
  2259. if (flagstrings[i].value == lstate)
  2260. {
  2261. return flagstrings[i].name;
  2262. }
  2263. i++;
  2264. }
  2265. snprintf(buffer, sizeof(buffer), "unknown #%ld", (u_long)lstate);
  2266. return buffer;
  2267. }
  2268. /*--------------------------------------------------
  2269. * l_mktime - make representation of a relative time
  2270. */
  2271. static char *
  2272. l_mktime(
  2273. u_long delta
  2274. )
  2275. {
  2276. u_long tmp, m, s;
  2277. static char buffer[40];
  2278. char *t;
  2279. buffer[0] = '\0';
  2280. if ((tmp = delta / (60*60*24)) != 0)
  2281. {
  2282. snprintf(buffer, BUFFER_SIZE(buffer, buffer), "%ldd+", (u_long)tmp);
  2283. delta -= tmp * 60*60*24;
  2284. }
  2285. s = delta % 60;
  2286. delta /= 60;
  2287. m = delta % 60;
  2288. delta /= 60;
  2289. t = buffer + strlen(buffer);
  2290. snprintf(t, BUFFER_SIZE(buffer, t), "%02d:%02d:%02d",
  2291. (int)delta, (int)m, (int)s);
  2292. return buffer;
  2293. }
  2294. /*--------------------------------------------------
  2295. * parse_statistics - list summary of clock states
  2296. */
  2297. static void
  2298. parse_statistics(
  2299. struct parseunit *parse
  2300. )
  2301. {
  2302. int i;
  2303. NLOG(NLOG_CLOCKSTATIST) /* conditional if clause for conditional syslog */
  2304. {
  2305. msyslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
  2306. CLK_UNIT(parse->peer),
  2307. l_mktime(current_time - parse->generic->timestarted));
  2308. msyslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
  2309. CLK_UNIT(parse->peer),
  2310. clockstatus(parse->generic->currentstatus));
  2311. for (i = 0; i <= CEVNT_MAX; i++)
  2312. {
  2313. u_long s_time;
  2314. u_long percent, d = current_time - parse->generic->timestarted;
  2315. percent = s_time = PARSE_STATETIME(parse, i);
  2316. while (((u_long)(~0) / 10000) < percent)
  2317. {
  2318. percent /= 10;
  2319. d /= 10;
  2320. }
  2321. if (d)
  2322. percent = (percent * 10000) / d;
  2323. else
  2324. percent = 10000;
  2325. if (s_time)
  2326. msyslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3ld.%02ld%%)",
  2327. CLK_UNIT(parse->peer),
  2328. clockstatus((unsigned int)i),
  2329. l_mktime(s_time),
  2330. percent / 100, percent % 100);
  2331. }
  2332. }
  2333. }
  2334. /*--------------------------------------------------
  2335. * cparse_statistics - wrapper for statistics call
  2336. */
  2337. static void
  2338. cparse_statistics(
  2339. struct parseunit *parse
  2340. )
  2341. {
  2342. if (parse->laststatistic + PARSESTATISTICS < current_time)
  2343. parse_statistics(parse);
  2344. parse->laststatistic = current_time;
  2345. }
  2346. /**===========================================================================
  2347. ** ntp interface routines
  2348. **/
  2349. /*--------------------------------------------------
  2350. * parse_shutdown - shut down a PARSE clock
  2351. */
  2352. static void
  2353. parse_shutdown(
  2354. int unit,
  2355. struct peer *peer
  2356. )
  2357. {
  2358. struct parseunit *parse = (struct parseunit *)0;
  2359. if (peer && peer->procptr)
  2360. parse = (struct parseunit *)peer->procptr->unitptr;
  2361. if (!parse)
  2362. {
  2363. /* nothing to clean up */
  2364. return;
  2365. }
  2366. if (!parse->peer)
  2367. {
  2368. msyslog(LOG_INFO, "PARSE receiver #%d: INTERNAL ERROR - unit already inactive - shutdown ignored", unit);
  2369. return;
  2370. }
  2371. #ifdef HAVE_PPSAPI
  2372. if (parse->flags & PARSE_PPSCLOCK)
  2373. {
  2374. (void)time_pps_destroy(parse->ppshandle);
  2375. }
  2376. #endif
  2377. if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
  2378. (void)close(parse->ppsfd); /* close separate PPS source */
  2379. /*
  2380. * print statistics a last time and
  2381. * stop statistics machine
  2382. */
  2383. parse_statistics(parse);
  2384. if (parse->parse_type->cl_end)
  2385. {
  2386. parse->parse_type->cl_end(parse);
  2387. }
  2388. /*
  2389. * cleanup before leaving this world
  2390. */
  2391. if (parse->binding)
  2392. PARSE_END(parse);
  2393. /*
  2394. * Tell the I/O module to turn us off. We're history.
  2395. */
  2396. io_closeclock(&parse->generic->io);
  2397. free_varlist(parse->kv);
  2398. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  2399. msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
  2400. CLK_UNIT(parse->peer), parse->parse_type->cl_description);
  2401. parse->peer = (struct peer *)0; /* unused now */
  2402. peer->procptr->unitptr = (caddr_t)0;
  2403. free(parse);
  2404. }
  2405. #ifdef HAVE_PPSAPI
  2406. /*----------------------------------------
  2407. * set up HARDPPS via PPSAPI
  2408. */
  2409. static void
  2410. parse_hardpps(
  2411. struct parseunit *parse,
  2412. int mode
  2413. )
  2414. {
  2415. if (parse->hardppsstate == mode)
  2416. return;
  2417. if (CLK_PPS(parse->peer) && (parse->flags & PARSE_PPSKERNEL)) {
  2418. int i = 0;
  2419. if (mode == PARSE_HARDPPS_ENABLE)
  2420. {
  2421. if (parse->flags & PARSE_CLEAR)
  2422. i = PPS_CAPTURECLEAR;
  2423. else
  2424. i = PPS_CAPTUREASSERT;
  2425. }
  2426. if (time_pps_kcbind(parse->ppshandle, PPS_KC_HARDPPS, i,
  2427. PPS_TSFMT_TSPEC) < 0) {
  2428. msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
  2429. CLK_UNIT(parse->peer));
  2430. } else {
  2431. NLOG(NLOG_CLOCKINFO)
  2432. msyslog(LOG_INFO, "PARSE receiver #%d: kernel PPS synchronisation %sabled",
  2433. CLK_UNIT(parse->peer), (mode == PARSE_HARDPPS_ENABLE) ? "en" : "dis");
  2434. /*
  2435. * tell the rest, that we have a kernel PPS source, iff we ever enable HARDPPS
  2436. */
  2437. if (mode == PARSE_HARDPPS_ENABLE)
  2438. pps_enable = 1;
  2439. }
  2440. }
  2441. parse->hardppsstate = mode;
  2442. }
  2443. /*----------------------------------------
  2444. * set up PPS via PPSAPI
  2445. */
  2446. static int
  2447. parse_ppsapi(
  2448. struct parseunit *parse
  2449. )
  2450. {
  2451. int cap, mode, mode1;
  2452. char *cp;
  2453. parse->flags &= ~PARSE_PPSCLOCK;
  2454. if (time_pps_getcap(parse->ppshandle, &cap) < 0) {
  2455. msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
  2456. CLK_UNIT(parse->peer));
  2457. return 0;
  2458. }
  2459. if (time_pps_getparams(parse->ppshandle, &parse->ppsparams) < 0) {
  2460. msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getparams failed: %m",
  2461. CLK_UNIT(parse->peer));
  2462. return 0;
  2463. }
  2464. /* nb. only turn things on, if someone else has turned something
  2465. * on before we get here, leave it alone!
  2466. */
  2467. if (parse->flags & PARSE_CLEAR) {
  2468. cp = "CLEAR";
  2469. mode = PPS_CAPTURECLEAR;
  2470. mode1 = PPS_OFFSETCLEAR;
  2471. } else {
  2472. cp = "ASSERT";
  2473. mode = PPS_CAPTUREASSERT;
  2474. mode1 = PPS_OFFSETASSERT;
  2475. }
  2476. msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
  2477. CLK_UNIT(parse->peer), cp);
  2478. if (!(mode & cap)) {
  2479. msyslog(LOG_ERR, "PARSE receiver #%d: FAILED to initialize PPS to %s (PPS API capabilities=0x%x)",
  2480. CLK_UNIT(parse->peer), cp, cap);
  2481. return 0;
  2482. }
  2483. if (!(mode1 & cap)) {
  2484. msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
  2485. CLK_UNIT(parse->peer), cp, cap);
  2486. mode1 = 0;
  2487. } else {
  2488. if (mode1 == PPS_OFFSETCLEAR)
  2489. {
  2490. parse->ppsparams.clear_offset.tv_sec = -parse->ppsphaseadjust;
  2491. parse->ppsparams.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
  2492. }
  2493. if (mode1 == PPS_OFFSETASSERT)
  2494. {
  2495. parse->ppsparams.assert_offset.tv_sec = -parse->ppsphaseadjust;
  2496. parse->ppsparams.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
  2497. }
  2498. }
  2499. /* only set what is legal */
  2500. parse->ppsparams.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
  2501. if (time_pps_setparams(parse->ppshandle, &parse->ppsparams) < 0) {
  2502. msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
  2503. CLK_UNIT(parse->peer));
  2504. return 0;
  2505. }
  2506. parse->flags |= PARSE_PPSCLOCK;
  2507. return 1;
  2508. }
  2509. #else
  2510. #define parse_hardpps(_PARSE_, _MODE_) /* empty */
  2511. #endif
  2512. /*--------------------------------------------------
  2513. * parse_start - open the PARSE devices and initialize data for processing
  2514. */
  2515. static int
  2516. parse_start(
  2517. int sysunit,
  2518. struct peer *peer
  2519. )
  2520. {
  2521. u_int unit;
  2522. int fd232;
  2523. #ifdef HAVE_TERMIOS
  2524. struct termios tio; /* NEEDED FOR A LONG TIME ! */
  2525. #endif
  2526. #ifdef HAVE_SYSV_TTYS
  2527. struct termio tio; /* NEEDED FOR A LONG TIME ! */
  2528. #endif
  2529. struct parseunit * parse;
  2530. char parsedev[sizeof(PARSEDEVICE)+20];
  2531. char parseppsdev[sizeof(PARSEPPSDEVICE)+20];
  2532. parsectl_t tmp_ctl;
  2533. u_int type;
  2534. /*
  2535. * get out Copyright information once
  2536. */
  2537. if (!notice)
  2538. {
  2539. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  2540. msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2006, Frank Kardel");
  2541. notice = 1;
  2542. }
  2543. type = CLK_TYPE(peer);
  2544. unit = CLK_UNIT(peer);
  2545. if ((type == ~0) || (parse_clockinfo[type].cl_description == (char *)0))
  2546. {
  2547. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
  2548. unit, CLK_REALTYPE(peer), ncltypes-1);
  2549. return 0;
  2550. }
  2551. /*
  2552. * Unit okay, attempt to open the device.
  2553. */
  2554. (void) snprintf(parsedev, sizeof(parsedev), PARSEDEVICE, unit);
  2555. (void) snprintf(parseppsdev, sizeof(parsedev), PARSEPPSDEVICE, unit);
  2556. #ifndef O_NOCTTY
  2557. #define O_NOCTTY 0
  2558. #endif
  2559. fd232 = open(parsedev, O_RDWR | O_NOCTTY
  2560. #ifdef O_NONBLOCK
  2561. | O_NONBLOCK
  2562. #endif
  2563. , 0777);
  2564. if (fd232 == -1)
  2565. {
  2566. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
  2567. return 0;
  2568. }
  2569. parse = (struct parseunit *)emalloc(sizeof(struct parseunit));
  2570. memset((char *)parse, 0, sizeof(struct parseunit));
  2571. parse->generic = peer->procptr; /* link up */
  2572. parse->generic->unitptr = (caddr_t)parse; /* link down */
  2573. /*
  2574. * Set up the structures
  2575. */
  2576. parse->generic->timestarted = current_time;
  2577. parse->lastchange = current_time;
  2578. parse->flags = 0;
  2579. parse->pollneeddata = 0;
  2580. parse->laststatistic = current_time;
  2581. parse->lastformat = (unsigned short)~0; /* assume no format known */
  2582. parse->timedata.parse_status = (unsigned short)~0; /* be sure to mark initial status change */
  2583. parse->lastmissed = 0; /* assume got everything */
  2584. parse->ppsserial = 0;
  2585. parse->ppsfd = -1;
  2586. parse->localdata = (void *)0;
  2587. parse->localstate = 0;
  2588. parse->kv = (struct ctl_var *)0;
  2589. clear_err(parse, ERR_ALL);
  2590. parse->parse_type = &parse_clockinfo[type];
  2591. parse->maxunsync = parse->parse_type->cl_maxunsync;
  2592. parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
  2593. parse->generic->fudgetime2 = 0.0;
  2594. parse->ppsphaseadjust = parse->generic->fudgetime2;
  2595. parse->generic->clockdesc = parse->parse_type->cl_description;
  2596. peer->rootdelay = parse->parse_type->cl_rootdelay;
  2597. peer->sstclktype = parse->parse_type->cl_type;
  2598. peer->precision = sys_precision;
  2599. peer->stratum = STRATUM_REFCLOCK;
  2600. if (peer->stratum <= 1)
  2601. memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4);
  2602. else
  2603. parse->generic->refid = htonl(PARSEHSREFID);
  2604. parse->generic->io.fd = fd232;
  2605. parse->peer = peer; /* marks it also as busy */
  2606. /*
  2607. * configure terminal line
  2608. */
  2609. if (TTY_GETATTR(fd232, &tio) == -1)
  2610. {
  2611. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tio): %m", unit, fd232);
  2612. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2613. return 0;
  2614. }
  2615. else
  2616. {
  2617. #ifndef _PC_VDISABLE
  2618. memset((char *)tio.c_cc, 0, sizeof(tio.c_cc));
  2619. #else
  2620. int disablec;
  2621. errno = 0; /* pathconf can deliver -1 without changing errno ! */
  2622. disablec = fpathconf(parse->generic->io.fd, _PC_VDISABLE);
  2623. if (disablec == -1 && errno)
  2624. {
  2625. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CLK_UNIT(parse->peer));
  2626. memset((char *)tio.c_cc, 0, sizeof(tio.c_cc)); /* best guess */
  2627. }
  2628. else
  2629. if (disablec != -1)
  2630. memset((char *)tio.c_cc, disablec, sizeof(tio.c_cc));
  2631. #endif
  2632. #if defined (VMIN) || defined(VTIME)
  2633. if ((parse_clockinfo[type].cl_lflag & ICANON) == 0)
  2634. {
  2635. #ifdef VMIN
  2636. tio.c_cc[VMIN] = 1;
  2637. #endif
  2638. #ifdef VTIME
  2639. tio.c_cc[VTIME] = 0;
  2640. #endif
  2641. }
  2642. #endif
  2643. tio.c_cflag = parse_clockinfo[type].cl_cflag;
  2644. tio.c_iflag = parse_clockinfo[type].cl_iflag;
  2645. tio.c_oflag = parse_clockinfo[type].cl_oflag;
  2646. tio.c_lflag = parse_clockinfo[type].cl_lflag;
  2647. #ifdef HAVE_TERMIOS
  2648. if ((cfsetospeed(&tio, parse_clockinfo[type].cl_speed) == -1) ||
  2649. (cfsetispeed(&tio, parse_clockinfo[type].cl_speed) == -1))
  2650. {
  2651. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcset{i,o}speed(&tio, speed): %m", unit);
  2652. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2653. return 0;
  2654. }
  2655. #else
  2656. tio.c_cflag |= parse_clockinfo[type].cl_speed;
  2657. #endif
  2658. /*
  2659. * set up pps device
  2660. * if the PARSEPPSDEVICE can be opened that will be used
  2661. * for PPS else PARSEDEVICE will be used
  2662. */
  2663. parse->ppsfd = open(parseppsdev, O_RDWR | O_NOCTTY
  2664. #ifdef O_NONBLOCK
  2665. | O_NONBLOCK
  2666. #endif
  2667. , 0777);
  2668. if (parse->ppsfd == -1)
  2669. {
  2670. parse->ppsfd = fd232;
  2671. }
  2672. /*
  2673. * Linux PPS - the old way
  2674. */
  2675. #if defined(HAVE_TIO_SERIAL_STUFF) /* Linux hack: define PPS interface */
  2676. {
  2677. struct serial_struct ss;
  2678. if (ioctl(parse->ppsfd, TIOCGSERIAL, &ss) < 0 ||
  2679. (
  2680. #ifdef ASYNC_LOW_LATENCY
  2681. ss.flags |= ASYNC_LOW_LATENCY,
  2682. #endif
  2683. #ifndef HAVE_PPSAPI
  2684. #ifdef ASYNC_PPS_CD_NEG
  2685. ss.flags |= ASYNC_PPS_CD_NEG,
  2686. #endif
  2687. #endif
  2688. ioctl(parse->ppsfd, TIOCSSERIAL, &ss)) < 0) {
  2689. msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", parse->ppsfd);
  2690. msyslog(LOG_NOTICE,
  2691. "refclock_parse: optional PPS processing not available");
  2692. } else {
  2693. parse->flags |= PARSE_PPSCLOCK;
  2694. #ifdef ASYNC_PPS_CD_NEG
  2695. NLOG(NLOG_CLOCKINFO)
  2696. msyslog(LOG_INFO,
  2697. "refclock_parse: PPS detection on");
  2698. #endif
  2699. }
  2700. }
  2701. #endif
  2702. /*
  2703. * SUN the Solaris way
  2704. */
  2705. #ifdef HAVE_TIOCSPPS /* SUN PPS support */
  2706. if (CLK_PPS(parse->peer))
  2707. {
  2708. int i = 1;
  2709. if (ioctl(parse->ppsfd, TIOCSPPS, (caddr_t)&i) == 0)
  2710. {
  2711. parse->flags |= PARSE_PPSCLOCK;
  2712. }
  2713. }
  2714. #endif
  2715. /*
  2716. * PPS via PPSAPI
  2717. */
  2718. #if defined(HAVE_PPSAPI)
  2719. parse->hardppsstate = PARSE_HARDPPS_DISABLE;
  2720. if (CLK_PPS(parse->peer))
  2721. {
  2722. if (time_pps_create(parse->ppsfd, &parse->ppshandle) < 0)
  2723. {
  2724. msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
  2725. }
  2726. else
  2727. {
  2728. parse_ppsapi(parse);
  2729. }
  2730. }
  2731. #endif
  2732. if (TTY_SETATTR(fd232, &tio) == -1)
  2733. {
  2734. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tio): %m", unit, fd232);
  2735. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2736. return 0;
  2737. }
  2738. }
  2739. /*
  2740. * pick correct input machine
  2741. */
  2742. parse->generic->io.srcclock = (caddr_t)parse;
  2743. parse->generic->io.datalen = 0;
  2744. parse->binding = init_iobinding(parse);
  2745. if (parse->binding == (bind_t *)0)
  2746. {
  2747. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.", CLK_UNIT(parse->peer));
  2748. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2749. return 0; /* well, ok - special initialisation broke */
  2750. }
  2751. parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
  2752. parse->generic->io.io_input = parse->binding->bd_io_input; /* pick correct input routine */
  2753. /*
  2754. * as we always(?) get 8 bit chars we want to be
  2755. * sure, that the upper bits are zero for less
  2756. * than 8 bit I/O - so we pass that information on.
  2757. * note that there can be only one bit count format
  2758. * per file descriptor
  2759. */
  2760. switch (tio.c_cflag & CSIZE)
  2761. {
  2762. case CS5:
  2763. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
  2764. break;
  2765. case CS6:
  2766. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
  2767. break;
  2768. case CS7:
  2769. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
  2770. break;
  2771. case CS8:
  2772. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
  2773. break;
  2774. }
  2775. if (!PARSE_SETCS(parse, &tmp_ctl))
  2776. {
  2777. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
  2778. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2779. return 0; /* well, ok - special initialisation broke */
  2780. }
  2781. strncpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format, sizeof(tmp_ctl.parseformat.parse_buffer));
  2782. tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
  2783. if (!PARSE_SETFMT(parse, &tmp_ctl))
  2784. {
  2785. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
  2786. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2787. return 0; /* well, ok - special initialisation broke */
  2788. }
  2789. /*
  2790. * get rid of all IO accumulated so far
  2791. */
  2792. #ifdef HAVE_TERMIOS
  2793. (void) tcflush(parse->generic->io.fd, TCIOFLUSH);
  2794. #else
  2795. #if defined(TCFLSH) && defined(TCIOFLUSH)
  2796. {
  2797. int flshcmd = TCIOFLUSH;
  2798. (void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
  2799. }
  2800. #endif
  2801. #endif
  2802. /*
  2803. * try to do any special initializations
  2804. */
  2805. if (parse->parse_type->cl_init)
  2806. {
  2807. if (parse->parse_type->cl_init(parse))
  2808. {
  2809. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2810. return 0; /* well, ok - special initialisation broke */
  2811. }
  2812. }
  2813. /*
  2814. * Insert in async io device list.
  2815. */
  2816. if (!io_addclock(&parse->generic->io))
  2817. {
  2818. msyslog(LOG_ERR,
  2819. "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
  2820. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2821. return 0;
  2822. }
  2823. /*
  2824. * print out configuration
  2825. */
  2826. NLOG(NLOG_CLOCKINFO)
  2827. {
  2828. /* conditional if clause for conditional syslog */
  2829. msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
  2830. CLK_UNIT(parse->peer),
  2831. parse->parse_type->cl_description, parsedev,
  2832. (parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
  2833. msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
  2834. CLK_UNIT(parse->peer),
  2835. parse->peer->stratum,
  2836. l_mktime(parse->maxunsync), parse->peer->precision);
  2837. msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
  2838. CLK_UNIT(parse->peer),
  2839. parse->parse_type->cl_rootdelay,
  2840. parse->generic->fudgetime1,
  2841. parse->ppsphaseadjust,
  2842. parse->binding->bd_description);
  2843. msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
  2844. parse->parse_type->cl_format);
  2845. msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
  2846. CLK_PPS(parse->peer) ? "" : "NO ",
  2847. CLK_PPS(parse->peer) ?
  2848. #ifdef PPS_METHOD
  2849. " (implementation " PPS_METHOD ")"
  2850. #else
  2851. ""
  2852. #endif
  2853. : ""
  2854. );
  2855. }
  2856. return 1;
  2857. }
  2858. /*--------------------------------------------------
  2859. * parse_ctl - process changes on flags/time values
  2860. */
  2861. static void
  2862. parse_ctl(
  2863. struct parseunit *parse,
  2864. struct refclockstat *in
  2865. )
  2866. {
  2867. if (in)
  2868. {
  2869. if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
  2870. {
  2871. parse->flags = (parse->flags & ~(CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
  2872. (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4));
  2873. #if defined(HAVE_PPSAPI)
  2874. if (CLK_PPS(parse->peer))
  2875. {
  2876. parse_ppsapi(parse);
  2877. }
  2878. #endif
  2879. }
  2880. if (in->haveflags & CLK_HAVETIME1)
  2881. {
  2882. parse->generic->fudgetime1 = in->fudgetime1;
  2883. msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
  2884. CLK_UNIT(parse->peer),
  2885. parse->generic->fudgetime1);
  2886. }
  2887. if (in->haveflags & CLK_HAVETIME2)
  2888. {
  2889. parse->generic->fudgetime2 = in->fudgetime2;
  2890. if (parse->flags & PARSE_TRUSTTIME)
  2891. {
  2892. parse->maxunsync = (u_long)ABS(in->fudgetime2);
  2893. msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
  2894. CLK_UNIT(parse->peer),
  2895. l_mktime(parse->maxunsync));
  2896. }
  2897. else
  2898. {
  2899. parse->ppsphaseadjust = in->fudgetime2;
  2900. msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
  2901. CLK_UNIT(parse->peer),
  2902. parse->ppsphaseadjust);
  2903. #if defined(HAVE_PPSAPI)
  2904. if (CLK_PPS(parse->peer))
  2905. {
  2906. parse_ppsapi(parse);
  2907. }
  2908. #endif
  2909. }
  2910. }
  2911. }
  2912. }
  2913. /*--------------------------------------------------
  2914. * parse_poll - called by the transmit procedure
  2915. */
  2916. static void
  2917. parse_poll(
  2918. int unit,
  2919. struct peer *peer
  2920. )
  2921. {
  2922. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  2923. if (peer != parse->peer)
  2924. {
  2925. msyslog(LOG_ERR,
  2926. "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
  2927. unit);
  2928. return;
  2929. }
  2930. /*
  2931. * Update clock stat counters
  2932. */
  2933. parse->generic->polls++;
  2934. if (parse->pollneeddata &&
  2935. ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
  2936. {
  2937. /*
  2938. * start worrying when exceeding a poll inteval
  2939. * bad news - didn't get a response last time
  2940. */
  2941. parse->lastmissed = current_time;
  2942. parse_event(parse, CEVNT_TIMEOUT);
  2943. ERR(ERR_NODATA)
  2944. msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
  2945. }
  2946. /*
  2947. * we just mark that we want the next sample for the clock filter
  2948. */
  2949. parse->pollneeddata = current_time;
  2950. if (parse->parse_type->cl_poll)
  2951. {
  2952. parse->parse_type->cl_poll(parse);
  2953. }
  2954. cparse_statistics(parse);
  2955. return;
  2956. }
  2957. #define LEN_STATES 300 /* length of state string */
  2958. /*--------------------------------------------------
  2959. * parse_control - set fudge factors, return statistics
  2960. */
  2961. static void
  2962. parse_control(
  2963. int unit,
  2964. struct refclockstat *in,
  2965. struct refclockstat *out,
  2966. struct peer *peer
  2967. )
  2968. {
  2969. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  2970. parsectl_t tmpctl;
  2971. static char outstatus[400]; /* status output buffer */
  2972. if (out)
  2973. {
  2974. out->lencode = 0;
  2975. out->p_lastcode = 0;
  2976. out->kv_list = (struct ctl_var *)0;
  2977. }
  2978. if (!parse || !parse->peer)
  2979. {
  2980. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
  2981. unit);
  2982. return;
  2983. }
  2984. unit = CLK_UNIT(parse->peer);
  2985. /*
  2986. * handle changes
  2987. */
  2988. parse_ctl(parse, in);
  2989. /*
  2990. * supply data
  2991. */
  2992. if (out)
  2993. {
  2994. u_long sum = 0;
  2995. char *tt, *start;
  2996. int i;
  2997. outstatus[0] = '\0';
  2998. out->type = REFCLK_PARSE;
  2999. /*
  3000. * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
  3001. */
  3002. parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
  3003. /*
  3004. * figure out skew between PPS and RS232 - just for informational
  3005. * purposes
  3006. */
  3007. if (PARSE_SYNC(parse->timedata.parse_state))
  3008. {
  3009. if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
  3010. {
  3011. l_fp off;
  3012. /*
  3013. * we have a PPS and RS232 signal - calculate the skew
  3014. * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
  3015. */
  3016. off = parse->timedata.parse_stime.fp;
  3017. L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
  3018. tt = add_var(&out->kv_list, 80, RO);
  3019. snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
  3020. }
  3021. }
  3022. if (PARSE_PPS(parse->timedata.parse_state))
  3023. {
  3024. tt = add_var(&out->kv_list, 80, RO|DEF);
  3025. snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
  3026. }
  3027. start = tt = add_var(&out->kv_list, 128, RO|DEF);
  3028. snprintf(tt, 128, "refclock_time=\"");
  3029. tt += strlen(tt);
  3030. if (parse->timedata.parse_time.fp.l_ui == 0)
  3031. {
  3032. strncpy(tt, "<UNDEFINED>\"", BUFFER_SIZES(start, tt, 128));
  3033. }
  3034. else
  3035. {
  3036. snprintf(tt, 128, "%s\"", gmprettydate(&parse->timedata.parse_time.fp));
  3037. }
  3038. if (!PARSE_GETTIMECODE(parse, &tmpctl))
  3039. {
  3040. ERR(ERR_INTERNAL)
  3041. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
  3042. }
  3043. else
  3044. {
  3045. start = tt = add_var(&out->kv_list, 512, RO|DEF);
  3046. snprintf(tt, 512, "refclock_status=\"");
  3047. tt += strlen(tt);
  3048. /*
  3049. * copy PPS flags from last read transaction (informational only)
  3050. */
  3051. tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
  3052. (PARSEB_PPS|PARSEB_S_PPS);
  3053. (void) parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
  3054. strncat(tt, "\"", BUFFER_SIZES(start, tt, 512));
  3055. if (tmpctl.parsegettc.parse_count)
  3056. mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
  3057. tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
  3058. }
  3059. tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
  3060. if (!PARSE_GETFMT(parse, &tmpctl))
  3061. {
  3062. ERR(ERR_INTERNAL)
  3063. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
  3064. }
  3065. else
  3066. {
  3067. tt = add_var(&out->kv_list, 80, RO|DEF);
  3068. snprintf(tt, 80, "refclock_format=\"");
  3069. strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
  3070. strncat(tt,"\"", 80);
  3071. }
  3072. /*
  3073. * gather state statistics
  3074. */
  3075. start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
  3076. strncpy(tt, "refclock_states=\"", LEN_STATES);
  3077. tt += strlen(tt);
  3078. for (i = 0; i <= CEVNT_MAX; i++)
  3079. {
  3080. u_long s_time;
  3081. u_long d = current_time - parse->generic->timestarted;
  3082. u_long percent;
  3083. percent = s_time = PARSE_STATETIME(parse, i);
  3084. while (((u_long)(~0) / 10000) < percent)
  3085. {
  3086. percent /= 10;
  3087. d /= 10;
  3088. }
  3089. if (d)
  3090. percent = (percent * 10000) / d;
  3091. else
  3092. percent = 10000;
  3093. if (s_time)
  3094. {
  3095. char item[80];
  3096. int count;
  3097. snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
  3098. sum ? "; " : "",
  3099. (parse->generic->currentstatus == i) ? "*" : "",
  3100. clockstatus((unsigned int)i),
  3101. l_mktime(s_time),
  3102. (int)(percent / 100), (int)(percent % 100));
  3103. if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
  3104. {
  3105. strncpy(tt, item, BUFFER_SIZES(start, tt, LEN_STATES));
  3106. tt += count;
  3107. }
  3108. sum += s_time;
  3109. }
  3110. }
  3111. snprintf(tt, BUFFER_SIZES(start, tt, LEN_STATES), "; running time: %s\"", l_mktime(sum));
  3112. tt = add_var(&out->kv_list, 32, RO);
  3113. snprintf(tt, 32, "refclock_id=\"%s\"", parse->parse_type->cl_id);
  3114. tt = add_var(&out->kv_list, 80, RO);
  3115. snprintf(tt, 80, "refclock_iomode=\"%s\"", parse->binding->bd_description);
  3116. tt = add_var(&out->kv_list, 128, RO);
  3117. snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
  3118. {
  3119. struct ctl_var *k;
  3120. k = parse->kv;
  3121. while (k && !(k->flags & EOV))
  3122. {
  3123. set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
  3124. k++;
  3125. }
  3126. }
  3127. out->lencode = strlen(outstatus);
  3128. out->p_lastcode = outstatus;
  3129. }
  3130. }
  3131. /**===========================================================================
  3132. ** processing routines
  3133. **/
  3134. /*--------------------------------------------------
  3135. * event handling - note that nominal events will also be posted
  3136. * keep track of state dwelling times
  3137. */
  3138. static void
  3139. parse_event(
  3140. struct parseunit *parse,
  3141. int event
  3142. )
  3143. {
  3144. if (parse->generic->currentstatus != (u_char) event)
  3145. {
  3146. parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
  3147. parse->lastchange = current_time;
  3148. if (parse->parse_type->cl_event)
  3149. parse->parse_type->cl_event(parse, event);
  3150. if (event == CEVNT_NOMINAL)
  3151. {
  3152. NLOG(NLOG_CLOCKSTATUS)
  3153. msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
  3154. CLK_UNIT(parse->peer));
  3155. }
  3156. refclock_report(parse->peer, event);
  3157. }
  3158. }
  3159. /*--------------------------------------------------
  3160. * process a PARSE time sample
  3161. */
  3162. static void
  3163. parse_process(
  3164. struct parseunit *parse,
  3165. parsetime_t *parsetime
  3166. )
  3167. {
  3168. l_fp off, rectime, reftime;
  3169. double fudge;
  3170. /*
  3171. * check for changes in conversion status
  3172. * (only one for each new status !)
  3173. */
  3174. if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
  3175. ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
  3176. (parse->timedata.parse_status != parsetime->parse_status))
  3177. {
  3178. char buffer[400];
  3179. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3180. msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
  3181. CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
  3182. if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
  3183. {
  3184. /*
  3185. * tell more about the story - list time code
  3186. * there is a slight change for a race condition and
  3187. * the time code might be overwritten by the next packet
  3188. */
  3189. parsectl_t tmpctl;
  3190. if (!PARSE_GETTIMECODE(parse, &tmpctl))
  3191. {
  3192. ERR(ERR_INTERNAL)
  3193. msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
  3194. }
  3195. else
  3196. {
  3197. ERR(ERR_BADDATA)
  3198. msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
  3199. CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
  3200. }
  3201. }
  3202. }
  3203. /*
  3204. * examine status and post appropriate events
  3205. */
  3206. if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
  3207. {
  3208. /*
  3209. * got bad data - tell the rest of the system
  3210. */
  3211. switch (parsetime->parse_status & CVT_MASK)
  3212. {
  3213. case CVT_NONE:
  3214. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3215. parse->parse_type->cl_message)
  3216. parse->parse_type->cl_message(parse, parsetime);
  3217. /*
  3218. * save PPS information that comes piggyback
  3219. */
  3220. if (PARSE_PPS(parsetime->parse_state))
  3221. {
  3222. parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  3223. parse->timedata.parse_ptime = parsetime->parse_ptime;
  3224. }
  3225. break; /* well, still waiting - timeout is handled at higher levels */
  3226. case CVT_FAIL:
  3227. if (parsetime->parse_status & CVT_BADFMT)
  3228. {
  3229. parse_event(parse, CEVNT_BADREPLY);
  3230. }
  3231. else
  3232. if (parsetime->parse_status & CVT_BADDATE)
  3233. {
  3234. parse_event(parse, CEVNT_BADDATE);
  3235. }
  3236. else
  3237. if (parsetime->parse_status & CVT_BADTIME)
  3238. {
  3239. parse_event(parse, CEVNT_BADTIME);
  3240. }
  3241. else
  3242. {
  3243. parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
  3244. }
  3245. }
  3246. return; /* skip the rest - useless */
  3247. }
  3248. /*
  3249. * check for format changes
  3250. * (in case somebody has swapped clocks 8-)
  3251. */
  3252. if (parse->lastformat != parsetime->parse_format)
  3253. {
  3254. parsectl_t tmpctl;
  3255. tmpctl.parseformat.parse_format = parsetime->parse_format;
  3256. if (!PARSE_GETFMT(parse, &tmpctl))
  3257. {
  3258. ERR(ERR_INTERNAL)
  3259. msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
  3260. }
  3261. else
  3262. {
  3263. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3264. msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
  3265. CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer);
  3266. }
  3267. parse->lastformat = parsetime->parse_format;
  3268. }
  3269. /*
  3270. * now, any changes ?
  3271. */
  3272. if ((parse->timedata.parse_state ^ parsetime->parse_state) &
  3273. ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
  3274. {
  3275. char tmp1[200];
  3276. char tmp2[200];
  3277. /*
  3278. * something happend - except for PPS events
  3279. */
  3280. (void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
  3281. (void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
  3282. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3283. msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
  3284. CLK_UNIT(parse->peer), tmp2, tmp1);
  3285. }
  3286. /*
  3287. * carry on PPS information if still usable
  3288. */
  3289. if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
  3290. {
  3291. parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  3292. parsetime->parse_ptime = parse->timedata.parse_ptime;
  3293. }
  3294. /*
  3295. * remember for future
  3296. */
  3297. parse->timedata = *parsetime;
  3298. /*
  3299. * check to see, whether the clock did a complete powerup or lost PZF signal
  3300. * and post correct events for current condition
  3301. */
  3302. if (PARSE_POWERUP(parsetime->parse_state))
  3303. {
  3304. /*
  3305. * this is bad, as we have completely lost synchronisation
  3306. * well this is a problem with the receiver here
  3307. * for PARSE Meinberg DCF77 receivers the lost synchronisation
  3308. * is true as it is the powerup state and the time is taken
  3309. * from a crude real time clock chip
  3310. * for the PZF series this is only partly true, as
  3311. * PARSE_POWERUP only means that the pseudo random
  3312. * phase shift sequence cannot be found. this is only
  3313. * bad, if we have never seen the clock in the SYNC
  3314. * state, where the PHASE and EPOCH are correct.
  3315. * for reporting events the above business does not
  3316. * really matter, but we can use the time code
  3317. * even in the POWERUP state after having seen
  3318. * the clock in the synchronized state (PZF class
  3319. * receivers) unless we have had a telegram disruption
  3320. * after having seen the clock in the SYNC state. we
  3321. * thus require having seen the clock in SYNC state
  3322. * *after* having missed telegrams (noresponse) from
  3323. * the clock. one problem remains: we might use erroneously
  3324. * POWERUP data if the disruption is shorter than 1 polling
  3325. * interval. fortunately powerdowns last usually longer than 64
  3326. * seconds and the receiver is at least 2 minutes in the
  3327. * POWERUP or NOSYNC state before switching to SYNC
  3328. */
  3329. parse_event(parse, CEVNT_FAULT);
  3330. NLOG(NLOG_CLOCKSTATUS)
  3331. ERR(ERR_BADSTATUS)
  3332. msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
  3333. CLK_UNIT(parse->peer));
  3334. }
  3335. else
  3336. {
  3337. /*
  3338. * we have two states left
  3339. *
  3340. * SYNC:
  3341. * this state means that the EPOCH (timecode) and PHASE
  3342. * information has be read correctly (at least two
  3343. * successive PARSE timecodes were received correctly)
  3344. * this is the best possible state - full trust
  3345. *
  3346. * NOSYNC:
  3347. * The clock should be on phase with respect to the second
  3348. * signal, but the timecode has not been received correctly within
  3349. * at least the last two minutes. this is a sort of half baked state
  3350. * for PARSE Meinberg DCF77 clocks this is bad news (clock running
  3351. * without timecode confirmation)
  3352. * PZF 535 has also no time confirmation, but the phase should be
  3353. * very precise as the PZF signal can be decoded
  3354. */
  3355. if (PARSE_SYNC(parsetime->parse_state))
  3356. {
  3357. /*
  3358. * currently completely synchronized - best possible state
  3359. */
  3360. parse->lastsync = current_time;
  3361. clear_err(parse, ERR_BADSTATUS);
  3362. }
  3363. else
  3364. {
  3365. /*
  3366. * we have had some problems receiving the time code
  3367. */
  3368. parse_event(parse, CEVNT_PROP);
  3369. NLOG(NLOG_CLOCKSTATUS)
  3370. ERR(ERR_BADSTATUS)
  3371. msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
  3372. CLK_UNIT(parse->peer));
  3373. }
  3374. }
  3375. fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
  3376. if (PARSE_TIMECODE(parsetime->parse_state))
  3377. {
  3378. rectime = parsetime->parse_stime.fp;
  3379. off = reftime = parsetime->parse_time.fp;
  3380. L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
  3381. #ifdef DEBUG
  3382. if (debug > 3)
  3383. printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
  3384. CLK_UNIT(parse->peer),
  3385. prettydate(&reftime),
  3386. prettydate(&rectime),
  3387. lfptoa(&off,6));
  3388. #endif
  3389. }
  3390. if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
  3391. {
  3392. l_fp offset;
  3393. double ppsphaseadjust = parse->ppsphaseadjust;
  3394. #ifdef HAVE_PPSAPI
  3395. /*
  3396. * set fudge = 0.0 if already included in PPS time stamps
  3397. */
  3398. if (parse->ppsparams.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
  3399. {
  3400. ppsphaseadjust = 0.0;
  3401. }
  3402. #endif
  3403. /*
  3404. * we have a PPS signal - much better than the RS232 stuff (we hope)
  3405. */
  3406. offset = parsetime->parse_ptime.fp;
  3407. #ifdef DEBUG
  3408. if (debug > 3)
  3409. printf("PARSE receiver #%d: PPStime %s\n",
  3410. CLK_UNIT(parse->peer),
  3411. prettydate(&offset));
  3412. #endif
  3413. if (PARSE_TIMECODE(parsetime->parse_state))
  3414. {
  3415. if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
  3416. M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
  3417. {
  3418. fudge = ppsphaseadjust; /* pick PPS fudge factor */
  3419. /*
  3420. * RS232 offsets within [-0.5..0.5[ - take PPS offsets
  3421. */
  3422. if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
  3423. {
  3424. reftime = off = offset;
  3425. if (reftime.l_uf & (unsigned)0x80000000)
  3426. reftime.l_ui++;
  3427. reftime.l_uf = 0;
  3428. /*
  3429. * implied on second offset
  3430. */
  3431. off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
  3432. off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
  3433. }
  3434. else
  3435. {
  3436. /*
  3437. * time code describes pulse
  3438. */
  3439. reftime = off = parsetime->parse_time.fp;
  3440. L_SUB(&off, &offset); /* true offset */
  3441. }
  3442. }
  3443. /*
  3444. * take RS232 offset when PPS when out of bounds
  3445. */
  3446. }
  3447. else
  3448. {
  3449. fudge = ppsphaseadjust; /* pick PPS fudge factor */
  3450. /*
  3451. * Well, no time code to guide us - assume on second pulse
  3452. * and pray, that we are within [-0.5..0.5[
  3453. */
  3454. off = offset;
  3455. reftime = offset;
  3456. if (reftime.l_uf & (unsigned)0x80000000)
  3457. reftime.l_ui++;
  3458. reftime.l_uf = 0;
  3459. /*
  3460. * implied on second offset
  3461. */
  3462. off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
  3463. off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
  3464. }
  3465. }
  3466. else
  3467. {
  3468. if (!PARSE_TIMECODE(parsetime->parse_state))
  3469. {
  3470. /*
  3471. * Well, no PPS, no TIMECODE, no more work ...
  3472. */
  3473. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3474. parse->parse_type->cl_message)
  3475. parse->parse_type->cl_message(parse, parsetime);
  3476. return;
  3477. }
  3478. }
  3479. #ifdef DEBUG
  3480. if (debug > 3)
  3481. printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
  3482. CLK_UNIT(parse->peer),
  3483. prettydate(&reftime),
  3484. prettydate(&rectime),
  3485. lfptoa(&off,6));
  3486. #endif
  3487. rectime = reftime;
  3488. L_SUB(&rectime, &off); /* just to keep the ntp interface happy */
  3489. #ifdef DEBUG
  3490. if (debug > 3)
  3491. printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
  3492. CLK_UNIT(parse->peer),
  3493. prettydate(&reftime),
  3494. prettydate(&rectime));
  3495. #endif
  3496. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3497. parse->parse_type->cl_message)
  3498. parse->parse_type->cl_message(parse, parsetime);
  3499. if (PARSE_SYNC(parsetime->parse_state))
  3500. {
  3501. /*
  3502. * log OK status
  3503. */
  3504. parse_event(parse, CEVNT_NOMINAL);
  3505. }
  3506. clear_err(parse, ERR_BADIO);
  3507. clear_err(parse, ERR_BADDATA);
  3508. clear_err(parse, ERR_NODATA);
  3509. clear_err(parse, ERR_INTERNAL);
  3510. /*
  3511. * and now stick it into the clock machine
  3512. * samples are only valid iff lastsync is not too old and
  3513. * we have seen the clock in sync at least once
  3514. * after the last time we didn't see an expected data telegram
  3515. * at startup being not in sync is also bad just like
  3516. * POWERUP state
  3517. * see the clock states section above for more reasoning
  3518. */
  3519. if (((current_time - parse->lastsync) > parse->maxunsync) ||
  3520. (parse->lastsync < parse->lastmissed) ||
  3521. ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
  3522. PARSE_POWERUP(parsetime->parse_state))
  3523. {
  3524. parse->generic->leap = LEAP_NOTINSYNC;
  3525. parse->lastsync = 0; /* wait for full sync again */
  3526. }
  3527. else
  3528. {
  3529. if (PARSE_LEAPADD(parsetime->parse_state))
  3530. {
  3531. /*
  3532. * we pick this state also for time code that pass leap warnings
  3533. * without direction information (as earth is currently slowing
  3534. * down).
  3535. */
  3536. parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
  3537. }
  3538. else
  3539. if (PARSE_LEAPDEL(parsetime->parse_state))
  3540. {
  3541. parse->generic->leap = LEAP_DELSECOND;
  3542. }
  3543. else
  3544. {
  3545. parse->generic->leap = LEAP_NOWARNING;
  3546. }
  3547. }
  3548. if (parse->generic->leap != LEAP_NOTINSYNC)
  3549. {
  3550. /*
  3551. * only good/trusted samples are interesting
  3552. */
  3553. #ifdef DEBUG
  3554. if (debug > 2)
  3555. {
  3556. printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
  3557. CLK_UNIT(parse->peer),
  3558. prettydate(&reftime),
  3559. prettydate(&rectime),
  3560. fudge);
  3561. }
  3562. #endif
  3563. parse->generic->lastref = reftime;
  3564. refclock_process_offset(parse->generic, reftime, rectime, fudge);
  3565. /*
  3566. * pass PPS information on to PPS clock
  3567. */
  3568. if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
  3569. {
  3570. (void) pps_sample(&parse->timedata.parse_ptime.fp);
  3571. parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
  3572. }
  3573. } else {
  3574. parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
  3575. }
  3576. /*
  3577. * ready, unless the machine wants a sample or
  3578. * we are in fast startup mode (peer->dist > MAXDISTANCE)
  3579. */
  3580. if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
  3581. return;
  3582. parse->pollneeddata = 0;
  3583. parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
  3584. refclock_receive(parse->peer);
  3585. }
  3586. /**===========================================================================
  3587. ** special code for special clocks
  3588. **/
  3589. static void
  3590. mk_utcinfo(
  3591. char *t,
  3592. int wnt,
  3593. int wnlsf,
  3594. int dn,
  3595. int dtls,
  3596. int dtlsf,
  3597. int size
  3598. )
  3599. {
  3600. l_fp leapdate;
  3601. char *start = t;
  3602. snprintf(t, size, "current correction %d sec", dtls);
  3603. t += strlen(t);
  3604. if (wnlsf < 990)
  3605. wnlsf += 1024;
  3606. if (wnt < 990)
  3607. wnt += 1024;
  3608. gpstolfp((unsigned short)wnlsf, (unsigned short)dn, 0, &leapdate);
  3609. if ((dtlsf != dtls) &&
  3610. ((wnlsf - wnt) < 52))
  3611. {
  3612. snprintf(t, BUFFER_SIZES(start, t, size), ", next correction %d sec on %s, new GPS-UTC offset %d",
  3613. dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
  3614. }
  3615. else
  3616. {
  3617. snprintf(t, BUFFER_SIZES(start, t, size), ", last correction on %s",
  3618. gmprettydate(&leapdate));
  3619. }
  3620. }
  3621. #ifdef CLOCK_MEINBERG
  3622. /**===========================================================================
  3623. ** Meinberg GPS166/GPS167 support
  3624. **/
  3625. /*------------------------------------------------------------
  3626. * gps16x_message - process GPS16x messages
  3627. */
  3628. static void
  3629. gps16x_message(
  3630. struct parseunit *parse,
  3631. parsetime_t *parsetime
  3632. )
  3633. {
  3634. if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
  3635. {
  3636. GPS_MSG_HDR header;
  3637. unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
  3638. #ifdef DEBUG
  3639. if (debug > 2)
  3640. {
  3641. char msgbuffer[600];
  3642. mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
  3643. printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
  3644. CLK_UNIT(parse->peer),
  3645. parsetime->parse_msglen,
  3646. msgbuffer);
  3647. }
  3648. #endif
  3649. get_mbg_header(&bufp, &header);
  3650. if (header.gps_hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
  3651. (header.gps_len == 0 ||
  3652. (header.gps_len < sizeof(parsetime->parse_msg) &&
  3653. header.gps_data_csum == mbg_csum(bufp, header.gps_len))))
  3654. {
  3655. /*
  3656. * clean message
  3657. */
  3658. switch (header.gps_cmd)
  3659. {
  3660. case GPS_SW_REV:
  3661. {
  3662. char buffer[64];
  3663. SW_REV gps_sw_rev;
  3664. get_mbg_sw_rev(&bufp, &gps_sw_rev);
  3665. snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
  3666. (gps_sw_rev.code >> 8) & 0xFF,
  3667. gps_sw_rev.code & 0xFF,
  3668. gps_sw_rev.name[0] ? " " : "",
  3669. gps_sw_rev.name);
  3670. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3671. }
  3672. break;
  3673. case GPS_STAT:
  3674. {
  3675. static struct state
  3676. {
  3677. unsigned short flag; /* status flag */
  3678. unsigned const char *string; /* bit name */
  3679. } states[] =
  3680. {
  3681. { TM_ANT_DISCONN, (const unsigned char *)"ANTENNA FAULTY" },
  3682. { TM_SYN_FLAG, (const unsigned char *)"NO SYNC SIGNAL" },
  3683. { TM_NO_SYNC, (const unsigned char *)"NO SYNC POWERUP" },
  3684. { TM_NO_POS, (const unsigned char *)"NO POSITION" },
  3685. { 0, (const unsigned char *)"" }
  3686. };
  3687. unsigned short status;
  3688. struct state *s = states;
  3689. char buffer[512];
  3690. char *p, *b;
  3691. status = get_lsb_short(&bufp);
  3692. snprintf(buffer, sizeof(buffer), "meinberg_gps_status=\"[0x%04x] ", status);
  3693. if (status)
  3694. {
  3695. p = b = buffer + strlen(buffer);
  3696. while (s->flag)
  3697. {
  3698. if (status & s->flag)
  3699. {
  3700. if (p != b)
  3701. {
  3702. *p++ = ',';
  3703. *p++ = ' ';
  3704. }
  3705. strncat(p, (const char *)s->string, sizeof(buffer));
  3706. }
  3707. s++;
  3708. }
  3709. *p++ = '"';
  3710. *p = '\0';
  3711. }
  3712. else
  3713. {
  3714. strncat(buffer, "<OK>\"", sizeof(buffer));
  3715. }
  3716. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3717. }
  3718. break;
  3719. case GPS_POS_XYZ:
  3720. {
  3721. XYZ xyz;
  3722. char buffer[256];
  3723. get_mbg_xyz(&bufp, xyz);
  3724. snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
  3725. mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
  3726. mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
  3727. mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
  3728. set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
  3729. }
  3730. break;
  3731. case GPS_POS_LLA:
  3732. {
  3733. LLA lla;
  3734. char buffer[256];
  3735. get_mbg_lla(&bufp, lla);
  3736. snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
  3737. mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
  3738. mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
  3739. mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
  3740. set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
  3741. }
  3742. break;
  3743. case GPS_TZDL:
  3744. break;
  3745. case GPS_PORT_PARM:
  3746. break;
  3747. case GPS_SYNTH:
  3748. break;
  3749. case GPS_ANT_INFO:
  3750. {
  3751. ANT_INFO antinfo;
  3752. char buffer[512];
  3753. char *p;
  3754. get_mbg_antinfo(&bufp, &antinfo);
  3755. snprintf(buffer, sizeof(buffer), "meinberg_antenna_status=\"");
  3756. p = buffer + strlen(buffer);
  3757. switch (antinfo.status)
  3758. {
  3759. case ANT_INVALID:
  3760. strncat(p, "<OK>", BUFFER_SIZE(buffer, p));
  3761. p += strlen(p);
  3762. break;
  3763. case ANT_DISCONN:
  3764. strncat(p, "DISCONNECTED since ", BUFFER_SIZE(buffer, p));
  3765. NLOG(NLOG_CLOCKSTATUS)
  3766. ERR(ERR_BADSTATUS)
  3767. msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
  3768. CLK_UNIT(parse->peer), p);
  3769. p += strlen(p);
  3770. mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
  3771. *p = '\0';
  3772. break;
  3773. case ANT_RECONN:
  3774. strncat(p, "RECONNECTED on ", BUFFER_SIZE(buffer, p));
  3775. p += strlen(p);
  3776. mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p));
  3777. snprintf(p, BUFFER_SIZE(buffer, p), ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
  3778. (antinfo.delta_t < 0) ? '-' : '+',
  3779. ABS(antinfo.delta_t) / 10000,
  3780. ABS(antinfo.delta_t) % 10000);
  3781. p += strlen(p);
  3782. mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
  3783. *p = '\0';
  3784. break;
  3785. default:
  3786. snprintf(p, BUFFER_SIZE(buffer, p), "bad status 0x%04x", antinfo.status);
  3787. p += strlen(p);
  3788. break;
  3789. }
  3790. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  3791. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3792. }
  3793. break;
  3794. case GPS_UCAP:
  3795. break;
  3796. case GPS_CFGH:
  3797. {
  3798. CFGH cfgh;
  3799. char buffer[512];
  3800. char *p;
  3801. get_mbg_cfgh(&bufp, &cfgh);
  3802. if (cfgh.valid)
  3803. {
  3804. int i;
  3805. p = buffer;
  3806. strncpy(buffer, "gps_tot_51=\"", BUFFER_SIZE(buffer, p));
  3807. p += strlen(p);
  3808. mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
  3809. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3810. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3811. p = buffer;
  3812. strncpy(buffer, "gps_tot_63=\"", BUFFER_SIZE(buffer, p));
  3813. p += strlen(p);
  3814. mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
  3815. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3816. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3817. p = buffer;
  3818. strncpy(buffer, "gps_t0a=\"", BUFFER_SIZE(buffer, p));
  3819. p += strlen(p);
  3820. mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
  3821. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3822. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3823. for (i = MIN_SVNO; i < MAX_SVNO; i++)
  3824. {
  3825. p = buffer;
  3826. snprintf(p, BUFFER_SIZE(buffer, p), "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
  3827. p += strlen(p);
  3828. switch (cfgh.cfg[i] & 0x7)
  3829. {
  3830. case 0:
  3831. strncpy(p, "BLOCK I", BUFFER_SIZE(buffer, p));
  3832. break;
  3833. case 1:
  3834. strncpy(p, "BLOCK II", BUFFER_SIZE(buffer, p));
  3835. break;
  3836. default:
  3837. strncpy(p, "bad CFG", BUFFER_SIZE(buffer, p));
  3838. break;
  3839. }
  3840. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  3841. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3842. p = buffer;
  3843. snprintf(p, BUFFER_SIZE(buffer, p), "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
  3844. p += strlen(p);
  3845. switch ((cfgh.health[i] >> 5) & 0x7 )
  3846. {
  3847. case 0:
  3848. strncpy(p, "OK;", BUFFER_SIZE(buffer, p));
  3849. break;
  3850. case 1:
  3851. strncpy(p, "PARITY;", BUFFER_SIZE(buffer, p));
  3852. break;
  3853. case 2:
  3854. strncpy(p, "TLM/HOW;", BUFFER_SIZE(buffer, p));
  3855. break;
  3856. case 3:
  3857. strncpy(p, "Z-COUNT;", BUFFER_SIZE(buffer, p));
  3858. break;
  3859. case 4:
  3860. strncpy(p, "SUBFRAME 1,2,3;", BUFFER_SIZE(buffer, p));
  3861. break;
  3862. case 5:
  3863. strncpy(p, "SUBFRAME 4,5;", BUFFER_SIZE(buffer, p));
  3864. break;
  3865. case 6:
  3866. strncpy(p, "UPLOAD BAD;", BUFFER_SIZE(buffer, p));
  3867. break;
  3868. case 7:
  3869. strncpy(p, "DATA BAD;", BUFFER_SIZE(buffer, p));
  3870. break;
  3871. }
  3872. p += strlen(p);
  3873. switch (cfgh.health[i] & 0x1F)
  3874. {
  3875. case 0:
  3876. strncpy(p, "SIGNAL OK", BUFFER_SIZE(buffer, p));
  3877. break;
  3878. case 0x1C:
  3879. strncpy(p, "SV TEMP OUT", BUFFER_SIZE(buffer, p));
  3880. break;
  3881. case 0x1D:
  3882. strncpy(p, "SV WILL BE TEMP OUT", BUFFER_SIZE(buffer, p));
  3883. break;
  3884. case 0x1E:
  3885. break;
  3886. case 0x1F:
  3887. strncpy(p, "MULTIPLE ERRS", BUFFER_SIZE(buffer, p));
  3888. break;
  3889. default:
  3890. strncpy(p, "TRANSMISSION PROBLEMS", BUFFER_SIZE(buffer, p));
  3891. break;
  3892. }
  3893. strncat(p, "\"", sizeof(buffer));
  3894. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3895. }
  3896. }
  3897. }
  3898. break;
  3899. case GPS_ALM:
  3900. break;
  3901. case GPS_EPH:
  3902. break;
  3903. case GPS_UTC:
  3904. {
  3905. UTC utc;
  3906. char buffer[512];
  3907. char *p;
  3908. p = buffer;
  3909. get_mbg_utc(&bufp, &utc);
  3910. if (utc.valid)
  3911. {
  3912. strncpy(p, "gps_utc_correction=\"", sizeof(buffer));
  3913. p += strlen(p);
  3914. mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
  3915. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  3916. }
  3917. else
  3918. {
  3919. strncpy(p, "gps_utc_correction=\"<NO UTC DATA>\"", BUFFER_SIZE(buffer, p));
  3920. }
  3921. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3922. }
  3923. break;
  3924. case GPS_IONO:
  3925. break;
  3926. case GPS_ASCII_MSG:
  3927. {
  3928. ASCII_MSG gps_ascii_msg;
  3929. char buffer[128];
  3930. get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
  3931. if (gps_ascii_msg.valid)
  3932. {
  3933. char buffer1[128];
  3934. mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
  3935. snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
  3936. }
  3937. else
  3938. strncpy(buffer, "gps_message=<NONE>", sizeof(buffer));
  3939. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3940. }
  3941. break;
  3942. default:
  3943. break;
  3944. }
  3945. }
  3946. else
  3947. {
  3948. msyslog(LOG_DEBUG, "PARSE receiver #%d: gps16x_message: message checksum error: hdr_csum = 0x%x (expected 0x%lx), data_len = %d, data_csum = 0x%x (expected 0x%lx)",
  3949. CLK_UNIT(parse->peer),
  3950. header.gps_hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
  3951. header.gps_len,
  3952. header.gps_data_csum, mbg_csum(bufp, (unsigned)((header.gps_len < sizeof(parsetime->parse_msg)) ? header.gps_len : 0)));
  3953. }
  3954. }
  3955. return;
  3956. }
  3957. /*------------------------------------------------------------
  3958. * gps16x_poll - query the reciver peridically
  3959. */
  3960. static void
  3961. gps16x_poll(
  3962. struct peer *peer
  3963. )
  3964. {
  3965. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  3966. static GPS_MSG_HDR sequence[] =
  3967. {
  3968. { GPS_SW_REV, 0, 0, 0 },
  3969. { GPS_STAT, 0, 0, 0 },
  3970. { GPS_UTC, 0, 0, 0 },
  3971. { GPS_ASCII_MSG, 0, 0, 0 },
  3972. { GPS_ANT_INFO, 0, 0, 0 },
  3973. { GPS_CFGH, 0, 0, 0 },
  3974. { GPS_POS_XYZ, 0, 0, 0 },
  3975. { GPS_POS_LLA, 0, 0, 0 },
  3976. { (unsigned short)~0, 0, 0, 0 }
  3977. };
  3978. int rtc;
  3979. unsigned char cmd_buffer[64];
  3980. unsigned char *outp = cmd_buffer;
  3981. GPS_MSG_HDR *header;
  3982. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  3983. {
  3984. parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
  3985. }
  3986. if (sequence[parse->localstate].gps_cmd == (unsigned short)~0)
  3987. parse->localstate = 0;
  3988. header = sequence + parse->localstate++;
  3989. *outp++ = SOH; /* start command */
  3990. put_mbg_header(&outp, header);
  3991. outp = cmd_buffer + 1;
  3992. header->gps_hdr_csum = (short)mbg_csum(outp, 6);
  3993. put_mbg_header(&outp, header);
  3994. #ifdef DEBUG
  3995. if (debug > 2)
  3996. {
  3997. char buffer[128];
  3998. mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
  3999. printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
  4000. CLK_UNIT(parse->peer),
  4001. parse->localstate - 1,
  4002. (int)(outp - cmd_buffer),
  4003. buffer);
  4004. }
  4005. #endif
  4006. rtc = write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
  4007. if (rtc < 0)
  4008. {
  4009. ERR(ERR_BADIO)
  4010. msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4011. }
  4012. else
  4013. if (rtc != outp - cmd_buffer)
  4014. {
  4015. ERR(ERR_BADIO)
  4016. msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, (int)(outp - cmd_buffer));
  4017. }
  4018. clear_err(parse, ERR_BADIO);
  4019. return;
  4020. }
  4021. /*--------------------------------------------------
  4022. * init routine - setup timer
  4023. */
  4024. static int
  4025. gps16x_poll_init(
  4026. struct parseunit *parse
  4027. )
  4028. {
  4029. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4030. {
  4031. parse->peer->action = gps16x_poll;
  4032. gps16x_poll(parse->peer);
  4033. }
  4034. return 0;
  4035. }
  4036. #else
  4037. static void
  4038. gps16x_message(
  4039. struct parseunit *parse,
  4040. parsetime_t *parsetime
  4041. )
  4042. {}
  4043. static int
  4044. gps16x_poll_init(
  4045. struct parseunit *parse
  4046. )
  4047. {
  4048. return 1;
  4049. }
  4050. #endif /* CLOCK_MEINBERG */
  4051. /**===========================================================================
  4052. ** clock polling support
  4053. **/
  4054. /*--------------------------------------------------
  4055. * direct poll routine
  4056. */
  4057. static void
  4058. poll_dpoll(
  4059. struct parseunit *parse
  4060. )
  4061. {
  4062. int rtc;
  4063. const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
  4064. int ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
  4065. rtc = write(parse->generic->io.fd, ps, (unsigned long)ct);
  4066. if (rtc < 0)
  4067. {
  4068. ERR(ERR_BADIO)
  4069. msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4070. }
  4071. else
  4072. if (rtc != ct)
  4073. {
  4074. ERR(ERR_BADIO)
  4075. msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
  4076. }
  4077. clear_err(parse, ERR_BADIO);
  4078. }
  4079. /*--------------------------------------------------
  4080. * periodic poll routine
  4081. */
  4082. static void
  4083. poll_poll(
  4084. struct peer *peer
  4085. )
  4086. {
  4087. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  4088. if (parse->parse_type->cl_poll)
  4089. parse->parse_type->cl_poll(parse);
  4090. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4091. {
  4092. parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
  4093. }
  4094. }
  4095. /*--------------------------------------------------
  4096. * init routine - setup timer
  4097. */
  4098. static int
  4099. poll_init(
  4100. struct parseunit *parse
  4101. )
  4102. {
  4103. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4104. {
  4105. parse->peer->action = poll_poll;
  4106. poll_poll(parse->peer);
  4107. }
  4108. return 0;
  4109. }
  4110. /**===========================================================================
  4111. ** Trimble support
  4112. **/
  4113. /*-------------------------------------------------------------
  4114. * trimble TAIP init routine - setup EOL and then do poll_init.
  4115. */
  4116. static int
  4117. trimbletaip_init(
  4118. struct parseunit *parse
  4119. )
  4120. {
  4121. #ifdef HAVE_TERMIOS
  4122. struct termios tio;
  4123. #endif
  4124. #ifdef HAVE_SYSV_TTYS
  4125. struct termio tio;
  4126. #endif
  4127. /*
  4128. * configure terminal line for trimble receiver
  4129. */
  4130. if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
  4131. {
  4132. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
  4133. return 0;
  4134. }
  4135. else
  4136. {
  4137. tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
  4138. if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
  4139. {
  4140. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
  4141. return 0;
  4142. }
  4143. }
  4144. return poll_init(parse);
  4145. }
  4146. /*--------------------------------------------------
  4147. * trimble TAIP event routine - reset receiver upon data format trouble
  4148. */
  4149. static const char *taipinit[] = {
  4150. ">FPV00000000<",
  4151. ">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
  4152. ">FTM00020001<",
  4153. (char *)0
  4154. };
  4155. static void
  4156. trimbletaip_event(
  4157. struct parseunit *parse,
  4158. int event
  4159. )
  4160. {
  4161. switch (event)
  4162. {
  4163. case CEVNT_BADREPLY: /* reset on garbled input */
  4164. case CEVNT_TIMEOUT: /* reset on no input */
  4165. {
  4166. const char **iv;
  4167. iv = taipinit;
  4168. while (*iv)
  4169. {
  4170. int rtc = write(parse->generic->io.fd, *iv, strlen(*iv));
  4171. if (rtc < 0)
  4172. {
  4173. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4174. return;
  4175. }
  4176. else
  4177. {
  4178. if (rtc != strlen(*iv))
  4179. {
  4180. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
  4181. CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
  4182. return;
  4183. }
  4184. }
  4185. iv++;
  4186. }
  4187. NLOG(NLOG_CLOCKINFO)
  4188. ERR(ERR_BADIO)
  4189. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
  4190. CLK_UNIT(parse->peer));
  4191. }
  4192. break;
  4193. default: /* ignore */
  4194. break;
  4195. }
  4196. }
  4197. /*
  4198. * This driver supports the Trimble SVee Six Plus GPS receiver module.
  4199. * It should support other Trimble receivers which use the Trimble Standard
  4200. * Interface Protocol (see below).
  4201. *
  4202. * The module has a serial I/O port for command/data and a 1 pulse-per-second
  4203. * output, about 1 microsecond wide. The leading edge of the pulse is
  4204. * coincident with the change of the GPS second. This is the same as
  4205. * the change of the UTC second +/- ~1 microsecond. Some other clocks
  4206. * specifically use a feature in the data message as a timing reference, but
  4207. * the SVee Six Plus does not do this. In fact there is considerable jitter
  4208. * on the timing of the messages, so this driver only supports the use
  4209. * of the PPS pulse for accurate timing. Where it is determined that
  4210. * the offset is way off, when first starting up ntpd for example,
  4211. * the timing of the data stream is used until the offset becomes low enough
  4212. * (|offset| < CLOCK_MAX), at which point the pps offset is used.
  4213. *
  4214. * It can use either option for receiving PPS information - the 'ppsclock'
  4215. * stream pushed onto the serial data interface to timestamp the Carrier
  4216. * Detect interrupts, where the 1PPS connects to the CD line. This only
  4217. * works on SunOS 4.1.x currently. To select this, define PPSPPS in
  4218. * Config.local. The other option is to use a pulse-stretcher/level-converter
  4219. * to convert the PPS pulse into a RS232 start pulse & feed this into another
  4220. * tty port. To use this option, define PPSCLK in Config.local. The pps input,
  4221. * by whichever method, is handled in ntp_loopfilter.c
  4222. *
  4223. * The receiver uses a serial message protocol called Trimble Standard
  4224. * Interface Protocol (it can support others but this driver only supports
  4225. * TSIP). Messages in this protocol have the following form:
  4226. *
  4227. * <DLE><id> ... <data> ... <DLE><ETX>
  4228. *
  4229. * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
  4230. * on transmission and compressed back to one on reception. Otherwise
  4231. * the values of data bytes can be anything. The serial interface is RS-422
  4232. * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
  4233. * in total!), and 1 stop bit. The protocol supports byte, integer, single,
  4234. * and double datatypes. Integers are two bytes, sent most significant first.
  4235. * Singles are IEEE754 single precision floating point numbers (4 byte) sent
  4236. * sign & exponent first. Doubles are IEEE754 double precision floating point
  4237. * numbers (8 byte) sent sign & exponent first.
  4238. * The receiver supports a large set of messages, only a small subset of
  4239. * which are used here. From driver to receiver the following are used:
  4240. *
  4241. * ID Description
  4242. *
  4243. * 21 Request current time
  4244. * 22 Mode Select
  4245. * 2C Set/Request operating parameters
  4246. * 2F Request UTC info
  4247. * 35 Set/Request I/O options
  4248. * From receiver to driver the following are recognised:
  4249. *
  4250. * ID Description
  4251. *
  4252. * 41 GPS Time
  4253. * 44 Satellite selection, PDOP, mode
  4254. * 46 Receiver health
  4255. * 4B Machine code/status
  4256. * 4C Report operating parameters (debug only)
  4257. * 4F UTC correction data (used to get leap second warnings)
  4258. * 55 I/O options (debug only)
  4259. *
  4260. * All others are accepted but ignored.
  4261. *
  4262. */
  4263. #define PI 3.1415926535898 /* lots of sig figs */
  4264. #define D2R PI/180.0
  4265. /*-------------------------------------------------------------------
  4266. * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
  4267. * interface to the receiver.
  4268. *
  4269. * CAVEAT: the sendflt, sendint routines are byte order dependend and
  4270. * float implementation dependend - these must be converted to portable
  4271. * versions !
  4272. *
  4273. * CURRENT LIMITATION: float implementation. This runs only on systems
  4274. * with IEEE754 floats as native floats
  4275. */
  4276. typedef struct trimble
  4277. {
  4278. u_long last_msg; /* last message received */
  4279. u_long last_reset; /* last time a reset was issued */
  4280. u_char qtracking; /* query tracking status */
  4281. u_long ctrack; /* current tracking set */
  4282. u_long ltrack; /* last tracking set */
  4283. } trimble_t;
  4284. union uval {
  4285. u_char bd[8];
  4286. int iv;
  4287. float fv;
  4288. double dv;
  4289. };
  4290. struct txbuf
  4291. {
  4292. short idx; /* index to first unused byte */
  4293. u_char *txt; /* pointer to actual data buffer */
  4294. };
  4295. void sendcmd P((struct txbuf *buf, int c));
  4296. void sendbyte P((struct txbuf *buf, int b));
  4297. void sendetx P((struct txbuf *buf, struct parseunit *parse));
  4298. void sendint P((struct txbuf *buf, int a));
  4299. void sendflt P((struct txbuf *buf, double a));
  4300. void
  4301. sendcmd(
  4302. struct txbuf *buf,
  4303. int c
  4304. )
  4305. {
  4306. buf->txt[0] = DLE;
  4307. buf->txt[1] = (u_char)c;
  4308. buf->idx = 2;
  4309. }
  4310. void sendcmd P((struct txbuf *buf, int c));
  4311. void sendbyte P((struct txbuf *buf, int b));
  4312. void sendetx P((struct txbuf *buf, struct parseunit *parse));
  4313. void sendint P((struct txbuf *buf, int a));
  4314. void sendflt P((struct txbuf *buf, double a));
  4315. void
  4316. sendbyte(
  4317. struct txbuf *buf,
  4318. int b
  4319. )
  4320. {
  4321. if (b == DLE)
  4322. buf->txt[buf->idx++] = DLE;
  4323. buf->txt[buf->idx++] = (u_char)b;
  4324. }
  4325. void
  4326. sendetx(
  4327. struct txbuf *buf,
  4328. struct parseunit *parse
  4329. )
  4330. {
  4331. buf->txt[buf->idx++] = DLE;
  4332. buf->txt[buf->idx++] = ETX;
  4333. if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
  4334. {
  4335. ERR(ERR_BADIO)
  4336. msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4337. }
  4338. else
  4339. {
  4340. #ifdef DEBUG
  4341. if (debug > 2)
  4342. {
  4343. char buffer[256];
  4344. mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
  4345. printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
  4346. CLK_UNIT(parse->peer),
  4347. buf->idx, buffer);
  4348. }
  4349. #endif
  4350. clear_err(parse, ERR_BADIO);
  4351. }
  4352. }
  4353. void
  4354. sendint(
  4355. struct txbuf *buf,
  4356. int a
  4357. )
  4358. {
  4359. /* send 16bit int, msbyte first */
  4360. sendbyte(buf, (u_char)((a>>8) & 0xff));
  4361. sendbyte(buf, (u_char)(a & 0xff));
  4362. }
  4363. void
  4364. sendflt(
  4365. struct txbuf *buf,
  4366. double a
  4367. )
  4368. {
  4369. int i;
  4370. union uval uval;
  4371. uval.fv = a;
  4372. #ifdef WORDS_BIGENDIAN
  4373. for (i=0; i<=3; i++)
  4374. #else
  4375. for (i=3; i>=0; i--)
  4376. #endif
  4377. sendbyte(buf, uval.bd[i]);
  4378. }
  4379. #define TRIM_POS_OPT 0x13 /* output position with high precision */
  4380. #define TRIM_TIME_OPT 0x03 /* use UTC time stamps, on second */
  4381. /*--------------------------------------------------
  4382. * trimble TSIP setup routine
  4383. */
  4384. static int
  4385. trimbletsip_setup(
  4386. struct parseunit *parse,
  4387. const char *reason
  4388. )
  4389. {
  4390. u_char buffer[256];
  4391. struct txbuf buf;
  4392. trimble_t *t = parse->localdata;
  4393. if (t && t->last_reset &&
  4394. ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
  4395. return 1; /* not yet */
  4396. }
  4397. if (t)
  4398. t->last_reset = current_time;
  4399. buf.txt = buffer;
  4400. sendcmd(&buf, CMD_CVERSION); /* request software versions */
  4401. sendetx(&buf, parse);
  4402. sendcmd(&buf, CMD_COPERPARAM); /* set operating parameters */
  4403. sendbyte(&buf, 4); /* static */
  4404. sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */
  4405. sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */
  4406. sendflt(&buf, 12.0); /* PDOP mask = 12 */
  4407. sendflt(&buf, 8.0); /* PDOP switch level = 8 */
  4408. sendetx(&buf, parse);
  4409. sendcmd(&buf, CMD_CMODESEL); /* fix mode select */
  4410. sendbyte(&buf, 1); /* time transfer mode */
  4411. sendetx(&buf, parse);
  4412. sendcmd(&buf, CMD_CMESSAGE); /* request system message */
  4413. sendetx(&buf, parse);
  4414. sendcmd(&buf, CMD_CSUPER); /* superpacket fix */
  4415. sendbyte(&buf, 0x2); /* binary mode */
  4416. sendetx(&buf, parse);
  4417. sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */
  4418. sendbyte(&buf, TRIM_POS_OPT); /* position output */
  4419. sendbyte(&buf, 0x00); /* no velocity output */
  4420. sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */
  4421. sendbyte(&buf, 0x00); /* no raw measurements */
  4422. sendetx(&buf, parse);
  4423. sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */
  4424. sendetx(&buf, parse);
  4425. NLOG(NLOG_CLOCKINFO)
  4426. ERR(ERR_BADIO)
  4427. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
  4428. return 0;
  4429. }
  4430. /*--------------------------------------------------
  4431. * TRIMBLE TSIP check routine
  4432. */
  4433. static void
  4434. trimble_check(
  4435. struct peer *peer
  4436. )
  4437. {
  4438. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  4439. trimble_t *t = parse->localdata;
  4440. u_char buffer[256];
  4441. struct txbuf buf;
  4442. buf.txt = buffer;
  4443. if (t)
  4444. {
  4445. if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
  4446. (void)trimbletsip_setup(parse, "message timeout");
  4447. }
  4448. poll_poll(parse->peer); /* emit query string and re-arm timer */
  4449. if (t && t->qtracking)
  4450. {
  4451. u_long oldsats = t->ltrack & ~t->ctrack;
  4452. t->qtracking = 0;
  4453. t->ltrack = t->ctrack;
  4454. if (oldsats)
  4455. {
  4456. int i;
  4457. for (i = 0; oldsats; i++) {
  4458. if (oldsats & (1 << i))
  4459. {
  4460. sendcmd(&buf, CMD_CSTATTRACK);
  4461. sendbyte(&buf, i+1); /* old sat */
  4462. sendetx(&buf, parse);
  4463. }
  4464. oldsats &= ~(1 << i);
  4465. }
  4466. }
  4467. sendcmd(&buf, CMD_CSTATTRACK);
  4468. sendbyte(&buf, 0x00); /* current tracking set */
  4469. sendetx(&buf, parse);
  4470. }
  4471. }
  4472. /*--------------------------------------------------
  4473. * TRIMBLE TSIP end routine
  4474. */
  4475. static void
  4476. trimbletsip_end(
  4477. struct parseunit *parse
  4478. )
  4479. { trimble_t *t = parse->localdata;
  4480. if (t)
  4481. {
  4482. free(t);
  4483. parse->localdata = (void *)0;
  4484. }
  4485. parse->peer->nextaction = 0;
  4486. parse->peer->action = (void (*) P((struct peer *)))0;
  4487. }
  4488. /*--------------------------------------------------
  4489. * TRIMBLE TSIP init routine
  4490. */
  4491. static int
  4492. trimbletsip_init(
  4493. struct parseunit *parse
  4494. )
  4495. {
  4496. #if defined(VEOL) || defined(VEOL2)
  4497. #ifdef HAVE_TERMIOS
  4498. struct termios tio; /* NEEDED FOR A LONG TIME ! */
  4499. #endif
  4500. #ifdef HAVE_SYSV_TTYS
  4501. struct termio tio; /* NEEDED FOR A LONG TIME ! */
  4502. #endif
  4503. /*
  4504. * allocate local data area
  4505. */
  4506. if (!parse->localdata)
  4507. {
  4508. trimble_t *t;
  4509. t = (trimble_t *)(parse->localdata = emalloc(sizeof(trimble_t)));
  4510. if (t)
  4511. {
  4512. memset((char *)t, 0, sizeof(trimble_t));
  4513. t->last_msg = current_time;
  4514. }
  4515. }
  4516. parse->peer->action = trimble_check;
  4517. parse->peer->nextaction = current_time;
  4518. /*
  4519. * configure terminal line for ICANON mode with VEOL characters
  4520. */
  4521. if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
  4522. {
  4523. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcgetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
  4524. return 0;
  4525. }
  4526. else
  4527. {
  4528. if ((parse_clockinfo[CLK_TYPE(parse->peer)].cl_lflag & ICANON))
  4529. {
  4530. #ifdef VEOL
  4531. tio.c_cc[VEOL] = ETX;
  4532. #endif
  4533. #ifdef VEOL2
  4534. tio.c_cc[VEOL2] = DLE;
  4535. #endif
  4536. }
  4537. if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
  4538. {
  4539. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcsetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
  4540. return 0;
  4541. }
  4542. }
  4543. #endif
  4544. return trimbletsip_setup(parse, "initial startup");
  4545. }
  4546. /*------------------------------------------------------------
  4547. * trimbletsip_event - handle Trimble events
  4548. * simple evente handler - attempt to re-initialize receiver
  4549. */
  4550. static void
  4551. trimbletsip_event(
  4552. struct parseunit *parse,
  4553. int event
  4554. )
  4555. {
  4556. switch (event)
  4557. {
  4558. case CEVNT_BADREPLY: /* reset on garbled input */
  4559. case CEVNT_TIMEOUT: /* reset on no input */
  4560. (void)trimbletsip_setup(parse, "event BAD_REPLY/TIMEOUT");
  4561. break;
  4562. default: /* ignore */
  4563. break;
  4564. }
  4565. }
  4566. /*
  4567. * getflt, getint convert fields in the incoming data into the
  4568. * appropriate type of item
  4569. *
  4570. * CAVEAT: these routines are currently definitely byte order dependent
  4571. * and assume Representation(float) == IEEE754
  4572. * These functions MUST be converted to portable versions (especially
  4573. * converting the float representation into ntp_fp formats in order
  4574. * to avoid floating point operations at all!
  4575. */
  4576. static float
  4577. getflt(
  4578. u_char *bp
  4579. )
  4580. {
  4581. union uval uval;
  4582. #ifdef WORDS_BIGENDIAN
  4583. uval.bd[0] = *bp++;
  4584. uval.bd[1] = *bp++;
  4585. uval.bd[2] = *bp++;
  4586. uval.bd[3] = *bp;
  4587. #else /* ! WORDS_BIGENDIAN */
  4588. uval.bd[3] = *bp++;
  4589. uval.bd[2] = *bp++;
  4590. uval.bd[1] = *bp++;
  4591. uval.bd[0] = *bp;
  4592. #endif /* ! WORDS_BIGENDIAN */
  4593. return uval.fv;
  4594. }
  4595. static double
  4596. getdbl(
  4597. u_char *bp
  4598. )
  4599. {
  4600. union uval uval;
  4601. #ifdef WORDS_BIGENDIAN
  4602. uval.bd[0] = *bp++;
  4603. uval.bd[1] = *bp++;
  4604. uval.bd[2] = *bp++;
  4605. uval.bd[3] = *bp++;
  4606. uval.bd[4] = *bp++;
  4607. uval.bd[5] = *bp++;
  4608. uval.bd[6] = *bp++;
  4609. uval.bd[7] = *bp;
  4610. #else /* ! WORDS_BIGENDIAN */
  4611. uval.bd[7] = *bp++;
  4612. uval.bd[6] = *bp++;
  4613. uval.bd[5] = *bp++;
  4614. uval.bd[4] = *bp++;
  4615. uval.bd[3] = *bp++;
  4616. uval.bd[2] = *bp++;
  4617. uval.bd[1] = *bp++;
  4618. uval.bd[0] = *bp;
  4619. #endif /* ! WORDS_BIGENDIAN */
  4620. return uval.dv;
  4621. }
  4622. static int
  4623. getshort(
  4624. unsigned char *p
  4625. )
  4626. {
  4627. return get_msb_short(&p);
  4628. }
  4629. /*--------------------------------------------------
  4630. * trimbletsip_message - process trimble messages
  4631. */
  4632. #define RTOD (180.0 / 3.1415926535898)
  4633. #define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
  4634. static void
  4635. trimbletsip_message(
  4636. struct parseunit *parse,
  4637. parsetime_t *parsetime
  4638. )
  4639. {
  4640. unsigned char *buffer = parsetime->parse_msg;
  4641. unsigned int size = parsetime->parse_msglen;
  4642. if ((size < 4) ||
  4643. (buffer[0] != DLE) ||
  4644. (buffer[size-1] != ETX) ||
  4645. (buffer[size-2] != DLE))
  4646. {
  4647. #ifdef DEBUG
  4648. if (debug > 2) {
  4649. int i;
  4650. printf("TRIMBLE BAD packet, size %d:\n ", size);
  4651. for (i = 0; i < size; i++) {
  4652. printf ("%2.2x, ", buffer[i]&0xff);
  4653. if (i%16 == 15) printf("\n\t");
  4654. }
  4655. printf("\n");
  4656. }
  4657. #endif
  4658. return;
  4659. }
  4660. else
  4661. {
  4662. int var_flag;
  4663. trimble_t *tr = parse->localdata;
  4664. unsigned int cmd = buffer[1];
  4665. char pbuffer[200];
  4666. char *t = pbuffer;
  4667. cmd_info_t *s;
  4668. #ifdef DEBUG
  4669. if (debug > 3) {
  4670. int i;
  4671. printf("TRIMBLE packet 0x%02x, size %d:\n ", cmd, size);
  4672. for (i = 0; i < size; i++) {
  4673. printf ("%2.2x, ", buffer[i]&0xff);
  4674. if (i%16 == 15) printf("\n\t");
  4675. }
  4676. printf("\n");
  4677. }
  4678. #endif
  4679. if (tr)
  4680. tr->last_msg = current_time;
  4681. s = trimble_convert(cmd, trimble_rcmds);
  4682. if (s)
  4683. {
  4684. snprintf(t, BUFFER_SIZE(pbuffer, t), "%s=\"", s->varname);
  4685. }
  4686. else
  4687. {
  4688. DPRINTF(1, ("TRIMBLE UNKNOWN COMMAND 0x%02x\n", cmd));
  4689. return;
  4690. }
  4691. var_flag = s->varmode;
  4692. t += strlen(t);
  4693. switch(cmd)
  4694. {
  4695. case CMD_RCURTIME:
  4696. snprintf(t, BUFFER_SIZE(pbuffer, t), "%f, %d, %f",
  4697. getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
  4698. getflt((unsigned char *)&mb(6)));
  4699. break;
  4700. case CMD_RBEST4:
  4701. strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
  4702. t += strlen(t);
  4703. switch (mb(0) & 0xF)
  4704. {
  4705. default:
  4706. snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
  4707. break;
  4708. case 1:
  4709. strncpy(t, "0D", BUFFER_SIZE(pbuffer, t));
  4710. break;
  4711. case 3:
  4712. strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
  4713. break;
  4714. case 4:
  4715. strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
  4716. break;
  4717. }
  4718. t += strlen(t);
  4719. if (mb(0) & 0x10)
  4720. strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
  4721. else
  4722. strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
  4723. t += strlen(t);
  4724. snprintf(t, BUFFER_SIZE(pbuffer, t), "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
  4725. mb(1), mb(2), mb(3), mb(4),
  4726. getflt((unsigned char *)&mb(5)),
  4727. getflt((unsigned char *)&mb(9)),
  4728. getflt((unsigned char *)&mb(13)),
  4729. getflt((unsigned char *)&mb(17)));
  4730. break;
  4731. case CMD_RVERSION:
  4732. snprintf(t, BUFFER_SIZE(pbuffer, t), "%d.%d (%d/%d/%d)",
  4733. mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
  4734. break;
  4735. case CMD_RRECVHEALTH:
  4736. {
  4737. static const char *msgs[] =
  4738. {
  4739. "Battery backup failed",
  4740. "Signal processor error",
  4741. "Alignment error, channel or chip 1",
  4742. "Alignment error, channel or chip 2",
  4743. "Antenna feed line fault",
  4744. "Excessive ref freq. error",
  4745. "<BIT 6>",
  4746. "<BIT 7>"
  4747. };
  4748. int i, bits;
  4749. switch (mb(0) & 0xFF)
  4750. {
  4751. default:
  4752. snprintf(t, BUFFER_SIZE(pbuffer, t), "illegal value 0x%02x", mb(0) & 0xFF);
  4753. break;
  4754. case 0x00:
  4755. strncpy(t, "doing position fixes", BUFFER_SIZE(pbuffer, t));
  4756. break;
  4757. case 0x01:
  4758. strncpy(t, "no GPS time yet", BUFFER_SIZE(pbuffer, t));
  4759. break;
  4760. case 0x03:
  4761. strncpy(t, "PDOP too high", BUFFER_SIZE(pbuffer, t));
  4762. break;
  4763. case 0x08:
  4764. strncpy(t, "no usable satellites", BUFFER_SIZE(pbuffer, t));
  4765. break;
  4766. case 0x09:
  4767. strncpy(t, "only ONE usable satellite", BUFFER_SIZE(pbuffer, t));
  4768. break;
  4769. case 0x0A:
  4770. strncpy(t, "only TWO usable satellites", BUFFER_SIZE(pbuffer, t));
  4771. break;
  4772. case 0x0B:
  4773. strncpy(t, "only THREE usable satellites", BUFFER_SIZE(pbuffer, t));
  4774. break;
  4775. case 0x0C:
  4776. strncpy(t, "the chosen satellite is unusable", BUFFER_SIZE(pbuffer, t));
  4777. break;
  4778. }
  4779. t += strlen(t);
  4780. bits = mb(1) & 0xFF;
  4781. for (i = 0; i < 8; i++)
  4782. if (bits & (0x1<<i))
  4783. {
  4784. snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
  4785. t += strlen(t);
  4786. }
  4787. }
  4788. break;
  4789. case CMD_RMESSAGE:
  4790. mkreadable(t, (int)BUFFER_SIZE(pbuffer, t), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
  4791. break;
  4792. case CMD_RMACHSTAT:
  4793. {
  4794. static const char *msgs[] =
  4795. {
  4796. "Synthesizer Fault",
  4797. "Battery Powered Time Clock Fault",
  4798. "A-to-D Converter Fault",
  4799. "The almanac stored in the receiver is not complete and current",
  4800. "<BIT 4>",
  4801. "<BIT 5",
  4802. "<BIT 6>",
  4803. "<BIT 7>"
  4804. };
  4805. int i, bits;
  4806. snprintf(t, BUFFER_SIZE(pbuffer, t), "machine id 0x%02x", mb(0) & 0xFF);
  4807. t += strlen(t);
  4808. bits = mb(1) & 0xFF;
  4809. for (i = 0; i < 8; i++)
  4810. if (bits & (0x1<<i))
  4811. {
  4812. snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
  4813. t += strlen(t);
  4814. }
  4815. snprintf(t, BUFFER_SIZE(pbuffer, t), ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
  4816. }
  4817. break;
  4818. case CMD_ROPERPARAM:
  4819. snprintf(t, BUFFER_SIZE(pbuffer, t), "%2x %.1f %.1f %.1f %.1f",
  4820. mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
  4821. getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
  4822. break;
  4823. case CMD_RUTCPARAM:
  4824. {
  4825. float t0t = getflt((unsigned char *)&mb(14));
  4826. short wnt = getshort((unsigned char *)&mb(18));
  4827. short dtls = getshort((unsigned char *)&mb(12));
  4828. short wnlsf = getshort((unsigned char *)&mb(20));
  4829. short dn = getshort((unsigned char *)&mb(22));
  4830. short dtlsf = getshort((unsigned char *)&mb(24));
  4831. if ((int)t0t != 0)
  4832. {
  4833. mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf, BUFFER_SIZE(pbuffer, t));
  4834. }
  4835. else
  4836. {
  4837. strncpy(t, "<NO UTC DATA>", BUFFER_SIZE(pbuffer, t));
  4838. }
  4839. }
  4840. break;
  4841. case CMD_RSAT1BIAS:
  4842. snprintf(t, BUFFER_SIZE(pbuffer, t), "%.1fm %.2fm/s at %.1fs",
  4843. getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
  4844. break;
  4845. case CMD_RIOOPTIONS:
  4846. {
  4847. snprintf(t, BUFFER_SIZE(pbuffer, t), "%02x %02x %02x %02x",
  4848. mb(0), mb(1), mb(2), mb(3));
  4849. if (mb(0) != TRIM_POS_OPT ||
  4850. mb(2) != TRIM_TIME_OPT)
  4851. {
  4852. (void)trimbletsip_setup(parse, "bad io options");
  4853. }
  4854. }
  4855. break;
  4856. case CMD_RSPOSXYZ:
  4857. {
  4858. double x = getflt((unsigned char *)&mb(0));
  4859. double y = getflt((unsigned char *)&mb(4));
  4860. double z = getflt((unsigned char *)&mb(8));
  4861. double f = getflt((unsigned char *)&mb(12));
  4862. if (f > 0.0)
  4863. snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
  4864. x, y, z,
  4865. f);
  4866. else
  4867. return;
  4868. }
  4869. break;
  4870. case CMD_RSLLAPOS:
  4871. {
  4872. double lat = getflt((unsigned char *)&mb(0));
  4873. double lng = getflt((unsigned char *)&mb(4));
  4874. double f = getflt((unsigned char *)&mb(12));
  4875. if (f > 0.0)
  4876. snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, long %f %c, alt %.2fm",
  4877. ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
  4878. ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
  4879. getflt((unsigned char *)&mb(8)));
  4880. else
  4881. return;
  4882. }
  4883. break;
  4884. case CMD_RDOUBLEXYZ:
  4885. {
  4886. double x = getdbl((unsigned char *)&mb(0));
  4887. double y = getdbl((unsigned char *)&mb(8));
  4888. double z = getdbl((unsigned char *)&mb(16));
  4889. snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm",
  4890. x, y, z);
  4891. }
  4892. break;
  4893. case CMD_RDOUBLELLA:
  4894. {
  4895. double lat = getdbl((unsigned char *)&mb(0));
  4896. double lng = getdbl((unsigned char *)&mb(8));
  4897. snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, lon %f %c, alt %.2fm",
  4898. ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
  4899. ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
  4900. getdbl((unsigned char *)&mb(16)));
  4901. }
  4902. break;
  4903. case CMD_RALLINVIEW:
  4904. {
  4905. int i, sats;
  4906. strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
  4907. t += strlen(t);
  4908. switch (mb(0) & 0x7)
  4909. {
  4910. default:
  4911. snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
  4912. break;
  4913. case 3:
  4914. strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
  4915. break;
  4916. case 4:
  4917. strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
  4918. break;
  4919. }
  4920. t += strlen(t);
  4921. if (mb(0) & 0x8)
  4922. strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
  4923. else
  4924. strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
  4925. t += strlen(t);
  4926. sats = (mb(0)>>4) & 0xF;
  4927. snprintf(t, BUFFER_SIZE(pbuffer, t), "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
  4928. getflt((unsigned char *)&mb(1)),
  4929. getflt((unsigned char *)&mb(5)),
  4930. getflt((unsigned char *)&mb(9)),
  4931. getflt((unsigned char *)&mb(13)),
  4932. sats, (sats == 1) ? "" : "s");
  4933. t += strlen(t);
  4934. for (i=0; i < sats; i++)
  4935. {
  4936. snprintf(t, BUFFER_SIZE(pbuffer, t), "%s%02d", i ? ", " : "", mb(17+i));
  4937. t += strlen(t);
  4938. if (tr)
  4939. tr->ctrack |= (1 << (mb(17+i)-1));
  4940. }
  4941. if (tr)
  4942. { /* mark for tracking status query */
  4943. tr->qtracking = 1;
  4944. }
  4945. }
  4946. break;
  4947. case CMD_RSTATTRACK:
  4948. {
  4949. snprintf(t-2, BUFFER_SIZE(pbuffer, t-2), "[%02d]=\"", mb(0)); /* add index to var name */
  4950. t += strlen(t);
  4951. if (getflt((unsigned char *)&mb(4)) < 0.0)
  4952. {
  4953. strncpy(t, "<NO MEASUREMENTS>", BUFFER_SIZE(pbuffer, t));
  4954. var_flag &= ~DEF;
  4955. }
  4956. else
  4957. {
  4958. snprintf(t, BUFFER_SIZE(pbuffer, t), "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
  4959. (mb(1) & 0xFF)>>3,
  4960. mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
  4961. mb(3),
  4962. getflt((unsigned char *)&mb(4)),
  4963. getflt((unsigned char *)&mb(12)) * RTOD,
  4964. getflt((unsigned char *)&mb(16)) * RTOD);
  4965. t += strlen(t);
  4966. if (mb(20))
  4967. {
  4968. var_flag &= ~DEF;
  4969. strncpy(t, ", OLD", BUFFER_SIZE(pbuffer, t));
  4970. }
  4971. t += strlen(t);
  4972. if (mb(22))
  4973. {
  4974. if (mb(22) == 1)
  4975. strncpy(t, ", BAD PARITY", BUFFER_SIZE(pbuffer, t));
  4976. else
  4977. if (mb(22) == 2)
  4978. strncpy(t, ", BAD EPH HEALTH", BUFFER_SIZE(pbuffer, t));
  4979. }
  4980. t += strlen(t);
  4981. if (mb(23))
  4982. strncpy(t, ", collecting data", BUFFER_SIZE(pbuffer, t));
  4983. }
  4984. }
  4985. break;
  4986. default:
  4987. strncpy(t, "<UNDECODED>", BUFFER_SIZE(pbuffer, t));
  4988. break;
  4989. }
  4990. t += strlen(t);
  4991. strncpy(t,"\"", BUFFER_SIZE(pbuffer, t));
  4992. set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
  4993. }
  4994. }
  4995. /**============================================================
  4996. ** RAWDCF support
  4997. **/
  4998. /*--------------------------------------------------
  4999. * rawdcf_init_1 - set up modem lines for RAWDCF receivers
  5000. * SET DTR line
  5001. */
  5002. #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
  5003. static int
  5004. rawdcf_init_1(
  5005. struct parseunit *parse
  5006. )
  5007. {
  5008. /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
  5009. /*
  5010. * You can use the RS232 to supply the power for a DCF77 receiver.
  5011. * Here a voltage between the DTR and the RTS line is used. Unfortunately
  5012. * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
  5013. */
  5014. int sl232;
  5015. if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
  5016. {
  5017. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
  5018. return 0;
  5019. }
  5020. #ifdef TIOCM_DTR
  5021. sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR; /* turn on DTR, clear RTS for power supply */
  5022. #else
  5023. sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR; /* turn on DTR, clear RTS for power supply */
  5024. #endif
  5025. if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
  5026. {
  5027. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
  5028. }
  5029. return 0;
  5030. }
  5031. #else
  5032. static int
  5033. rawdcfdtr_init_1(
  5034. struct parseunit *parse
  5035. )
  5036. {
  5037. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer));
  5038. return 0;
  5039. }
  5040. #endif /* DTR initialisation type */
  5041. /*--------------------------------------------------
  5042. * rawdcf_init_2 - set up modem lines for RAWDCF receivers
  5043. * CLR DTR line, SET RTS line
  5044. */
  5045. #if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS))
  5046. static int
  5047. rawdcf_init_2(
  5048. struct parseunit *parse
  5049. )
  5050. {
  5051. /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
  5052. /*
  5053. * You can use the RS232 to supply the power for a DCF77 receiver.
  5054. * Here a voltage between the DTR and the RTS line is used. Unfortunately
  5055. * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
  5056. */
  5057. int sl232;
  5058. if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
  5059. {
  5060. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
  5061. return 0;
  5062. }
  5063. #ifdef TIOCM_RTS
  5064. sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS; /* turn on RTS, clear DTR for power supply */
  5065. #else
  5066. sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS; /* turn on RTS, clear DTR for power supply */
  5067. #endif
  5068. if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
  5069. {
  5070. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
  5071. }
  5072. return 0;
  5073. }
  5074. #else
  5075. static int
  5076. rawdcf_init_2(
  5077. struct parseunit *parse
  5078. )
  5079. {
  5080. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer));
  5081. return 0;
  5082. }
  5083. #endif /* DTR initialisation type */
  5084. #else /* defined(REFCLOCK) && defined(PARSE) */
  5085. int refclock_parse_bs;
  5086. #endif /* defined(REFCLOCK) && defined(PARSE) */
  5087. /*
  5088. * History:
  5089. *
  5090. * refclock_parse.c,v
  5091. * Revision 4.80 2007/08/11 12:06:29 kardel
  5092. * update comments wrt/ to PPS
  5093. *
  5094. * Revision 4.79 2007/08/11 11:52:23 kardel
  5095. * - terminate io bindings before io_closeclock() will close our file descriptor
  5096. *
  5097. * Revision 4.78 2006/12/22 20:08:27 kardel
  5098. * Bug 746 (RFE): add configuration for Expert mouseCLOCK USB v2.0 as mode 19
  5099. *
  5100. * Revision 4.77 2006/08/05 07:44:49 kardel
  5101. * support optionally separate PPS devices via /dev/refclockpps-{0..3}
  5102. *
  5103. * Revision 4.76 2006/06/22 18:40:47 kardel
  5104. * clean up signedness (gcc 4)
  5105. *
  5106. * Revision 4.75 2006/06/22 16:58:10 kardel
  5107. * Bug #632: call parse_ppsapi() in parse_ctl() when updating
  5108. * the PPS offset. Fix sign of offset passed to kernel.
  5109. *
  5110. * Revision 4.74 2006/06/18 21:18:37 kardel
  5111. * NetBSD Coverity CID 3796: possible NULL deref
  5112. *
  5113. * Revision 4.73 2006/05/26 14:23:46 kardel
  5114. * cleanup of copyright info
  5115. *
  5116. * Revision 4.72 2006/05/26 14:19:43 kardel
  5117. * cleanup of ioctl cruft
  5118. *
  5119. * Revision 4.71 2006/05/26 14:15:57 kardel
  5120. * delay adding refclock to async refclock io after all initializations
  5121. *
  5122. * Revision 4.70 2006/05/25 18:20:50 kardel
  5123. * bug #619
  5124. * terminate parse io engine after de-registering
  5125. * from refclock io engine
  5126. *
  5127. * Revision 4.69 2006/05/25 17:28:02 kardel
  5128. * complete refclock io structure initialization *before* inserting it into the
  5129. * refclock input machine (avoids null pointer deref) (bug #619)
  5130. *
  5131. * Revision 4.68 2006/05/01 17:02:51 kardel
  5132. * copy receiver method also for newlwy created receive buffers
  5133. *
  5134. * Revision 4.67 2006/05/01 14:37:29 kardel
  5135. * If an input buffer parses into more than one message do insert the
  5136. * parsed message in a new input buffer instead of processing it
  5137. * directly. This avoids deed complicated processing in signal
  5138. * handling.
  5139. *
  5140. * Revision 4.66 2006/03/18 00:45:30 kardel
  5141. * coverity fixes found in NetBSD coverity scan
  5142. *
  5143. * Revision 4.65 2006/01/26 06:08:33 kardel
  5144. * output errno on PPS setup failure
  5145. *
  5146. * Revision 4.64 2005/11/09 20:44:47 kardel
  5147. * utilize full PPS timestamp resolution from PPS API
  5148. *
  5149. * Revision 4.63 2005/10/07 22:10:25 kardel
  5150. * bounded buffer implementation
  5151. *
  5152. * Revision 4.62.2.2 2005/09/25 10:20:16 kardel
  5153. * avoid unexpected buffer overflows due to sprintf("%f") on strange floats:
  5154. * replace almost all str* and *printf functions be their buffer bounded
  5155. * counterparts
  5156. *
  5157. * Revision 4.62.2.1 2005/08/27 16:19:27 kardel
  5158. * limit re-set rate of trimble clocks
  5159. *
  5160. * Revision 4.62 2005/08/06 17:40:00 kardel
  5161. * cleanup size handling wrt/ to buffer boundaries
  5162. *
  5163. * Revision 4.61 2005/07/27 21:16:19 kardel
  5164. * fix a long (> 11 years) misconfiguration wrt/ Meinberg cflag factory
  5165. * default setup. CSTOPB was missing for the 7E2 default data format of
  5166. * the DCF77 clocks.
  5167. *
  5168. * Revision 4.60 2005/07/17 21:14:44 kardel
  5169. * change contents of version string to include the RCS/CVS Id
  5170. *
  5171. * Revision 4.59 2005/07/06 06:56:38 kardel
  5172. * syntax error
  5173. *
  5174. * Revision 4.58 2005/07/04 13:10:40 kardel
  5175. * fix bug 455: tripping over NULL pointer on cleanup
  5176. * fix shadow storage logic for ppsphaseadjust and trustime wrt/ time2
  5177. * fix compiler warnings for some platforms wrt/ printf formatstrings and
  5178. * varying structure element sizes
  5179. * reorder assignment in binding to avoid tripping over NULL pointers
  5180. *
  5181. * Revision 4.57 2005/06/25 09:25:19 kardel
  5182. * sort out log output sequence
  5183. *
  5184. * Revision 4.56 2005/06/14 21:47:27 kardel
  5185. * collect samples only if samples are ok (sync or trusted flywheel)
  5186. * propagate pps phase adjustment value to kernel via PPSAPI to help HARDPPS
  5187. * en- and dis-able HARDPPS in correlation to receiver sync state
  5188. *
  5189. * Revision 4.55 2005/06/02 21:28:31 kardel
  5190. * clarify trust logic
  5191. *
  5192. * Revision 4.54 2005/06/02 17:06:49 kardel
  5193. * change status reporting to use fixed refclock_report()
  5194. *
  5195. * Revision 4.53 2005/06/02 16:33:31 kardel
  5196. * fix acceptance of clocks unsync clocks right at start
  5197. *
  5198. * Revision 4.52 2005/05/26 21:55:06 kardel
  5199. * cleanup status reporting
  5200. *
  5201. * Revision 4.51 2005/05/26 19:19:14 kardel
  5202. * implement fast refclock startup
  5203. *
  5204. * Revision 4.50 2005/04/16 20:51:35 kardel
  5205. * set pps_enable = 1 when binding a kernel PPS source
  5206. *
  5207. * Revision 4.49 2005/04/16 17:29:26 kardel
  5208. * add non polling clock type 18 for just listenning to Meinberg clocks
  5209. *
  5210. * Revision 4.48 2005/04/16 16:22:27 kardel
  5211. * bk sync 20050415 ntp-dev
  5212. *
  5213. * Revision 4.47 2004/11/29 10:42:48 kardel
  5214. * bk sync ntp-dev 20041129
  5215. *
  5216. * Revision 4.46 2004/11/29 10:26:29 kardel
  5217. * keep fudgetime2 in sync with trusttime/ppsphaseadjust depending in flag1
  5218. *
  5219. * Revision 4.45 2004/11/14 20:53:20 kardel
  5220. * clear PPS flags after using them
  5221. *
  5222. * Revision 4.44 2004/11/14 15:29:41 kardel
  5223. * support PPSAPI, upgrade Copyright to Berkeley style
  5224. *
  5225. * Revision 4.43 2001/05/26 22:53:16 kardel
  5226. * 20010526 reconcilation
  5227. *
  5228. * Revision 4.42 2000/05/14 15:31:51 kardel
  5229. * PPSAPI && RAWDCF modemline support
  5230. *
  5231. * Revision 4.41 2000/04/09 19:50:45 kardel
  5232. * fixed rawdcfdtr_init() -> rawdcf_init_1
  5233. *
  5234. * Revision 4.40 2000/04/09 15:27:55 kardel
  5235. * modem line fiddle in rawdcf_init_2
  5236. *
  5237. * Revision 4.39 2000/03/18 09:16:55 kardel
  5238. * PPSAPI integration
  5239. *
  5240. * Revision 4.38 2000/03/05 20:25:06 kardel
  5241. * support PPSAPI
  5242. *
  5243. * Revision 4.37 2000/03/05 20:11:14 kardel
  5244. * 4.0.99g reconcilation
  5245. *
  5246. * Revision 4.36 1999/11/28 17:18:20 kardel
  5247. * disabled burst mode
  5248. *
  5249. * Revision 4.35 1999/11/28 09:14:14 kardel
  5250. * RECON_4_0_98F
  5251. *
  5252. * Revision 4.34 1999/05/14 06:08:05 kardel
  5253. * store current_time in a suitable container (u_long)
  5254. *
  5255. * Revision 4.33 1999/05/13 21:48:38 kardel
  5256. * double the no response timeout interval
  5257. *
  5258. * Revision 4.32 1999/05/13 20:09:13 kardel
  5259. * complain only about missing polls after a full poll interval
  5260. *
  5261. * Revision 4.31 1999/05/13 19:59:32 kardel
  5262. * add clock type 16 for RTS set DTR clr in RAWDCF
  5263. *
  5264. * Revision 4.30 1999/02/28 20:36:43 kardel
  5265. * fixed printf fmt
  5266. *
  5267. * Revision 4.29 1999/02/28 19:58:23 kardel
  5268. * updated copyright information
  5269. *
  5270. * Revision 4.28 1999/02/28 19:01:50 kardel
  5271. * improved debug out on sent Meinberg messages
  5272. *
  5273. * Revision 4.27 1999/02/28 18:05:55 kardel
  5274. * no linux/ppsclock.h stuff
  5275. *
  5276. * Revision 4.26 1999/02/28 15:27:27 kardel
  5277. * wharton clock integration
  5278. *
  5279. * Revision 4.25 1999/02/28 14:04:46 kardel
  5280. * added missing double quotes to UTC information string
  5281. *
  5282. * Revision 4.24 1999/02/28 12:06:50 kardel
  5283. * (parse_control): using gmprettydate instead of prettydate()
  5284. * (mk_utcinfo): new function for formatting GPS derived UTC information
  5285. * (gps16x_message): changed to use mk_utcinfo()
  5286. * (trimbletsip_message): changed to use mk_utcinfo()
  5287. * ignoring position information in unsynchronized mode
  5288. * (parse_start): augument linux support for optional ASYNC_LOW_LATENCY
  5289. *
  5290. * Revision 4.23 1999/02/23 19:47:53 kardel
  5291. * fixed #endifs
  5292. * (stream_receive): fixed formats
  5293. *
  5294. * Revision 4.22 1999/02/22 06:21:02 kardel
  5295. * use new autoconfig symbols
  5296. *
  5297. * Revision 4.21 1999/02/21 12:18:13 kardel
  5298. * 4.91f reconcilation
  5299. *
  5300. * Revision 4.20 1999/02/21 10:53:36 kardel
  5301. * initial Linux PPSkit version
  5302. *
  5303. * Revision 4.19 1999/02/07 09:10:45 kardel
  5304. * clarify STREAMS mitigation rules in comment
  5305. *
  5306. * Revision 4.18 1998/12/20 23:45:34 kardel
  5307. * fix types and warnings
  5308. *
  5309. * Revision 4.17 1998/11/15 21:24:51 kardel
  5310. * cannot access mbg_ routines when CLOCK_MEINBERG
  5311. * is not defined
  5312. *
  5313. * Revision 4.16 1998/11/15 20:28:17 kardel
  5314. * Release 4.0.73e13 reconcilation
  5315. *
  5316. * Revision 4.15 1998/08/22 21:56:08 kardel
  5317. * fixed IO handling for non-STREAM IO
  5318. *
  5319. * Revision 4.14 1998/08/16 19:00:48 kardel
  5320. * (gps16x_message): reduced UTC parameter information (dropped A0,A1)
  5321. * made uval a local variable (killed one of the last globals)
  5322. * (sendetx): added logging of messages when in debug mode
  5323. * (trimble_check): added periodic checks to facilitate re-initialization
  5324. * (trimbletsip_init): made use of EOL character if in non-kernel operation
  5325. * (trimbletsip_message): extended message interpretation
  5326. * (getdbl): fixed data conversion
  5327. *
  5328. * Revision 4.13 1998/08/09 22:29:13 kardel
  5329. * Trimble TSIP support
  5330. *
  5331. * Revision 4.12 1998/07/11 10:05:34 kardel
  5332. * Release 4.0.73d reconcilation
  5333. *
  5334. * Revision 4.11 1998/06/14 21:09:42 kardel
  5335. * Sun acc cleanup
  5336. *
  5337. * Revision 4.10 1998/06/13 12:36:45 kardel
  5338. * signed/unsigned, name clashes
  5339. *
  5340. * Revision 4.9 1998/06/12 15:30:00 kardel
  5341. * prototype fixes
  5342. *
  5343. * Revision 4.8 1998/06/12 11:19:42 kardel
  5344. * added direct input processing routine for refclocks in
  5345. * order to avaiod that single character io gobbles up all
  5346. * receive buffers and drops input data. (Problem started
  5347. * with fast machines so a character a buffer was possible
  5348. * one of the few cases where faster machines break existing
  5349. * allocation algorithms)
  5350. *
  5351. * Revision 4.7 1998/06/06 18:35:20 kardel
  5352. * (parse_start): added BURST mode initialisation
  5353. *
  5354. * Revision 4.6 1998/05/27 06:12:46 kardel
  5355. * RAWDCF_BASEDELAY default added
  5356. * old comment removed
  5357. * casts for ioctl()
  5358. *
  5359. * Revision 4.5 1998/05/25 22:05:09 kardel
  5360. * RAWDCF_SETDTR option removed
  5361. * clock type 14 attempts to set DTR for
  5362. * power supply of RAWDCF receivers
  5363. *
  5364. * Revision 4.4 1998/05/24 16:20:47 kardel
  5365. * updated comments referencing Meinberg clocks
  5366. * added RAWDCF clock with DTR set option as type 14
  5367. *
  5368. * Revision 4.3 1998/05/24 10:48:33 kardel
  5369. * calibrated CONRAD RAWDCF default fudge factor
  5370. *
  5371. * Revision 4.2 1998/05/24 09:59:35 kardel
  5372. * corrected version information (ntpq support)
  5373. *
  5374. * Revision 4.1 1998/05/24 09:52:31 kardel
  5375. * use fixed format only (new IO model)
  5376. * output debug to stdout instead of msyslog()
  5377. * don't include >"< in ASCII output in order not to confuse
  5378. * ntpq parsing
  5379. *
  5380. * Revision 4.0 1998/04/10 19:52:11 kardel
  5381. * Start 4.0 release version numbering
  5382. *
  5383. * Revision 1.2 1998/04/10 19:28:04 kardel
  5384. * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
  5385. * derived from 3.105.1.2 from V3 tree
  5386. *
  5387. * Revision information 3.1 - 3.105 from log deleted 1998/04/10 kardel
  5388. *
  5389. */